QWizards



  • Hi,
    I am implementing a non-linear QWizard application. I have a custom button which I want it to be used to return to the main (start) page, i.e it should be disabled in the main page but be enabled in all other pages. Below is how I implemented it:
    @
    //mywizard.h
    #include <QtGui/QWizard>
    #include <QtGui/QPushButton>

    class MyWizard : public QWizard
    {
    Q_OBJECT
    .
    .
    .
    private:
    QPushButton *mainPageButton;

     friend class MainPage; 
     friend class OtherPage; 
    
    private slots:
          int showMainPage(int customButton);
    

    }

    ////mywizard.cpp
    #include <mywizard.h>
    MyWizard::MyWizard(QWidget *parent)
    : QWizard(parent)
    {
    setPage(Page_Main, new MainPage);
    setPage(Page_Other, new OtherPage);
    setStartId(Page_Main);
    .
    .
    .
    mainPageButton = new QPushButton(tr("&MainPage"));
    mainPageButton->setDisabled(true);
    this->setButton(CustomButton1, mainPageButton);
    this->setOption(HaveCustomButton1);
    connect(this, SIGNAL(customButtonClicked(int)), this, SLOT(showMainPage(int)));
    .
    .
    .
    }
    int MyWizard::showMainPage(int customButton)
    {
    if(customButton == CustomButton1)
    {
    return MyWizard::Page_Main;
    }
    else
    return currentId();
    }

    //mainpage.h
    #include "mywizard.h"

    class MainPage : public QWizardPage
    {
    Q_OBJECT
    .
    .
    .
    public:
    MainPage(QWidget *parent = 0);
    void disableMainPageButton(MyWizard mainPage){ mainPage.mainPageButton->setDisabled(true); }

    }

    //mainpage.cpp
    #include "mainpage.h"
    #include "mywizard.h"

    MainPage::MainPage(QWidget *parent)
    : QWizardPage(parent)
    {
    .
    .
    .
    MyWizard mywizardMainPageButton;
    MainPage gotoMainPage;
    gotoMainPage.disableMainPageButton(mywizardMainPageButton);
    .
    .
    .
    }

    //otherpage.h
    #include "mywizard.h"
    class OtherPage : public QWizardPage
    {
    Q_OBJECT
    .
    .
    .
    public:
    OtherPage(QWidget *parent = 0);
    void enableMainPageButton(MyWizard mainPage){ mainPage.mainPageButton->setEnabled(true); }
    .
    .
    .
    }

    //otherpage.cpp
    #include "otherpage.h"
    #include "mywizard.h"
    OtherPage::OtherPage(QWidget *parent)
    : QWizardPage(parent)
    {
    .
    .
    .
    MyWizard mywizardMainPageButton;
    OtherPage gotoMainPage;
    gotoMainPage.enableMainPageButton(mywizardMainPageButton);
    .
    .
    .
    }
    @

    Unfortunatetly, I get the following errors when compiling:

    In copy constructor ‘MyWizard::MyWizard(const MyWizard&)’:
    error: ‘QWizard::QWizard(const QWizard&)’ is private
    within this context
    In constructor ‘MainPage::MainPage(QWidget*)’:
    synthesized method ‘MyWizard::MyWizard(const MyWizard&)’ first required here
    initializing argument 1 of ‘void MainPage::enableMainPageButton(MyWizard)’

    How can I fix this errors so that I can achieve what I want?



  • For all QWidget (also QObject) derived classes, copy constructor is disabled so it is not copiable.
    Perehaps in the code which uses MyWizard, you try to copy it?



  • I kind of not understand, can you please explain further. That is from the above given code, where did I go wrong? When I started with mainPageButton enabled when I click it from otherPage, the mainPage is not shown, is there anything wrong with (MyWizard) showMainPage member function?



  • The error message that you wrote here let's me assume that the copy constructor is used somewhere. I don't know where, perhaps in some other code, but the error message is clear.



  • Line 110 looks suspisious... Why do you create a MyWizard instance inside a wizard page?



  • Andre, you pointed to the line that creates the error, nearly :-)
    112 is the bug:

    @
    class MainPage : public QWizardPage
    {
    Q_OBJECT
    .
    public:
    void disableMainPageButton(MyWizard mainPage){ mainPage.mainPageButton->setDisabled(true); }

    MyWizard mywizardMainPageButton;
    OtherPage gotoMainPage;
    // line 112:
    gotoMainPage.enableMainPageButton(mywizardMainPageButton);
    

    @

    The function definition of disableMainPageButton says, parameter by value, which makes a copy. I think you wanted a reference or a pointer?



  • I tried to use pointers as you suggested, Gerolf, and the errors are gone. However, when running the application it does not start up. When debugging, its like there is a segmentation fault signal from the OS.
    This is how I edited the code:
    @
    OtherPage::OtherPage(QWidget *parent)
    : QWizardPage(parent)
    {
    .
    .
    .
    MyWizard *mywizardMainPageButton = new MyWizard(this);
    OtherPage gotoMainPage;
    gotoMainPage.enableMainPageButton(mywizardMainPageButton);
    .
    .
    .
    }
    @

    How can I eliminate this segmentation fault so my application can start up?



  • Basically the same question as I asked earlier: Why do you create a new instance of your wizard from a wizard page? That simply can not be right.

    What you probably want to do, is access the wizard class that this page is a page for, right? In that case, you need something like this:

    @
    MyWizard *mywizardMainPageButton = qobject_cast<MyWizard>(wizard());
    if (mywizardMainPageButton) {
    mywizardMainPageButton->gotoMainPage();
    }
    @



  • Hi manaila,

    you have an infinite recursion in the constructor:

    @
    OtherPage::OtherPage(QWidget *parent)
    : QWizardPage(parent)
    {
    ....
    MyWizard *mywizardMainPageButton = new MyWizard(this);
    OtherPage gotoMainPage; // <-- here you craete a second instance, whcih calls this constructor which creates...
    gotoMainPage.enableMainPageButton(mywizardMainPageButton);
    }
    @



  • [quote author="Andre" date="1315993852"]Basically the same question as I asked earlier: Why do you create a new instance of your wizard from a wizard page? That simply can not be right.

    What you probably want to do, is access the wizard class that this page is a page for, right?

    [/quote]
    Yeah, thats what I want do. I followed your suggestion and I get the following errors:

    ‘MyWizard’ was not declared in this scope
    ‘mywizardMainPageButton’ was not declared in this scope
    ‘MyWizard’ cannot appear in a constant-expression
    no matching function for call to ‘qobject_cast(QWizard*)’

    [quote author="Gerolf" date="1315997656"]

    you have an infinite recursion in the constructor:

    [/quote]
    I edited it such that I am left with:
    @
    MyWizard *mywizardMainPageButton = new MyWizard(this);
    enableMainPageButton(mywizardMainPageButton);
    @
    It compiles with no errors but it does not show up when running it.



  • You do #include the header that declares your MyWizard class from the file where the code we are discussing is in, right?



  • what should show up?

    you dont show mywizardMainPageButton, you don't add it to a layout or wizard...



  • [quote author="Andre" date="1316011376"]You do #include the header that declares your MyWizard class from the file where the code we are discussing is in, right? [/quote]
    My bad, I forgot to include the header files. After including them I got the errors:
    cannot convert ‘MyWizard’ to ‘MyWizard*’ in initialization, and I edited the code to
    @
    MyWizard mywizardMainPageButton = qobject_cast<MyWizard>(wizard());
    @
    I am not sure if its right but it did not show errors when compiling. But the wizard GUI application does not show up when executing it. I get the message: The program has unexpectedly finished.

    [quote author="Gerolf" date="1316012745"]what should show up?

    you dont show mywizardMainPageButton, you don't add it to a layout or wizard...[/quote]
    I was expecting the wizard GUI application to show up when executing it. In fact, the GUI does show up when excluding this code which allows returning to the main page when the custombutton1 (mainPageButton) is clicked from any other wizard page, as discussed at the beginning of this thread.



  • [quote author="manaila" date="1316069748"]
    @
    MyWizard mywizardMainPageButton = qobject_cast<MyWizard>(wizard());
    @
    [/quote]

    you create a local stack ob ject, hard cast it to a pointer, which is a big bug and want to use the pointer afterwards. Please, these are basic C++ things. The object does not exist aftre that line anymore.



  • So, it means that QWizards do not offer the property that I wanted since your suggestions couldn't solve my problem. Thank you, anyway.



  • [quote author="manaila" date="1316080444"]So, it means that QWizards do not offer the property that I wanted since your suggestions couldn't solve my problem. Thank you, anyway.[/quote]

    That is not correct.

    The program has unexpectedly finished. This means, you have a programming bug.
    But without the whole code, it is a bit difficult, to check, what is wrong.

    I had a mistake in my last post, sorry for that. What does wizard() return?
    You see there are many relevant things, that come together and you always show 3 lines of code, where no one else then you know, what is behind.

    You could create a small example, that shows your problem and post it to pastebin or similar, so we can see the whole code.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.