QWizard: Temporarily disable the Back button
Hi all,
I have a simple QWizard (code below). When the user moves to page 2 of the wizard a longish, asynchronous network request is made. During that request I'd like to disable the Back (and potentially other) buttons on the wizard. When the request is complete the buttons will be enabled and going Back is allowed. Using setEnabled() on the back button is not working, presumably the QWizard code is re-enabling it. I have had to resort to disabling the entire wizard.
I know that I could set page 1 as a commit page, but that would prohibit the back button entirely on page 2. I only need a temporary block on the back button.
Have I missed the really obvious way to do this?
Cheers,
Chris
Code:
#include <QtGui>
#include <QDebug>
class Page1: public QWizardPage {
Q_OBJECT
public:
Page1
(QWidget *p
= 0): QWizardPage
(p
) { label
= new QLabel(tr
("This is an example page 1"),
this);
label->setWordWrap(true);
layout->addWidget(label);
setLayout(layout);
}
};
class Page2: public QWizardPage {
Q_OBJECT
public:
Page2
(QWidget *p
= 0): QWizardPage
(p
) { label
= new QLabel(tr
("This is an example page 2"),
this);
label->setWordWrap(true);
layout->addWidget(label);
setLayout(layout);
}
void initializePage() {
// This does not disable the button for the long process
wizard()->button(QWizard::BackButton)->setEnabled(false);
// so I have to resort to this
// wizard()->setEnabled(false);
label->setText("Starting");
// simulate a longish process
QTimer::singleShot(5000,
this,
SLOT(expired
()));
}
public slots:
void expired() {
label->setText("Finished");
wizard()->button(QWizard::BackButton)->setEnabled(true);
// wizard()->setEnabled(true);
}
};
class Wizard : public QWizard {
Q_OBJECT
public:
Wizard
(QWidget *p
= 0) : QWizard
(p
) { addPage(new Page1);
addPage(new Page2);
}
};
int main(int argc, char *argv[])
{
Wizard wiz;
wiz.show();
return app.exec();
}
#include "main.moc"
Re: QWizard: Temporarily disable the Back button
Wow, that's crazy. QWizard seems to set the buttons at last. Even the signal currentIdChanged() is useless. The only workaround is to create a slot which disables the button and call that slot inside initializePage() with an 1ms single shot timer. That's not nice, but the only solution I can figure out right now.
Re: QWizard: Temporarily disable the Back button
QWizardPage::initializePage() is virtual function is called by QWizard::initializePage() to prepare the page just before it is shown, once the page is prepared the control goes back to QWizard, then QWizard sets the Back and Next button status based on the page options set in QWizardPage::initializePage(), so it may not be good idea to set buttons in there.
You can set the buttons sometime later, something like this
Code:
class Page2: public QWizardPage {
Q_OBJECT
public:
Page2
(QWidget *p
= 0): QWizardPage
(p
) { label
= new QLabel(tr
("This is an example page 2"),
this);
label->setWordWrap(true);
layout->addWidget(label);
setLayout(layout);
}
void initializePage() {
label->setText("Starting");
// set trigger for longish process
QTimer::singleShot(0,
this,
SLOT(start
()));
}
public slots:
void start() {
wizard()->button(QWizard::BackButton)->setEnabled(false);
// simulate a longish process
QTimer::singleShot(5000,
this,
SLOT(expired
()));
}
void expired() {
label->setText("Finished");
wizard()->button(QWizard::BackButton)->setEnabled(true);
}
};
Re: QWizard: Temporarily disable the Back button
I guess the zero-duration single shot timer is an option. A bit clunky IMHO.
Edit: You also need to be careful not to emit completeChanged() or QWizard will reset your buttons (all of them, not just the Next/Finished button)
Re: It is possible to completely hide Back button
Hello Guyz,
I've looked at Qt's sources and found out that it's possible to hide Back button by creating cusom button layout and ommiting Back button in the list:
Code:
QList<QWizard::WizardButton> button_layout;
button_layout << QWizard::HelpButton << QWizard::Stretch <<
QWizard::NextButton << QWizard::CustomButton1 <<
QWizard::CancelButton;
this->setButtonLayout(button_layout);
I hope this will save some time to somebody.
Regards
Added after 7 minutes:
AFAIU to avoid using QTimer it is needed to modify QWizard source code. The easies way will be to add a virtual function
Quote:
virtual void buttonsUpdated();
and call it from the end of QWizard's:
Quote:
void QWizardPrivate::_q_updateButtonStates()
Then reimplement this buttonsUpdated() in your QWizard sublass and disable Back button there.
Re: It is possible to completely hide Back button
Adding virtual functions to public classes is no fun as it breaks binary compatibility.
Re: It is possible to completely hide Back button
wysota, thanks for mentioning about this.
The binary compatibility issue can be fixed using a signal instead of virtual function:
documentation