class KAssistantPage {
	KAssistantPage (QWidget *pageWidget, const QString &caption);

	void setAppropriate (bool);
	void isAppropriate ();
	void setValid (bool);
	void isValid ();

protected:
	virtual QWidget *widget ();
	virtual bool isGroup () { return false };
};

class KAssistantPageGroup : public KAssistantPage {
	/** @param caption might be used in the step list to display a caption for the whole group.
	If the caption parameter is omitted, instead the captions of the child pages would be shown,
	the grouping would be invisible to the end user */
	KAssistantPageGroup (const QString &caption=QString());
	/** might be obsolete, as this could also be done via a "parent" argument in the KAssistantPage(Group) constructor */
	void addPage (KAssistantPage *page);
	/** Is there at least one more appropriate page to show in this group (recurses into child groups, but not parent groups)? */
	bool haveNextPageToShow ();
	/** Is there at least one previous appropriate page to show in this group (recurses into child groups, but not parent groups)? */
	bool havePrevPageToShow ();
	/** recurses into child groups, but not parent groups */
	virtual void nextPage ();
	/** recurses into child groups, but not parent groups */
	virtual void prevPage ();
	/** only meaningful, if the group itself or one of it's children are current */
	KAsstistantPage *currentPage ();
protected:
	/** reimplemented to return null, as this is a group, not a single page */
	void *widget ();
	bool isGroup () { return true };
};

class KAssistantDialog : public KAssistantPageGroup, public KDialog {
	KAssistantDialog (QWidget *parent);

	/** reimplemented from KAssistantPageGroup to call accept () if on the last appropriate page */
	void nextPage ();
};

Use examples:

// simple fixed order with one page disabled by default
KAssistantPage *optional_page;

dialog = new KAssistantDialog (0);
dialog->addPage (new KAssistantPage (page1Widget, i18n ("First page")));
dialog->addPage (new KAssistantPage (page2Widget, i18n ("Second page")));
dialog->addPage (optional_page = new KAssistantPage (page3Widget, i18n ("Third page")));
dialog->addPage (new KAssistantPage (page4Widget, i18n ("Last page")));
optional_page->setAppropriate (false);


// separate alternative paths, path B disabled by default
dialog = new KAssistantDialog (0);

KAssistantPageGroup *pathA = new KAssistantPageGroup (i18n ("path a"));
pathA->addPage (new KAssistantPage (page2aWidget, i18n ("page 2a")));
pathA->addPage (new KAssistantPage (page3aWidget, i18n ("page 3a")));
pathA->addPage (new KAssistantPage (page4aWidget, i18n ("page 4a")));

KAssistantPageGroup *pathB = new KAssistantPageGroup (i18n ("path b"));
pathB->addPage (new KAssistantPage (page2bWidget, i18n ("page 2b")));
pathB->addPage (new KAssistantPage (page3bWidget, i18n ("page 3b")));
pathB->setAppropriate (false);

dialog->addPage (new KAssistantPage (page1Widget, i18n ("page 1")));
dialog->addPage (pathA);
dialog->addPage (pathB);
dialog->addPage (new KAssistantPage (page5Widget, i18n ("Last page")));