Building a wizard in designer is overly complex and has a few pitfalls.
This is especially the case when you try to build your wizard using Qt4
Designer exclusively. The main problem comes in due to the fact that
although you can happily place any widgets you like onto a QWizardPage,
in the QWizard you cannot actually access them at run time. So that
makes it useful for adding static content like labels or text but pretty
challenging for everything else. A while ago I implemented a welcome
wizard for QGIS but never actually applied it trunk. Today I had
occasion to dust off the cobwebs and I thought I would write this up to
explain how I did it since you won't find much help on Google on the
matter.
Ok, so first up, I created a new QWizard implementation
(qgswelcomewizardbase.ui) using designer like this.
So thats fine for page one, but on page two I want some dynamic content
- in this case a checkbox. You would think I could just click next in
designer and plonk it on the page here:
Rather you need to create a separate QWizardPage widget and drop your
controls on there like this:
Next you need to create an implementation class for the page widget. I
called my ui 'qgschoosetoregisterbase.ui' (catchy name I know), so my
inheriting class will be QgsChooseToRegister. It looks like this (all
implemented directly in the header):
#ifndef QGSCHOOSETOREGISTERPAGE_H
#define QGSCHOOSETOREGISTERPAGE_H
#include <ui_qgschoosetoregisterpagebase.h>
/** \ingroup app
* \brief a custom page (by promotion in designer) so that we
* can access added widgets on this page from within the QWizard context.
* @author Tim Sutton
* */
class QgsChooseToRegisterPage : public QWizardPage, public Ui::QgsChooseToRegisterPageBase
{
Q_OBJECT;
public:
QgsChooseToRegisterPage(){
setupUi( this );
setTitle( tr( "Would you like to register on our user's map?" ) );
};
~QgsChooseToRegisterPage(){};
};
#endif
As you can see, it doesn't do much. If you wanted to, you could also
user registerField() calls in this function to make any widgets globally
accessible from the wizard. Next comes the real trick, and that is to
promote the empty page widget in designer for our QWizard to our new
class. To do this, right click on the page object in the object
inspector and promote it to the QgsChoosToRegister class. You probably
won't have that latter listed already, in which case you should add it
to the list of promotable classes by right clicking on the page widget
in the object inspector and choosing 'promote to...'. Then fill in the
form to look like the screenshot below and click the add button to make
it part of the list of promoted classes. Then you can close and do the
aforementioned step as illustrated in the two screenshots below.
There is one last piece of the puzzle - how you actually access the
control (in our case the checkbox above). The code below is from our
implementation class for the QWizard and illustrates how to do this.
int QgsWelcomeWizard::nextId() const
{
switch ( currentId() )
{
case StartPage:
return ChooseToRegisterPage;
case ChooseToRegisterPage:
if ( mChooseToRegisterPage->mCbxRegister->isChecked() )
{
mRegisterPage->webView->setUrl( QUrl( "http://users.qgis.org/community-map/create_user_form.html" ) );
return RegisterPage;
}
else
{
return ThanksPage;
}
case RegisterPage:
return ThanksPage;
default:
return -1;
}
}
To access the checkbox I simply called
setPage( ChooseToRegisterPage, mChooseToRegisterPage ),
in the init function of the page and then used the
mChooseToRegisterPage->mCbxRegister->isChecked()
To see if the checkbox was checked.
Hopefully this will prove helpful to others out there who run into the
same issues. The process described above is still a lot faster than hand
coding your wizard, though I thing the Qt4 folks could make like a lot
easier still by providing some glue to access the content of the wizard
pages.