src/gui/dialogs/qwizard.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qwizard.h"
       
    43 
       
    44 #ifndef QT_NO_WIZARD
       
    45 
       
    46 #include "qabstractspinbox.h"
       
    47 #include "qalgorithms.h"
       
    48 #include "qapplication.h"
       
    49 #include "qboxlayout.h"
       
    50 #include "qlayoutitem.h"
       
    51 #include "qdesktopwidget.h"
       
    52 #include "qevent.h"
       
    53 #include "qframe.h"
       
    54 #include "qlabel.h"
       
    55 #include "qlineedit.h"
       
    56 #include "qpainter.h"
       
    57 #include "qpushbutton.h"
       
    58 #include "qset.h"
       
    59 #include "qstyle.h"
       
    60 #include "qvarlengtharray.h"
       
    61 #if defined(Q_WS_MAC)
       
    62 #include "private/qt_mac_p.h"
       
    63 #include "qlibrary.h"
       
    64 #elif !defined(QT_NO_STYLE_WINDOWSVISTA)
       
    65 #include "qwizard_win_p.h"
       
    66 #include "qtimer.h"
       
    67 #endif
       
    68 
       
    69 #include "private/qdialog_p.h"
       
    70 #include <qdebug.h>
       
    71 
       
    72 #ifdef Q_WS_WINCE
       
    73 extern bool qt_wince_is_mobile();     //defined in qguifunctions_wce.cpp
       
    74 #endif
       
    75 
       
    76 #include <string.h>     // for memset()
       
    77 
       
    78 #ifdef QT_SOFTKEYS_ENABLED
       
    79 #include "qaction.h"
       
    80 #endif
       
    81 
       
    82 QT_BEGIN_NAMESPACE
       
    83 
       
    84 // These fudge terms were needed a few places to obtain pixel-perfect results
       
    85 const int GapBetweenLogoAndRightEdge = 5;
       
    86 const int ModernHeaderTopMargin = 2;
       
    87 const int ClassicHMargin = 4;
       
    88 const int MacButtonTopMargin = 13;
       
    89 const int MacLayoutLeftMargin = 20;
       
    90 //const int MacLayoutTopMargin = 14; // Unused. Save some space and avoid warning.
       
    91 const int MacLayoutRightMargin = 20;
       
    92 const int MacLayoutBottomMargin = 17;
       
    93 
       
    94 static void changeSpacerSize(QLayout *layout, int index, int width, int height)
       
    95 {
       
    96     QSpacerItem *spacer = layout->itemAt(index)->spacerItem();
       
    97     if (!spacer)
       
    98         return;
       
    99     spacer->changeSize(width, height);
       
   100 }
       
   101 
       
   102 static QWidget *iWantTheFocus(QWidget *ancestor)
       
   103 {
       
   104     const int MaxIterations = 100;
       
   105 
       
   106     QWidget *candidate = ancestor;
       
   107     for (int i = 0; i < MaxIterations; ++i) {
       
   108         candidate = candidate->nextInFocusChain();
       
   109         if (!candidate)
       
   110             break;
       
   111 
       
   112         if (candidate->focusPolicy() & Qt::TabFocus) {
       
   113             if (candidate != ancestor && ancestor->isAncestorOf(candidate))
       
   114                 return candidate;
       
   115         }
       
   116     }
       
   117     return 0;
       
   118 }
       
   119 
       
   120 static bool objectInheritsXAndXIsCloserThanY(const QObject *object, const QByteArray &classX,
       
   121                                              const QByteArray &classY)
       
   122 {
       
   123     const QMetaObject *metaObject = object->metaObject();
       
   124     while (metaObject) {
       
   125         if (metaObject->className() == classX)
       
   126             return true;
       
   127         if (metaObject->className() == classY)
       
   128             return false;
       
   129         metaObject = metaObject->superClass();
       
   130     }
       
   131     return false;
       
   132 }
       
   133 
       
   134 const int NFallbackDefaultProperties = 7;
       
   135 
       
   136 const struct {
       
   137     const char *className;
       
   138     const char *property;
       
   139     const char *changedSignal;
       
   140 } fallbackProperties[NFallbackDefaultProperties] = {
       
   141     // If you modify this list, make sure to update the documentation (and the auto test)
       
   142     { "QAbstractButton", "checked", SIGNAL(toggled(bool)) },
       
   143     { "QAbstractSlider", "value", SIGNAL(valueChanged(int)) },
       
   144     { "QComboBox", "currentIndex", SIGNAL(currentIndexChanged(int)) },
       
   145     { "QDateTimeEdit", "dateTime", SIGNAL(dateTimeChanged(QDateTime)) },
       
   146     { "QLineEdit", "text", SIGNAL(textChanged(QString)) },
       
   147     { "QListWidget", "currentRow", SIGNAL(currentRowChanged(int)) },
       
   148     { "QSpinBox", "value", SIGNAL(valueChanged(int)) }
       
   149 };
       
   150 
       
   151 class QWizardDefaultProperty
       
   152 {
       
   153 public:
       
   154     QByteArray className;
       
   155     QByteArray property;
       
   156     QByteArray changedSignal;
       
   157 
       
   158     inline QWizardDefaultProperty() {}
       
   159     inline QWizardDefaultProperty(const char *className, const char *property,
       
   160                                    const char *changedSignal)
       
   161         : className(className), property(property), changedSignal(changedSignal) {}
       
   162 };
       
   163 
       
   164 class QWizardField
       
   165 {
       
   166 public:
       
   167     inline QWizardField() {}
       
   168     QWizardField(QWizardPage *page, const QString &spec, QObject *object, const char *property,
       
   169                   const char *changedSignal);
       
   170 
       
   171     void resolve(const QVector<QWizardDefaultProperty> &defaultPropertyTable);
       
   172     void findProperty(const QWizardDefaultProperty *properties, int propertyCount);
       
   173 
       
   174     QWizardPage *page;
       
   175     QString name;
       
   176     bool mandatory;
       
   177     QObject *object;
       
   178     QByteArray property;
       
   179     QByteArray changedSignal;
       
   180     QVariant initialValue;
       
   181 };
       
   182 
       
   183 QWizardField::QWizardField(QWizardPage *page, const QString &spec, QObject *object,
       
   184                            const char *property, const char *changedSignal)
       
   185     : page(page), name(spec), mandatory(false), object(object), property(property),
       
   186       changedSignal(changedSignal)
       
   187 {
       
   188     if (name.endsWith(QLatin1Char('*'))) {
       
   189         name.chop(1);
       
   190         mandatory = true;
       
   191     }
       
   192 }
       
   193 
       
   194 void QWizardField::resolve(const QVector<QWizardDefaultProperty> &defaultPropertyTable)
       
   195 {
       
   196     if (property.isEmpty())
       
   197         findProperty(defaultPropertyTable.constData(), defaultPropertyTable.count());
       
   198     initialValue = object->property(property);
       
   199 }
       
   200 
       
   201 void QWizardField::findProperty(const QWizardDefaultProperty *properties, int propertyCount)
       
   202 {
       
   203     QByteArray className;
       
   204 
       
   205     for (int i = 0; i < propertyCount; ++i) {
       
   206         if (objectInheritsXAndXIsCloserThanY(object, properties[i].className, className)) {
       
   207             className = properties[i].className;
       
   208             property = properties[i].property;
       
   209             changedSignal = properties[i].changedSignal;
       
   210         }
       
   211     }
       
   212 }
       
   213 
       
   214 class QWizardLayoutInfo
       
   215 {
       
   216 public:
       
   217     inline QWizardLayoutInfo()
       
   218     : topLevelMarginLeft(-1), topLevelMarginRight(-1), topLevelMarginTop(-1),
       
   219       topLevelMarginBottom(-1), childMarginLeft(-1), childMarginRight(-1),
       
   220       childMarginTop(-1), childMarginBottom(-1), hspacing(-1), vspacing(-1),
       
   221           wizStyle(QWizard::ClassicStyle), header(false), watermark(false), title(false),
       
   222           subTitle(false), extension(false) {}
       
   223 
       
   224     int topLevelMarginLeft;
       
   225     int topLevelMarginRight;
       
   226     int topLevelMarginTop;
       
   227     int topLevelMarginBottom;
       
   228     int childMarginLeft;
       
   229     int childMarginRight;
       
   230     int childMarginTop;
       
   231     int childMarginBottom;
       
   232     int hspacing;
       
   233     int vspacing;
       
   234     int buttonSpacing;
       
   235     QWizard::WizardStyle wizStyle;
       
   236     bool header;
       
   237     bool watermark;
       
   238     bool title;
       
   239     bool subTitle;
       
   240     bool extension;
       
   241 
       
   242     bool operator==(const QWizardLayoutInfo &other);
       
   243     inline bool operator!=(const QWizardLayoutInfo &other) { return !operator==(other); }
       
   244 };
       
   245 
       
   246 bool QWizardLayoutInfo::operator==(const QWizardLayoutInfo &other)
       
   247 {
       
   248     return topLevelMarginLeft == other.topLevelMarginLeft
       
   249            && topLevelMarginRight == other.topLevelMarginRight
       
   250            && topLevelMarginTop == other.topLevelMarginTop
       
   251            && topLevelMarginBottom == other.topLevelMarginBottom
       
   252            && childMarginLeft == other.childMarginLeft
       
   253            && childMarginRight == other.childMarginRight
       
   254            && childMarginTop == other.childMarginTop
       
   255            && childMarginBottom == other.childMarginBottom
       
   256            && hspacing == other.hspacing
       
   257            && vspacing == other.vspacing
       
   258            && buttonSpacing == other.buttonSpacing
       
   259            && wizStyle == other.wizStyle
       
   260            && header == other.header
       
   261            && watermark == other.watermark
       
   262            && title == other.title
       
   263            && subTitle == other.subTitle
       
   264            && extension == other.extension;
       
   265 }
       
   266 
       
   267 class QWizardHeader : public QWidget
       
   268 {
       
   269 public:
       
   270     enum RulerType { Ruler };
       
   271 
       
   272     inline QWizardHeader(RulerType /* ruler */, QWidget *parent = 0)
       
   273         : QWidget(parent) { setFixedHeight(2); }
       
   274     QWizardHeader(QWidget *parent = 0);
       
   275 
       
   276     void setup(const QWizardLayoutInfo &info, const QString &title,
       
   277                const QString &subTitle, const QPixmap &logo, const QPixmap &banner,
       
   278                Qt::TextFormat titleFormat, Qt::TextFormat subTitleFormat);
       
   279 
       
   280 protected:
       
   281     void paintEvent(QPaintEvent *event);
       
   282 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   283 private:
       
   284     bool vistaDisabled() const;
       
   285 #endif
       
   286 private:
       
   287     QLabel *titleLabel;
       
   288     QLabel *subTitleLabel;
       
   289     QLabel *logoLabel;
       
   290     QGridLayout *layout;
       
   291     QPixmap bannerPixmap;
       
   292 };
       
   293 
       
   294 QWizardHeader::QWizardHeader(QWidget *parent)
       
   295     : QWidget(parent)
       
   296 {
       
   297     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
       
   298     setBackgroundRole(QPalette::Base);
       
   299 
       
   300     titleLabel = new QLabel(this);
       
   301     titleLabel->setBackgroundRole(QPalette::Base);
       
   302 
       
   303     subTitleLabel = new QLabel(this);
       
   304     subTitleLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
       
   305     subTitleLabel->setWordWrap(true);
       
   306 
       
   307     logoLabel = new QLabel(this);
       
   308 
       
   309     QFont font = titleLabel->font();
       
   310     font.setBold(true);
       
   311     titleLabel->setFont(font);
       
   312 
       
   313     layout = new QGridLayout(this);
       
   314     layout->setMargin(0);
       
   315     layout->setSpacing(0);
       
   316 
       
   317     layout->setRowMinimumHeight(3, 1);
       
   318     layout->setRowStretch(4, 1);
       
   319 
       
   320     layout->setColumnStretch(2, 1);
       
   321     layout->setColumnMinimumWidth(4, 2 * GapBetweenLogoAndRightEdge);
       
   322     layout->setColumnMinimumWidth(6, GapBetweenLogoAndRightEdge);
       
   323 
       
   324     layout->addWidget(titleLabel, 2, 1, 1, 2);
       
   325     layout->addWidget(subTitleLabel, 4, 2);
       
   326     layout->addWidget(logoLabel, 1, 5, 5, 1);
       
   327 }
       
   328 
       
   329 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   330 bool QWizardHeader::vistaDisabled() const
       
   331 {
       
   332     bool styleDisabled = false;
       
   333     QWizard *wiz = parentWidget() ? qobject_cast <QWizard *>(parentWidget()->parentWidget()) : 0;
       
   334     if (wiz) {
       
   335         // Designer dosen't support the Vista style for Wizards. This property is used to turn
       
   336         // off the Vista style.
       
   337         const QVariant v = wiz->property("_q_wizard_vista_off");
       
   338         styleDisabled = v.isValid() && v.toBool();
       
   339     }
       
   340     return styleDisabled;
       
   341 }
       
   342 #endif
       
   343 
       
   344 void QWizardHeader::setup(const QWizardLayoutInfo &info, const QString &title,
       
   345                           const QString &subTitle, const QPixmap &logo, const QPixmap &banner,
       
   346                           Qt::TextFormat titleFormat, Qt::TextFormat subTitleFormat)
       
   347 {
       
   348     bool modern = ((info.wizStyle == QWizard::ModernStyle)
       
   349 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   350         || ((info.wizStyle == QWizard::AeroStyle
       
   351             && QVistaHelper::vistaState() == QVistaHelper::Classic) || vistaDisabled())
       
   352 #endif
       
   353     );
       
   354 
       
   355     layout->setRowMinimumHeight(0, modern ? ModernHeaderTopMargin : 0);
       
   356     layout->setRowMinimumHeight(1, modern ? info.topLevelMarginTop - ModernHeaderTopMargin - 1 : 0);
       
   357     layout->setRowMinimumHeight(6, (modern ? 3 : GapBetweenLogoAndRightEdge) + 2);
       
   358 
       
   359     int minColumnWidth0 = modern ? info.topLevelMarginLeft + info.topLevelMarginRight : 0;
       
   360     int minColumnWidth1 = modern ? info.topLevelMarginLeft + info.topLevelMarginRight + 1
       
   361                                  : info.topLevelMarginLeft + ClassicHMargin;
       
   362     layout->setColumnMinimumWidth(0, minColumnWidth0);
       
   363     layout->setColumnMinimumWidth(1, minColumnWidth1);
       
   364 
       
   365     titleLabel->setTextFormat(titleFormat);
       
   366     titleLabel->setText(title);
       
   367     logoLabel->setPixmap(logo);
       
   368 
       
   369     subTitleLabel->setTextFormat(subTitleFormat);
       
   370     subTitleLabel->setText(QLatin1String("Pq\nPq"));
       
   371     int desiredSubTitleHeight = subTitleLabel->sizeHint().height();
       
   372     subTitleLabel->setText(subTitle);
       
   373 
       
   374     if (modern) {
       
   375         bannerPixmap = banner;
       
   376     } else {
       
   377         bannerPixmap = QPixmap();
       
   378     }
       
   379 
       
   380     if (bannerPixmap.isNull()) {
       
   381         /*
       
   382             There is no widthForHeight() function, so we simulate it with a loop.
       
   383         */
       
   384         int candidateSubTitleWidth = qMin(512, 2 * QApplication::desktop()->width() / 3);
       
   385         int delta = candidateSubTitleWidth >> 1;
       
   386         while (delta > 0) {
       
   387             if (subTitleLabel->heightForWidth(candidateSubTitleWidth - delta)
       
   388                         <= desiredSubTitleHeight)
       
   389                 candidateSubTitleWidth -= delta;
       
   390             delta >>= 1;
       
   391         }
       
   392 
       
   393         subTitleLabel->setMinimumSize(candidateSubTitleWidth, desiredSubTitleHeight);
       
   394 
       
   395         QSize size = layout->totalMinimumSize();
       
   396         setMinimumSize(size);
       
   397         setMaximumSize(QWIDGETSIZE_MAX, size.height());
       
   398     } else {
       
   399         subTitleLabel->setMinimumSize(0, 0);
       
   400         setFixedSize(banner.size() + QSize(0, 2));
       
   401     }
       
   402     updateGeometry();
       
   403 }
       
   404 
       
   405 void QWizardHeader::paintEvent(QPaintEvent * /* event */)
       
   406 {
       
   407     QPainter painter(this);
       
   408     painter.drawPixmap(0, 0, bannerPixmap);
       
   409 
       
   410     int x = width() - 2;
       
   411     int y = height() - 2;
       
   412     const QPalette &pal = palette();
       
   413     painter.setPen(pal.mid().color());
       
   414     painter.drawLine(0, y, x, y);
       
   415     painter.setPen(pal.base().color());
       
   416     painter.drawPoint(x + 1, y);
       
   417     painter.drawLine(0, y + 1, x + 1, y + 1);
       
   418 }
       
   419 
       
   420 // We save one vtable by basing QWizardRuler on QWizardHeader
       
   421 class QWizardRuler : public QWizardHeader
       
   422 {
       
   423 public:
       
   424     inline QWizardRuler(QWidget *parent = 0)
       
   425         : QWizardHeader(Ruler, parent) {}
       
   426 };
       
   427 
       
   428 class QWizardPagePrivate : public QWidgetPrivate
       
   429 {
       
   430     Q_DECLARE_PUBLIC(QWizardPage)
       
   431 
       
   432 public:
       
   433     enum TriState { Tri_Unknown = -1, Tri_False, Tri_True };
       
   434 
       
   435     inline QWizardPagePrivate()
       
   436         : wizard(0), completeState(Tri_Unknown), explicitlyFinal(false), commit(false) {}
       
   437 
       
   438     bool cachedIsComplete() const;
       
   439     void _q_maybeEmitCompleteChanged();
       
   440     void _q_updateCachedCompleteState();
       
   441 
       
   442     QWizard *wizard;
       
   443     QString title;
       
   444     QString subTitle;
       
   445     QPixmap pixmaps[QWizard::NPixmaps];
       
   446     QVector<QWizardField> pendingFields;
       
   447     mutable TriState completeState;
       
   448     bool explicitlyFinal;
       
   449     bool commit;
       
   450     QMap<int, QString> buttonCustomTexts;
       
   451 };
       
   452 
       
   453 bool QWizardPagePrivate::cachedIsComplete() const
       
   454 {
       
   455     Q_Q(const QWizardPage);
       
   456     if (completeState == Tri_Unknown)
       
   457         completeState = q->isComplete() ? Tri_True : Tri_False;
       
   458     return completeState == Tri_True;
       
   459 }
       
   460 
       
   461 void QWizardPagePrivate::_q_maybeEmitCompleteChanged()
       
   462 {
       
   463     Q_Q(QWizardPage);
       
   464     TriState newState = q->isComplete() ? Tri_True : Tri_False;
       
   465     if (newState != completeState)
       
   466         emit q->completeChanged();
       
   467 }
       
   468 
       
   469 void QWizardPagePrivate::_q_updateCachedCompleteState()
       
   470 {
       
   471     Q_Q(QWizardPage);
       
   472     completeState = q->isComplete() ? Tri_True : Tri_False;
       
   473 }
       
   474 
       
   475 class QWizardAntiFlickerWidget : public QWidget
       
   476 {
       
   477     QWizard *wizard;
       
   478     QWizardPrivate *wizardPrivate;
       
   479 public:
       
   480     QWizardAntiFlickerWidget(QWizard *wizard, QWizardPrivate *wizardPrivate)
       
   481         : QWidget(wizard)
       
   482         , wizard(wizard)
       
   483         , wizardPrivate(wizardPrivate) {}
       
   484 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   485 protected:
       
   486     void paintEvent(QPaintEvent *);
       
   487 #endif
       
   488 };
       
   489 
       
   490 class QWizardPrivate : public QDialogPrivate
       
   491 {
       
   492     Q_DECLARE_PUBLIC(QWizard)
       
   493 
       
   494 public:
       
   495     typedef QMap<int, QWizardPage *> PageMap;
       
   496 
       
   497     enum Direction {
       
   498         Backward,
       
   499         Forward
       
   500     };
       
   501 
       
   502     inline QWizardPrivate()
       
   503         : start(-1)
       
   504         , current(-1)
       
   505         , canContinue(false)
       
   506         , canFinish(false)
       
   507         , disableUpdatesCount(0)
       
   508         , opts(0)
       
   509         , buttonsHaveCustomLayout(false)
       
   510         , titleFmt(Qt::AutoText)
       
   511         , subTitleFmt(Qt::AutoText)
       
   512         , placeholderWidget1(0)
       
   513         , placeholderWidget2(0)
       
   514         , headerWidget(0)
       
   515         , watermarkLabel(0)
       
   516         , titleLabel(0)
       
   517         , subTitleLabel(0)
       
   518         , bottomRuler(0)
       
   519 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   520         , vistaInitPending(false)
       
   521         , vistaState(QVistaHelper::Dirty)
       
   522         , vistaStateChanged(false)
       
   523         , inHandleAeroStyleChange(false)
       
   524 #endif
       
   525         , minimumWidth(0)
       
   526         , minimumHeight(0)
       
   527         , maximumWidth(QWIDGETSIZE_MAX)
       
   528         , maximumHeight(QWIDGETSIZE_MAX)
       
   529     {
       
   530         for (int i = 0; i < QWizard::NButtons; ++i) {
       
   531             btns[i] = 0;
       
   532 #ifdef QT_SOFTKEYS_ENABLED
       
   533             softKeys[i] = 0;
       
   534 #endif
       
   535         }
       
   536 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   537         if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
       
   538             && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
       
   539             vistaInitPending = true;
       
   540 #endif
       
   541     }
       
   542 
       
   543     void init();
       
   544     void reset();
       
   545     void cleanupPagesNotInHistory();
       
   546     void addField(const QWizardField &field);
       
   547     void removeFieldAt(int index);
       
   548     void switchToPage(int newId, Direction direction);
       
   549     QWizardLayoutInfo layoutInfoForCurrentPage();
       
   550     void recreateLayout(const QWizardLayoutInfo &info);
       
   551     void updateLayout();
       
   552     void updateMinMaxSizes(const QWizardLayoutInfo &info);
       
   553     void updateCurrentPage();
       
   554     bool ensureButton(QWizard::WizardButton which) const;
       
   555     void connectButton(QWizard::WizardButton which) const;
       
   556     void updateButtonTexts();
       
   557     void updateButtonLayout();
       
   558     void setButtonLayout(const QWizard::WizardButton *array, int size);
       
   559     bool buttonLayoutContains(QWizard::WizardButton which);
       
   560     void updatePixmap(QWizard::WizardPixmap which);
       
   561 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   562     bool vistaDisabled() const;
       
   563     bool isVistaThemeEnabled(QVistaHelper::VistaState state) const;
       
   564     void handleAeroStyleChange();
       
   565 #endif
       
   566     bool isVistaThemeEnabled() const;
       
   567     void disableUpdates();
       
   568     void enableUpdates();
       
   569     void _q_emitCustomButtonClicked();
       
   570     void _q_updateButtonStates();
       
   571     void _q_handleFieldObjectDestroyed(QObject *);
       
   572     void setStyle(QStyle *style);
       
   573 #ifdef Q_WS_MAC
       
   574     static QPixmap findDefaultBackgroundPixmap();
       
   575 #endif
       
   576 
       
   577     PageMap pageMap;
       
   578     QVector<QWizardField> fields;
       
   579     QMap<QString, int> fieldIndexMap;
       
   580     QVector<QWizardDefaultProperty> defaultPropertyTable;
       
   581     QList<int> history;
       
   582     QSet<int> initialized; // ### remove and move bit to QWizardPage?
       
   583     int start;
       
   584     int current;
       
   585     bool canContinue;
       
   586     bool canFinish;
       
   587     QWizardLayoutInfo layoutInfo;
       
   588     int disableUpdatesCount;
       
   589 
       
   590     QWizard::WizardStyle wizStyle;
       
   591     QWizard::WizardOptions opts;
       
   592     QMap<int, QString> buttonCustomTexts;
       
   593     bool buttonsHaveCustomLayout;
       
   594     QList<QWizard::WizardButton> buttonsCustomLayout;
       
   595     Qt::TextFormat titleFmt;
       
   596     Qt::TextFormat subTitleFmt;
       
   597     mutable QPixmap defaultPixmaps[QWizard::NPixmaps];
       
   598 
       
   599     union {
       
   600         // keep in sync with QWizard::WizardButton
       
   601         mutable struct {
       
   602             QAbstractButton *back;
       
   603             QAbstractButton *next;
       
   604             QAbstractButton *commit;
       
   605             QAbstractButton *finish;
       
   606             QAbstractButton *cancel;
       
   607             QAbstractButton *help;
       
   608         } btn;
       
   609         mutable QAbstractButton *btns[QWizard::NButtons];
       
   610     };
       
   611     QWizardAntiFlickerWidget *antiFlickerWidget;
       
   612     QWidget *placeholderWidget1;
       
   613     QWidget *placeholderWidget2;
       
   614     QWizardHeader *headerWidget;
       
   615     QLabel *watermarkLabel;
       
   616     QFrame *pageFrame;
       
   617     QLabel *titleLabel;
       
   618     QLabel *subTitleLabel;
       
   619     QWizardRuler *bottomRuler;
       
   620 #ifdef QT_SOFTKEYS_ENABLED
       
   621     mutable QAction *softKeys[QWizard::NButtons];
       
   622 #endif
       
   623 
       
   624     QVBoxLayout *pageVBoxLayout;
       
   625     QHBoxLayout *buttonLayout;
       
   626     QGridLayout *mainLayout;
       
   627 
       
   628 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   629     QVistaHelper *vistaHelper;
       
   630     bool vistaInitPending;
       
   631     QVistaHelper::VistaState vistaState;
       
   632     bool vistaStateChanged;
       
   633     bool inHandleAeroStyleChange;
       
   634 #endif
       
   635     int minimumWidth;
       
   636     int minimumHeight;
       
   637     int maximumWidth;
       
   638     int maximumHeight;
       
   639 };
       
   640 
       
   641 static QString buttonDefaultText(int wstyle, int which, const QWizardPrivate *wizardPrivate)
       
   642 {
       
   643 #if defined(QT_NO_STYLE_WINDOWSVISTA)
       
   644     Q_UNUSED(wizardPrivate);
       
   645 #endif
       
   646     const bool macStyle = (wstyle == QWizard::MacStyle);
       
   647     switch (which) {
       
   648     case QWizard::BackButton:
       
   649         return macStyle ? QWizard::tr("Go Back") : QWizard::tr("< &Back");
       
   650     case QWizard::NextButton:
       
   651         if (macStyle)
       
   652             return QWizard::tr("Continue");
       
   653         else
       
   654             return wizardPrivate->isVistaThemeEnabled()
       
   655                 ? QWizard::tr("&Next") : QWizard::tr("&Next >");
       
   656     case QWizard::CommitButton:
       
   657         return QWizard::tr("Commit");
       
   658     case QWizard::FinishButton:
       
   659         return macStyle ? QWizard::tr("Done") : QWizard::tr("&Finish");
       
   660     case QWizard::CancelButton:
       
   661         return QWizard::tr("Cancel");
       
   662     case QWizard::HelpButton:
       
   663         return macStyle ? QWizard::tr("Help") : QWizard::tr("&Help");
       
   664     default:
       
   665         return QString();
       
   666     }
       
   667 }
       
   668 
       
   669 void QWizardPrivate::init()
       
   670 {
       
   671     Q_Q(QWizard);
       
   672 
       
   673     antiFlickerWidget = new QWizardAntiFlickerWidget(q, this);
       
   674     wizStyle = QWizard::WizardStyle(q->style()->styleHint(QStyle::SH_WizardStyle, 0, q));
       
   675     if (wizStyle == QWizard::MacStyle) {
       
   676         opts = (QWizard::NoDefaultButton | QWizard::NoCancelButton);
       
   677     } else if (wizStyle == QWizard::ModernStyle) {
       
   678         opts = QWizard::HelpButtonOnRight;
       
   679     }
       
   680 
       
   681 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   682     vistaHelper = new QVistaHelper(q);
       
   683 #endif
       
   684 
       
   685     // create these buttons right away; create the other buttons as necessary
       
   686     ensureButton(QWizard::BackButton);
       
   687     ensureButton(QWizard::NextButton);
       
   688     ensureButton(QWizard::CommitButton);
       
   689     ensureButton(QWizard::FinishButton);
       
   690 
       
   691     pageFrame = new QFrame(antiFlickerWidget);
       
   692     pageFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
       
   693 
       
   694     pageVBoxLayout = new QVBoxLayout(pageFrame);
       
   695     pageVBoxLayout->setSpacing(0);
       
   696     pageVBoxLayout->addSpacing(0);
       
   697     QSpacerItem *spacerItem = new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
       
   698     pageVBoxLayout->addItem(spacerItem);
       
   699 
       
   700     buttonLayout = new QHBoxLayout;
       
   701     mainLayout = new QGridLayout(antiFlickerWidget);
       
   702     mainLayout->setSizeConstraint(QLayout::SetNoConstraint);
       
   703 
       
   704     updateButtonLayout();
       
   705 
       
   706     for (int i = 0; i < NFallbackDefaultProperties; ++i)
       
   707         defaultPropertyTable.append(QWizardDefaultProperty(fallbackProperties[i].className,
       
   708                                                            fallbackProperties[i].property,
       
   709                                                            fallbackProperties[i].changedSignal));
       
   710 }
       
   711 
       
   712 void QWizardPrivate::reset()
       
   713 {
       
   714     Q_Q(QWizard);
       
   715     if (current != -1) {
       
   716         q->currentPage()->hide();
       
   717         cleanupPagesNotInHistory();
       
   718         for (int i = history.count() - 1; i >= 0; --i)
       
   719             q->cleanupPage(history.at(i));
       
   720         history.clear();
       
   721         initialized.clear();
       
   722 
       
   723         current = -1;
       
   724         emit q->currentIdChanged(-1);
       
   725     }
       
   726 }
       
   727 
       
   728 void QWizardPrivate::cleanupPagesNotInHistory()
       
   729 {
       
   730     Q_Q(QWizard);
       
   731 
       
   732     const QSet<int> original = initialized;
       
   733     QSet<int>::const_iterator i = original.constBegin();
       
   734     QSet<int>::const_iterator end = original.constEnd();
       
   735 
       
   736     for (; i != end; ++i) {
       
   737         if (!history.contains(*i)) {
       
   738             q->cleanupPage(*i);
       
   739             initialized.remove(*i);
       
   740         }
       
   741     }
       
   742 }
       
   743 
       
   744 void QWizardPrivate::addField(const QWizardField &field)
       
   745 {
       
   746     Q_Q(QWizard);
       
   747 
       
   748     QWizardField myField = field;
       
   749     myField.resolve(defaultPropertyTable);
       
   750 
       
   751     if (fieldIndexMap.contains(myField.name)) {
       
   752         qWarning("QWizardPage::addField: Duplicate field '%s'", qPrintable(myField.name));
       
   753         return;
       
   754     }
       
   755 
       
   756     fieldIndexMap.insert(myField.name, fields.count());
       
   757     fields += myField;
       
   758     if (myField.mandatory && !myField.changedSignal.isEmpty())
       
   759         QObject::connect(myField.object, myField.changedSignal,
       
   760                          myField.page, SLOT(_q_maybeEmitCompleteChanged()));
       
   761     QObject::connect(
       
   762         myField.object, SIGNAL(destroyed(QObject *)), q,
       
   763         SLOT(_q_handleFieldObjectDestroyed(QObject *)));
       
   764 }
       
   765 
       
   766 void QWizardPrivate::removeFieldAt(int index)
       
   767 {
       
   768     Q_Q(QWizard);
       
   769 
       
   770     const QWizardField &field = fields.at(index);
       
   771     fieldIndexMap.remove(field.name);
       
   772     if (field.mandatory && !field.changedSignal.isEmpty())
       
   773         QObject::disconnect(field.object, field.changedSignal,
       
   774                             field.page, SLOT(_q_maybeEmitCompleteChanged()));
       
   775     QObject::disconnect(
       
   776         field.object, SIGNAL(destroyed(QObject *)), q,
       
   777         SLOT(_q_handleFieldObjectDestroyed(QObject *)));
       
   778     fields.remove(index);
       
   779 }
       
   780 
       
   781 void QWizardPrivate::switchToPage(int newId, Direction direction)
       
   782 {
       
   783     Q_Q(QWizard);
       
   784 
       
   785     disableUpdates();
       
   786 
       
   787     int oldId = current;
       
   788     if (QWizardPage *oldPage = q->currentPage()) {
       
   789         oldPage->hide();
       
   790 
       
   791         if (direction == Backward) {
       
   792             if (!(opts & QWizard::IndependentPages)) {
       
   793                 q->cleanupPage(oldId);
       
   794                 initialized.remove(oldId);
       
   795             }
       
   796             Q_ASSERT(history.last() == oldId);
       
   797             history.removeLast();
       
   798             Q_ASSERT(history.last() == newId);
       
   799         }
       
   800     }
       
   801 
       
   802     current = newId;
       
   803 
       
   804     QWizardPage *newPage = q->currentPage();
       
   805     if (newPage) {
       
   806         if (direction == Forward) {
       
   807             if (!initialized.contains(current)) {
       
   808                 initialized.insert(current);
       
   809                 q->initializePage(current);
       
   810             }
       
   811             history.append(current);
       
   812         }
       
   813         newPage->show();
       
   814     }
       
   815 
       
   816     canContinue = (q->nextId() != -1);
       
   817     canFinish = (newPage && newPage->isFinalPage());
       
   818 
       
   819     _q_updateButtonStates();
       
   820     updateButtonTexts();
       
   821 
       
   822     const QWizard::WizardButton nextOrCommit =
       
   823         newPage && newPage->isCommitPage() ? QWizard::CommitButton : QWizard::NextButton;
       
   824     QAbstractButton *nextOrFinishButton =
       
   825         btns[canContinue ? nextOrCommit : QWizard::FinishButton];
       
   826     QWidget *candidate = 0;
       
   827 
       
   828     /*
       
   829         If there is no default button and the Next or Finish button
       
   830         is enabled, give focus directly to it as a convenience to the
       
   831         user. This is the normal case on Mac OS X.
       
   832 
       
   833         Otherwise, give the focus to the new page's first child that
       
   834         can handle it. If there is no such child, give the focus to
       
   835         Next or Finish.
       
   836     */
       
   837     if ((opts & QWizard::NoDefaultButton) && nextOrFinishButton->isEnabled()) {
       
   838         candidate = nextOrFinishButton;
       
   839     } else if (newPage) {
       
   840         candidate = iWantTheFocus(newPage);
       
   841     }
       
   842     if (!candidate)
       
   843         candidate = nextOrFinishButton;
       
   844     candidate->setFocus();
       
   845 
       
   846     if (wizStyle == QWizard::MacStyle)
       
   847         q->updateGeometry();
       
   848 
       
   849     enableUpdates();
       
   850     updateLayout();
       
   851 
       
   852     emit q->currentIdChanged(current);
       
   853 }
       
   854 
       
   855 // keep in sync with QWizard::WizardButton
       
   856 static const char * const buttonSlots[QWizard::NStandardButtons] = {
       
   857     SLOT(back()), SLOT(next()), SLOT(next()), SLOT(accept()), SLOT(reject()),
       
   858     SIGNAL(helpRequested())
       
   859 };
       
   860 
       
   861 QWizardLayoutInfo QWizardPrivate::layoutInfoForCurrentPage()
       
   862 {
       
   863     Q_Q(QWizard);
       
   864     QStyle *style = q->style();
       
   865 
       
   866     QWizardLayoutInfo info;
       
   867 
       
   868     const int layoutHorizontalSpacing = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
       
   869     info.topLevelMarginLeft = style->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, q);
       
   870     info.topLevelMarginRight = style->pixelMetric(QStyle::PM_LayoutRightMargin, 0, q);
       
   871     info.topLevelMarginTop = style->pixelMetric(QStyle::PM_LayoutTopMargin, 0, q);
       
   872     info.topLevelMarginBottom = style->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, q);
       
   873     info.childMarginLeft = style->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, titleLabel);
       
   874     info.childMarginRight = style->pixelMetric(QStyle::PM_LayoutRightMargin, 0, titleLabel);
       
   875     info.childMarginTop = style->pixelMetric(QStyle::PM_LayoutTopMargin, 0, titleLabel);
       
   876     info.childMarginBottom = style->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, titleLabel);
       
   877     info.hspacing = (layoutHorizontalSpacing == -1)
       
   878         ? style->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Horizontal)
       
   879         : layoutHorizontalSpacing;
       
   880     info.vspacing = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
       
   881     info.buttonSpacing = (layoutHorizontalSpacing == -1)
       
   882         ? style->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal)
       
   883         : layoutHorizontalSpacing;
       
   884 
       
   885     if (wizStyle == QWizard::MacStyle)
       
   886         info.buttonSpacing = 12;
       
   887 
       
   888     info.wizStyle = wizStyle;
       
   889     if ((info.wizStyle == QWizard::AeroStyle)
       
   890 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
   891         && (QVistaHelper::vistaState() == QVistaHelper::Classic || vistaDisabled())
       
   892 #endif
       
   893         )
       
   894         info.wizStyle = QWizard::ModernStyle;
       
   895 
       
   896     QString titleText;
       
   897     QString subTitleText;
       
   898     QPixmap backgroundPixmap;
       
   899     QPixmap watermarkPixmap;
       
   900 
       
   901     if (QWizardPage *page = q->currentPage()) {
       
   902         titleText = page->title();
       
   903         subTitleText = page->subTitle();
       
   904         backgroundPixmap = page->pixmap(QWizard::BackgroundPixmap);
       
   905         watermarkPixmap = page->pixmap(QWizard::WatermarkPixmap);
       
   906     }
       
   907 
       
   908     info.header = (info.wizStyle == QWizard::ClassicStyle || info.wizStyle == QWizard::ModernStyle)
       
   909         && !(opts & QWizard::IgnoreSubTitles) && !subTitleText.isEmpty();
       
   910     info.watermark = (info.wizStyle != QWizard::MacStyle) && (info.wizStyle != QWizard::AeroStyle)
       
   911         && !watermarkPixmap.isNull();
       
   912     info.title = !info.header && !titleText.isEmpty();
       
   913     info.subTitle = !(opts & QWizard::IgnoreSubTitles) && !info.header && !subTitleText.isEmpty();
       
   914     info.extension = info.watermark && (opts & QWizard::ExtendedWatermarkPixmap);
       
   915 
       
   916     return info;
       
   917 }
       
   918 
       
   919 void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
       
   920 {
       
   921     Q_Q(QWizard);
       
   922 
       
   923     /*
       
   924         Start by undoing the main layout.
       
   925     */
       
   926     for (int i = mainLayout->count() - 1; i >= 0; --i) {
       
   927         QLayoutItem *item = mainLayout->takeAt(i);
       
   928         if (item->layout()) {
       
   929             item->layout()->setParent(0);
       
   930         } else {
       
   931             delete item;
       
   932         }
       
   933     }
       
   934     for (int i = mainLayout->columnCount() - 1; i >= 0; --i)
       
   935         mainLayout->setColumnMinimumWidth(i, 0);
       
   936     for (int i = mainLayout->rowCount() - 1; i >= 0; --i)
       
   937         mainLayout->setRowMinimumHeight(i, 0);
       
   938 
       
   939     /*
       
   940         Now, recreate it.
       
   941     */
       
   942 
       
   943     bool mac = (info.wizStyle == QWizard::MacStyle);
       
   944     bool classic = (info.wizStyle == QWizard::ClassicStyle);
       
   945     bool modern = (info.wizStyle == QWizard::ModernStyle);
       
   946     bool aero = (info.wizStyle == QWizard::AeroStyle);
       
   947     int deltaMarginLeft = info.topLevelMarginLeft - info.childMarginLeft;
       
   948     int deltaMarginRight = info.topLevelMarginRight - info.childMarginRight;
       
   949     int deltaMarginTop = info.topLevelMarginTop - info.childMarginTop;
       
   950     int deltaMarginBottom = info.topLevelMarginBottom - info.childMarginBottom;
       
   951     int deltaVSpacing = info.topLevelMarginBottom - info.vspacing;
       
   952 
       
   953     int row = 0;
       
   954     int numColumns;
       
   955     if (mac) {
       
   956         numColumns = 3;
       
   957     } else if (info.watermark) {
       
   958         numColumns = 2;
       
   959     } else {
       
   960         numColumns = 1;
       
   961     }
       
   962     int pageColumn = qMin(1, numColumns - 1);
       
   963 
       
   964     if (mac) {
       
   965         mainLayout->setMargin(0);
       
   966         mainLayout->setSpacing(0);
       
   967         buttonLayout->setContentsMargins(MacLayoutLeftMargin, MacButtonTopMargin, MacLayoutRightMargin, MacLayoutBottomMargin);
       
   968         pageVBoxLayout->setMargin(7);
       
   969     } else {
       
   970         if (modern) {
       
   971             mainLayout->setMargin(0);
       
   972             mainLayout->setSpacing(0);
       
   973             pageVBoxLayout->setContentsMargins(deltaMarginLeft, deltaMarginTop,
       
   974                                                deltaMarginRight, deltaMarginBottom);
       
   975             buttonLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop,
       
   976                                              info.topLevelMarginRight, info.topLevelMarginBottom);
       
   977         } else {
       
   978             mainLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop,
       
   979                                            info.topLevelMarginRight, info.topLevelMarginBottom);
       
   980             mainLayout->setHorizontalSpacing(info.hspacing);
       
   981             mainLayout->setVerticalSpacing(info.vspacing);
       
   982             pageVBoxLayout->setContentsMargins(0, 0, 0, 0);
       
   983             buttonLayout->setContentsMargins(0, 0, 0, 0);
       
   984         }
       
   985     }
       
   986     buttonLayout->setSpacing(info.buttonSpacing);
       
   987 
       
   988     if (info.header) {
       
   989         if (!headerWidget)
       
   990             headerWidget = new QWizardHeader(antiFlickerWidget);
       
   991         headerWidget->setAutoFillBackground(modern);
       
   992         mainLayout->addWidget(headerWidget, row++, 0, 1, numColumns);
       
   993     }
       
   994     if (headerWidget)
       
   995         headerWidget->setVisible(info.header);
       
   996 
       
   997     int watermarkStartRow = row;
       
   998 
       
   999     if (mac)
       
  1000         mainLayout->setRowMinimumHeight(row++, 10);
       
  1001 
       
  1002     if (info.title) {
       
  1003         if (!titleLabel) {
       
  1004             titleLabel = new QLabel(antiFlickerWidget);
       
  1005             titleLabel->setBackgroundRole(QPalette::Base);
       
  1006             titleLabel->setWordWrap(true);
       
  1007         }
       
  1008 
       
  1009         QFont titleFont = q->font();
       
  1010         titleFont.setPointSize(titleFont.pointSize() + (mac ? 3 : 4));
       
  1011         titleFont.setBold(true);
       
  1012         titleLabel->setPalette(QPalette());
       
  1013 
       
  1014         if (aero) {
       
  1015             // ### hardcoded for now:
       
  1016             titleFont = QFont(QLatin1String("Segoe UI"), 12);
       
  1017             QPalette pal(titleLabel->palette());
       
  1018             pal.setColor(QPalette::Text, "#003399");
       
  1019             titleLabel->setPalette(pal);
       
  1020         }
       
  1021 
       
  1022         titleLabel->setFont(titleFont);
       
  1023         const int aeroTitleIndent = 25; // ### hardcoded for now - should be calculated somehow
       
  1024         if (aero)
       
  1025             titleLabel->setIndent(aeroTitleIndent);
       
  1026         else if (mac)
       
  1027             titleLabel->setIndent(2);
       
  1028         else if (classic)
       
  1029             titleLabel->setIndent(info.childMarginLeft);
       
  1030         else
       
  1031             titleLabel->setIndent(info.topLevelMarginLeft);
       
  1032         if (modern) {
       
  1033             if (!placeholderWidget1) {
       
  1034                 placeholderWidget1 = new QWidget(antiFlickerWidget);
       
  1035                 placeholderWidget1->setBackgroundRole(QPalette::Base);
       
  1036             }
       
  1037             placeholderWidget1->setFixedHeight(info.topLevelMarginLeft + 2);
       
  1038             mainLayout->addWidget(placeholderWidget1, row++, pageColumn);
       
  1039         }
       
  1040         mainLayout->addWidget(titleLabel, row++, pageColumn);
       
  1041         if (modern) {
       
  1042             if (!placeholderWidget2) {
       
  1043                 placeholderWidget2 = new QWidget(antiFlickerWidget);
       
  1044                 placeholderWidget2->setBackgroundRole(QPalette::Base);
       
  1045             }
       
  1046             placeholderWidget2->setFixedHeight(5);
       
  1047             mainLayout->addWidget(placeholderWidget2, row++, pageColumn);
       
  1048         }
       
  1049         if (mac)
       
  1050             mainLayout->setRowMinimumHeight(row++, 7);
       
  1051     }
       
  1052     if (placeholderWidget1)
       
  1053         placeholderWidget1->setVisible(info.title && modern);
       
  1054     if (placeholderWidget2)
       
  1055         placeholderWidget2->setVisible(info.title && modern);
       
  1056 
       
  1057     if (info.subTitle) {
       
  1058         if (!subTitleLabel) {
       
  1059             subTitleLabel = new QLabel(pageFrame);
       
  1060             subTitleLabel->setWordWrap(true);
       
  1061 
       
  1062             subTitleLabel->setContentsMargins(info.childMarginLeft , 0,
       
  1063                                               info.childMarginRight , 0);
       
  1064 
       
  1065             pageVBoxLayout->insertWidget(1, subTitleLabel);
       
  1066         }
       
  1067     }
       
  1068 
       
  1069     // ### try to replace with margin.
       
  1070     changeSpacerSize(pageVBoxLayout, 0, 0, info.subTitle ? info.childMarginLeft : 0);
       
  1071 
       
  1072     int hMargin = mac ? 1 : 0;
       
  1073     int vMargin = hMargin;
       
  1074 
       
  1075     pageFrame->setFrameStyle(mac ? (QFrame::Box | QFrame::Raised) : QFrame::NoFrame);
       
  1076     pageFrame->setLineWidth(0);
       
  1077     pageFrame->setMidLineWidth(hMargin);
       
  1078 
       
  1079     if (info.header) {
       
  1080         if (modern) {
       
  1081             hMargin = info.topLevelMarginLeft;
       
  1082             vMargin = deltaMarginBottom;
       
  1083         } else if (classic) {
       
  1084             hMargin = deltaMarginLeft + ClassicHMargin;
       
  1085             vMargin = 0;
       
  1086         }
       
  1087     }
       
  1088 
       
  1089     if (aero) {
       
  1090         int leftMargin   = 18; // ### hardcoded for now - should be calculated somehow
       
  1091         int topMargin    = vMargin;
       
  1092         int rightMargin  = hMargin; // ### for now
       
  1093         int bottomMargin = vMargin;
       
  1094         pageFrame->setContentsMargins(leftMargin, topMargin, rightMargin, bottomMargin);
       
  1095     } else {
       
  1096         pageFrame->setContentsMargins(hMargin, vMargin, hMargin, vMargin);
       
  1097     }
       
  1098 
       
  1099     if (info.watermark && !watermarkLabel) {
       
  1100         watermarkLabel = new QLabel(antiFlickerWidget);
       
  1101         watermarkLabel->setBackgroundRole(QPalette::Base);
       
  1102         watermarkLabel->setMinimumHeight(1);
       
  1103         watermarkLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
       
  1104         watermarkLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
       
  1105     }
       
  1106 
       
  1107     //bool wasSemiTransparent = pageFrame->testAttribute(Qt::WA_SetPalette);
       
  1108     const bool wasSemiTransparent =
       
  1109         pageFrame->palette().brush(QPalette::Window).color().alpha() < 255
       
  1110         || pageFrame->palette().brush(QPalette::Base).color().alpha() < 255;
       
  1111     if (mac) {
       
  1112         if (!wasSemiTransparent) {
       
  1113             QPalette pal = pageFrame->palette();
       
  1114             pal.setBrush(QPalette::Window, QColor(255, 255, 255, 153));
       
  1115             // ### The next line is required to ensure visual semitransparency when
       
  1116             // ### switching from ModernStyle to MacStyle. See TAG1 below.
       
  1117             pal.setBrush(QPalette::Base, QColor(255, 255, 255, 153));
       
  1118             pageFrame->setPalette(pal);
       
  1119             pageFrame->setAutoFillBackground(true);
       
  1120             antiFlickerWidget->setAutoFillBackground(false);
       
  1121         }
       
  1122     } else {
       
  1123         if (wasSemiTransparent)
       
  1124             pageFrame->setPalette(QPalette());
       
  1125 
       
  1126         bool baseBackground = (modern && !info.header); // ### TAG1
       
  1127         pageFrame->setBackgroundRole(baseBackground ? QPalette::Base : QPalette::Window);
       
  1128 
       
  1129         if (titleLabel)
       
  1130             titleLabel->setAutoFillBackground(baseBackground);
       
  1131         pageFrame->setAutoFillBackground(baseBackground);
       
  1132         if (watermarkLabel)
       
  1133             watermarkLabel->setAutoFillBackground(baseBackground);
       
  1134         if (placeholderWidget1)
       
  1135             placeholderWidget1->setAutoFillBackground(baseBackground);
       
  1136         if (placeholderWidget2)
       
  1137             placeholderWidget2->setAutoFillBackground(baseBackground);
       
  1138 
       
  1139         if (aero) {
       
  1140             QPalette pal = pageFrame->palette();
       
  1141             pal.setBrush(QPalette::Window, QColor(255, 255, 255));
       
  1142             pageFrame->setPalette(pal);
       
  1143             pageFrame->setAutoFillBackground(true);
       
  1144             pal = antiFlickerWidget->palette();
       
  1145             pal.setBrush(QPalette::Window, QColor(255, 255, 255));
       
  1146             antiFlickerWidget->setPalette(pal);
       
  1147             antiFlickerWidget->setAutoFillBackground(true);
       
  1148         }
       
  1149     }
       
  1150 
       
  1151     mainLayout->addWidget(pageFrame, row++, pageColumn);
       
  1152 
       
  1153     int watermarkEndRow = row;
       
  1154     if (classic)
       
  1155         mainLayout->setRowMinimumHeight(row++, deltaVSpacing);
       
  1156 
       
  1157     if (aero) {
       
  1158         buttonLayout->setContentsMargins(9, 9, 9, 9);
       
  1159         mainLayout->setContentsMargins(0, 11, 0, 0);
       
  1160     }
       
  1161 
       
  1162     int buttonStartColumn = info.extension ? 1 : 0;
       
  1163     int buttonNumColumns = info.extension ? 1 : numColumns;
       
  1164 
       
  1165     if (classic || modern) {
       
  1166         if (!bottomRuler)
       
  1167             bottomRuler = new QWizardRuler(antiFlickerWidget);
       
  1168         mainLayout->addWidget(bottomRuler, row++, buttonStartColumn, 1, buttonNumColumns);
       
  1169     }
       
  1170 
       
  1171     if (classic)
       
  1172         mainLayout->setRowMinimumHeight(row++, deltaVSpacing);
       
  1173 
       
  1174     mainLayout->addLayout(buttonLayout, row++, buttonStartColumn, 1, buttonNumColumns);
       
  1175 
       
  1176     if (info.watermark) {
       
  1177         if (info.extension)
       
  1178             watermarkEndRow = row;
       
  1179         mainLayout->addWidget(watermarkLabel, watermarkStartRow, 0,
       
  1180                               watermarkEndRow - watermarkStartRow, 1);
       
  1181     }
       
  1182 
       
  1183     mainLayout->setColumnMinimumWidth(0, mac && !info.watermark ? 181 : 0);
       
  1184     if (mac)
       
  1185         mainLayout->setColumnMinimumWidth(2, 21);
       
  1186 
       
  1187     if (headerWidget)
       
  1188         headerWidget->setVisible(info.header);
       
  1189     if (titleLabel)
       
  1190         titleLabel->setVisible(info.title);
       
  1191     if (subTitleLabel)
       
  1192         subTitleLabel->setVisible(info.subTitle);
       
  1193     if (bottomRuler)
       
  1194         bottomRuler->setVisible(classic || modern);
       
  1195     if (watermarkLabel)
       
  1196         watermarkLabel->setVisible(info.watermark);
       
  1197 
       
  1198     layoutInfo = info;
       
  1199 }
       
  1200 
       
  1201 void QWizardPrivate::updateLayout()
       
  1202 {
       
  1203     Q_Q(QWizard);
       
  1204 
       
  1205     disableUpdates();
       
  1206 
       
  1207     QWizardLayoutInfo info = layoutInfoForCurrentPage();
       
  1208     if (layoutInfo != info)
       
  1209         recreateLayout(info);
       
  1210     QWizardPage *page = q->currentPage();
       
  1211 
       
  1212     // If the page can expand vertically, let it stretch "infinitely" more
       
  1213     // than the QSpacerItem at the bottom. Otherwise, let the QSpacerItem
       
  1214     // stretch "infinitely" more than the page. Change the bottom item's
       
  1215     // policy accordingly. The case that the page has no layout is basically
       
  1216     // for Designer, only.
       
  1217     if (page) {
       
  1218         bool expandPage = !page->layout();
       
  1219         if (!expandPage) {
       
  1220             const QLayoutItem *pageItem = pageVBoxLayout->itemAt(pageVBoxLayout->indexOf(page));
       
  1221             expandPage = pageItem->expandingDirections() & Qt::Vertical;
       
  1222         }
       
  1223         QSpacerItem *bottomSpacer = pageVBoxLayout->itemAt(pageVBoxLayout->count() -  1)->spacerItem();
       
  1224         Q_ASSERT(bottomSpacer);
       
  1225         bottomSpacer->changeSize(0, 0, QSizePolicy::Ignored, expandPage ? QSizePolicy::Ignored : QSizePolicy::MinimumExpanding);
       
  1226         pageVBoxLayout->invalidate();
       
  1227     }
       
  1228 
       
  1229     if (info.header) {
       
  1230         Q_ASSERT(page);
       
  1231         headerWidget->setup(info, page->title(), page->subTitle(),
       
  1232                             page->pixmap(QWizard::LogoPixmap), page->pixmap(QWizard::BannerPixmap),
       
  1233                             titleFmt, subTitleFmt);
       
  1234     }
       
  1235 
       
  1236     if (info.watermark) {
       
  1237         Q_ASSERT(page);
       
  1238         watermarkLabel->setPixmap(page->pixmap(QWizard::WatermarkPixmap));
       
  1239     }
       
  1240     if (info.title) {
       
  1241         Q_ASSERT(page);
       
  1242         titleLabel->setTextFormat(titleFmt);
       
  1243         titleLabel->setText(page->title());
       
  1244     }
       
  1245     if (info.subTitle) {
       
  1246         Q_ASSERT(page);
       
  1247         subTitleLabel->setTextFormat(subTitleFmt);
       
  1248         subTitleLabel->setText(page->subTitle());
       
  1249     }
       
  1250 
       
  1251     enableUpdates();
       
  1252     updateMinMaxSizes(info);
       
  1253 }
       
  1254 
       
  1255 void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
       
  1256 {
       
  1257     Q_Q(QWizard);
       
  1258 
       
  1259     int extraHeight = 0;
       
  1260 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1261     if (isVistaThemeEnabled())
       
  1262         extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset();
       
  1263 #endif
       
  1264     QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight);
       
  1265     QSize maximumSize = mainLayout->totalMaximumSize();
       
  1266     if (info.header && headerWidget->maximumWidth() != QWIDGETSIZE_MAX) {
       
  1267         minimumSize.setWidth(headerWidget->maximumWidth());
       
  1268         maximumSize.setWidth(headerWidget->maximumWidth());
       
  1269     }
       
  1270     if (info.watermark) {
       
  1271         minimumSize.setHeight(mainLayout->totalSizeHint().height());
       
  1272         maximumSize.setHeight(mainLayout->totalSizeHint().height());
       
  1273     }
       
  1274     if (q->minimumWidth() == minimumWidth) {
       
  1275         minimumWidth = minimumSize.width();
       
  1276         q->setMinimumWidth(minimumWidth);
       
  1277     }
       
  1278     if (q->minimumHeight() == minimumHeight) {
       
  1279         minimumHeight = minimumSize.height();
       
  1280         q->setMinimumHeight(minimumHeight);
       
  1281     }
       
  1282     if (q->maximumWidth() == maximumWidth) {
       
  1283         maximumWidth = maximumSize.width();
       
  1284         q->setMaximumWidth(maximumWidth);
       
  1285     }
       
  1286     if (q->maximumHeight() == maximumHeight) {
       
  1287         maximumHeight = maximumSize.height();
       
  1288         q->setMaximumHeight(maximumHeight);
       
  1289     }
       
  1290 }
       
  1291 
       
  1292 void QWizardPrivate::updateCurrentPage()
       
  1293 {
       
  1294     Q_Q(QWizard);
       
  1295     if (q->currentPage()) {
       
  1296         canContinue = (q->nextId() != -1);
       
  1297         canFinish = q->currentPage()->isFinalPage();
       
  1298     } else {
       
  1299         canContinue = false;
       
  1300         canFinish = false;
       
  1301     }
       
  1302     _q_updateButtonStates();
       
  1303     updateButtonTexts();
       
  1304 }
       
  1305 
       
  1306 bool QWizardPrivate::ensureButton(QWizard::WizardButton which) const
       
  1307 {
       
  1308     Q_Q(const QWizard);
       
  1309     if (uint(which) >= QWizard::NButtons)
       
  1310         return false;
       
  1311 
       
  1312     if (!btns[which]) {
       
  1313         QPushButton *pushButton = new QPushButton(antiFlickerWidget);
       
  1314         QStyle *style = q->style();
       
  1315         if (style != QApplication::style()) // Propagate style
       
  1316             pushButton->setStyle(style);
       
  1317         // Make navigation buttons detectable as passive interactor in designer
       
  1318         switch (which) {
       
  1319             case QWizard::CommitButton:
       
  1320             case QWizard::FinishButton:
       
  1321             case QWizard::CancelButton:
       
  1322             break;
       
  1323         default: {
       
  1324             QString objectName = QLatin1String("__qt__passive_wizardbutton");
       
  1325             objectName += QString::number(which);
       
  1326             pushButton->setObjectName(objectName);
       
  1327         }
       
  1328             break;
       
  1329         }
       
  1330 #ifdef Q_WS_MAC
       
  1331         pushButton->setAutoDefault(false);
       
  1332 #endif
       
  1333         pushButton->hide();
       
  1334 #ifdef Q_CC_HPACC
       
  1335         const_cast<QWizardPrivate *>(this)->btns[which] = pushButton;
       
  1336 #else
       
  1337         btns[which] = pushButton;
       
  1338 #endif
       
  1339         if (which < QWizard::NStandardButtons)
       
  1340             pushButton->setText(buttonDefaultText(wizStyle, which, this));
       
  1341 
       
  1342 #ifdef QT_SOFTKEYS_ENABLED
       
  1343         QAction *softKey = new QAction(pushButton->text(), pushButton);
       
  1344         QAction::SoftKeyRole softKeyRole;
       
  1345         switch(which) {
       
  1346         case QWizard::NextButton:
       
  1347         case QWizard::FinishButton:
       
  1348         case QWizard::CancelButton:
       
  1349             softKeyRole = QAction::NegativeSoftKey;
       
  1350             break;
       
  1351         case QWizard::BackButton:
       
  1352         case QWizard::CommitButton:
       
  1353         case QWizard::HelpButton:
       
  1354         case QWizard::CustomButton1:
       
  1355         case QWizard::CustomButton2:
       
  1356         case QWizard::CustomButton3:
       
  1357         default:
       
  1358             softKeyRole = QAction::PositiveSoftKey;
       
  1359             break;
       
  1360         }
       
  1361         softKey->setSoftKeyRole(softKeyRole);
       
  1362         softKeys[which] = softKey;
       
  1363 #endif
       
  1364         connectButton(which);
       
  1365     }
       
  1366     return true;
       
  1367 }
       
  1368 
       
  1369 void QWizardPrivate::connectButton(QWizard::WizardButton which) const
       
  1370 {
       
  1371     Q_Q(const QWizard);
       
  1372     if (which < QWizard::NStandardButtons) {
       
  1373         QObject::connect(btns[which], SIGNAL(clicked()), q, buttonSlots[which]);
       
  1374     } else {
       
  1375         QObject::connect(btns[which], SIGNAL(clicked()), q, SLOT(_q_emitCustomButtonClicked()));
       
  1376     }
       
  1377 
       
  1378 #ifdef QT_SOFTKEYS_ENABLED
       
  1379     QObject::connect(softKeys[which], SIGNAL(triggered()), btns[which], SIGNAL(clicked()));
       
  1380 #endif
       
  1381 }
       
  1382 
       
  1383 void QWizardPrivate::updateButtonTexts()
       
  1384 {
       
  1385     Q_Q(QWizard);
       
  1386     for (int i = 0; i < QWizard::NButtons; ++i) {
       
  1387         if (btns[i]) {
       
  1388             if (q->currentPage() && (q->currentPage()->d_func()->buttonCustomTexts.contains(i)))
       
  1389                 btns[i]->setText(q->currentPage()->d_func()->buttonCustomTexts.value(i));
       
  1390             else if (buttonCustomTexts.contains(i))
       
  1391                 btns[i]->setText(buttonCustomTexts.value(i));
       
  1392             else if (i < QWizard::NStandardButtons)
       
  1393                 btns[i]->setText(buttonDefaultText(wizStyle, i, this));
       
  1394 #ifdef QT_SOFTKEYS_ENABLED
       
  1395             softKeys[i]->setText(btns[i]->text());
       
  1396 #endif
       
  1397         }
       
  1398     }
       
  1399 }
       
  1400 
       
  1401 void QWizardPrivate::updateButtonLayout()
       
  1402 {
       
  1403     if (buttonsHaveCustomLayout) {
       
  1404         QVarLengthArray<QWizard::WizardButton> array(buttonsCustomLayout.count());
       
  1405         for (int i = 0; i < buttonsCustomLayout.count(); ++i)
       
  1406             array[i] = buttonsCustomLayout.at(i);
       
  1407         setButtonLayout(array.constData(), array.count());
       
  1408     } else {
       
  1409         // Positions:
       
  1410         //     Help Stretch Custom1 Custom2 Custom3 Cancel Back Next Commit Finish Cancel Help
       
  1411 
       
  1412         const int ArraySize = 12;
       
  1413         QWizard::WizardButton array[ArraySize];
       
  1414         memset(array, -1, sizeof(array));
       
  1415         Q_ASSERT(array[0] == QWizard::NoButton);
       
  1416 
       
  1417         if (opts & QWizard::HaveHelpButton) {
       
  1418             int i = (opts & QWizard::HelpButtonOnRight) ? 11 : 0;
       
  1419             array[i] = QWizard::HelpButton;
       
  1420         }
       
  1421         array[1] = QWizard::Stretch;
       
  1422         if (opts & QWizard::HaveCustomButton1)
       
  1423             array[2] = QWizard::CustomButton1;
       
  1424         if (opts & QWizard::HaveCustomButton2)
       
  1425             array[3] = QWizard::CustomButton2;
       
  1426         if (opts & QWizard::HaveCustomButton3)
       
  1427             array[4] = QWizard::CustomButton3;
       
  1428 
       
  1429         if (!(opts & QWizard::NoCancelButton)) {
       
  1430             int i = (opts & QWizard::CancelButtonOnLeft) ? 5 : 10;
       
  1431             array[i] = QWizard::CancelButton;
       
  1432         }
       
  1433         array[6] = QWizard::BackButton;
       
  1434         array[7] = QWizard::NextButton;
       
  1435         array[8] = QWizard::CommitButton;
       
  1436         array[9] = QWizard::FinishButton;
       
  1437 
       
  1438         setButtonLayout(array, ArraySize);
       
  1439     }
       
  1440 }
       
  1441 
       
  1442 void QWizardPrivate::setButtonLayout(const QWizard::WizardButton *array, int size)
       
  1443 {
       
  1444     QWidget *prev = pageFrame;
       
  1445 
       
  1446     for (int i = buttonLayout->count() - 1; i >= 0; --i) {
       
  1447         QLayoutItem *item = buttonLayout->takeAt(i);
       
  1448         if (QWidget *widget = item->widget())
       
  1449             widget->hide();
       
  1450         delete item;
       
  1451     }
       
  1452 
       
  1453     for (int i = 0; i < size; ++i) {
       
  1454         QWizard::WizardButton which = array[i];
       
  1455         if (which == QWizard::Stretch) {
       
  1456             buttonLayout->addStretch(1);
       
  1457         } else if (which != QWizard::NoButton) {
       
  1458             ensureButton(which);
       
  1459             buttonLayout->addWidget(btns[which]);
       
  1460 
       
  1461             // Back, Next, Commit, and Finish are handled in _q_updateButtonStates()
       
  1462             if (which != QWizard::BackButton && which != QWizard::NextButton
       
  1463                 && which != QWizard::CommitButton && which != QWizard::FinishButton)
       
  1464                 btns[which]->show();
       
  1465 
       
  1466             if (prev)
       
  1467                 QWidget::setTabOrder(prev, btns[which]);
       
  1468             prev = btns[which];
       
  1469         }
       
  1470     }
       
  1471 
       
  1472     _q_updateButtonStates();
       
  1473 }
       
  1474 
       
  1475 bool QWizardPrivate::buttonLayoutContains(QWizard::WizardButton which)
       
  1476 {
       
  1477     return !buttonsHaveCustomLayout || buttonsCustomLayout.contains(which);
       
  1478 }
       
  1479 
       
  1480 void QWizardPrivate::updatePixmap(QWizard::WizardPixmap which)
       
  1481 {
       
  1482     Q_Q(QWizard);
       
  1483     if (which == QWizard::BackgroundPixmap) {
       
  1484         if (wizStyle == QWizard::MacStyle) {
       
  1485             q->update();
       
  1486             q->updateGeometry();
       
  1487         }
       
  1488     } else {
       
  1489         updateLayout();
       
  1490     }
       
  1491 }
       
  1492 
       
  1493 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1494 bool QWizardPrivate::vistaDisabled() const
       
  1495 {
       
  1496     Q_Q(const QWizard);
       
  1497     const QVariant v = q->property("_q_wizard_vista_off");
       
  1498     return v.isValid() && v.toBool();
       
  1499 }
       
  1500 
       
  1501 bool QWizardPrivate::isVistaThemeEnabled(QVistaHelper::VistaState state) const
       
  1502 {
       
  1503     return wizStyle == QWizard::AeroStyle
       
  1504         && QVistaHelper::vistaState() == state
       
  1505         && !vistaDisabled();
       
  1506 }
       
  1507 
       
  1508 void QWizardPrivate::handleAeroStyleChange()
       
  1509 {
       
  1510     Q_Q(QWizard);
       
  1511 
       
  1512     if (inHandleAeroStyleChange)
       
  1513         return; // prevent recursion
       
  1514     inHandleAeroStyleChange = true;
       
  1515 
       
  1516     vistaHelper->disconnectBackButton();
       
  1517     q->removeEventFilter(vistaHelper);
       
  1518 
       
  1519     if (isVistaThemeEnabled()) {
       
  1520         if (isVistaThemeEnabled(QVistaHelper::VistaAero)) {
       
  1521             vistaHelper->setDWMTitleBar(QVistaHelper::ExtendedTitleBar);
       
  1522             q->installEventFilter(vistaHelper);
       
  1523             q->setMouseTracking(true);
       
  1524             antiFlickerWidget->move(0, vistaHelper->titleBarSize() + vistaHelper->topOffset());
       
  1525             vistaHelper->backButton()->move(
       
  1526                 0, vistaHelper->topOffset() // ### should ideally work without the '+ 1'
       
  1527                 - qMin(vistaHelper->topOffset(), vistaHelper->topPadding() + 1));
       
  1528         } else {
       
  1529             vistaHelper->setDWMTitleBar(QVistaHelper::NormalTitleBar);
       
  1530             q->setMouseTracking(true);
       
  1531             antiFlickerWidget->move(0, vistaHelper->topOffset());
       
  1532             vistaHelper->backButton()->move(0, -1); // ### should ideally work with (0, 0)
       
  1533         }
       
  1534         vistaHelper->setTitleBarIconAndCaptionVisible(false);
       
  1535         QObject::connect(
       
  1536             vistaHelper->backButton(), SIGNAL(clicked()), q, buttonSlots[QWizard::BackButton]);
       
  1537         vistaHelper->backButton()->show();
       
  1538     } else {
       
  1539         q->setMouseTracking(true); // ### original value possibly different
       
  1540         q->unsetCursor(); // ### ditto
       
  1541         antiFlickerWidget->move(0, 0);
       
  1542         vistaHelper->hideBackButton();
       
  1543         vistaHelper->setTitleBarIconAndCaptionVisible(true);
       
  1544     }
       
  1545 
       
  1546     _q_updateButtonStates();
       
  1547 
       
  1548     if (q->isVisible())
       
  1549         vistaHelper->setWindowPosHack();
       
  1550 
       
  1551     inHandleAeroStyleChange = false;
       
  1552 }
       
  1553 #endif
       
  1554 
       
  1555 bool QWizardPrivate::isVistaThemeEnabled() const
       
  1556 {
       
  1557 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1558     return isVistaThemeEnabled(QVistaHelper::VistaAero)
       
  1559         || isVistaThemeEnabled(QVistaHelper::VistaBasic);
       
  1560 #else
       
  1561     return false;
       
  1562 #endif
       
  1563 }
       
  1564 
       
  1565 void QWizardPrivate::disableUpdates()
       
  1566 {
       
  1567     Q_Q(QWizard);
       
  1568     if (disableUpdatesCount++ == 0) {
       
  1569         q->setUpdatesEnabled(false);
       
  1570         antiFlickerWidget->hide();
       
  1571     }
       
  1572 }
       
  1573 
       
  1574 void QWizardPrivate::enableUpdates()
       
  1575 {
       
  1576     Q_Q(QWizard);
       
  1577     if (--disableUpdatesCount == 0) {
       
  1578         antiFlickerWidget->show();
       
  1579         q->setUpdatesEnabled(true);
       
  1580     }
       
  1581 }
       
  1582 
       
  1583 void QWizardPrivate::_q_emitCustomButtonClicked()
       
  1584 {
       
  1585     Q_Q(QWizard);
       
  1586     QObject *button = q->sender();
       
  1587     for (int i = QWizard::NStandardButtons; i < QWizard::NButtons; ++i) {
       
  1588         if (btns[i] == button) {
       
  1589             emit q->customButtonClicked(QWizard::WizardButton(i));
       
  1590             break;
       
  1591         }
       
  1592     }
       
  1593 }
       
  1594 
       
  1595 void QWizardPrivate::_q_updateButtonStates()
       
  1596 {
       
  1597     Q_Q(QWizard);
       
  1598 
       
  1599     disableUpdates();
       
  1600 
       
  1601     const QWizardPage *page = q->currentPage();
       
  1602     bool complete = page && page->isComplete();
       
  1603 
       
  1604     btn.back->setEnabled(history.count() > 1
       
  1605                          && !q->page(history.at(history.count() - 2))->isCommitPage()
       
  1606                          && (!canFinish || !(opts & QWizard::DisabledBackButtonOnLastPage)));
       
  1607     btn.next->setEnabled(canContinue && complete);
       
  1608     btn.commit->setEnabled(canContinue && complete);
       
  1609     btn.finish->setEnabled(canFinish && complete);
       
  1610 
       
  1611     const bool backButtonVisible = buttonLayoutContains(QWizard::BackButton)
       
  1612         && (history.count() > 1 || !(opts & QWizard::NoBackButtonOnStartPage))
       
  1613         && (canContinue || !(opts & QWizard::NoBackButtonOnLastPage));
       
  1614     bool commitPage = page && page->isCommitPage();
       
  1615     btn.back->setVisible(backButtonVisible);
       
  1616     btn.next->setVisible(buttonLayoutContains(QWizard::NextButton) && !commitPage
       
  1617                          && (canContinue || (opts & QWizard::HaveNextButtonOnLastPage)));
       
  1618     btn.commit->setVisible(buttonLayoutContains(QWizard::CommitButton) && commitPage
       
  1619                            && canContinue);
       
  1620     btn.finish->setVisible(buttonLayoutContains(QWizard::FinishButton)
       
  1621                            && (canFinish || (opts & QWizard::HaveFinishButtonOnEarlyPages)));
       
  1622 
       
  1623     bool useDefault = !(opts & QWizard::NoDefaultButton);
       
  1624     if (QPushButton *nextPush = qobject_cast<QPushButton *>(btn.next))
       
  1625         nextPush->setDefault(canContinue && useDefault && !commitPage);
       
  1626     if (QPushButton *commitPush = qobject_cast<QPushButton *>(btn.commit))
       
  1627         commitPush->setDefault(canContinue && useDefault && commitPage);
       
  1628     if (QPushButton *finishPush = qobject_cast<QPushButton *>(btn.finish))
       
  1629         finishPush->setDefault(!canContinue && useDefault);
       
  1630 
       
  1631 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1632     if (isVistaThemeEnabled()) {
       
  1633         vistaHelper->backButton()->setEnabled(btn.back->isEnabled());
       
  1634         vistaHelper->backButton()->setVisible(backButtonVisible);
       
  1635         btn.back->setVisible(false);
       
  1636     }
       
  1637 #endif
       
  1638 
       
  1639 #ifdef QT_SOFTKEYS_ENABLED
       
  1640     QAbstractButton *wizardButton;
       
  1641     for (int i = 0; i < QWizard::NButtons; ++i) {
       
  1642         wizardButton = btns[i];
       
  1643         if (wizardButton && !wizardButton->testAttribute(Qt::WA_WState_Hidden)) {
       
  1644             wizardButton->hide();
       
  1645             q->addAction(softKeys[i]);
       
  1646         } else {
       
  1647             q->removeAction(softKeys[i]);
       
  1648         }
       
  1649     }
       
  1650 #endif
       
  1651 
       
  1652     enableUpdates();
       
  1653 }
       
  1654 
       
  1655 void QWizardPrivate::_q_handleFieldObjectDestroyed(QObject *object)
       
  1656 {
       
  1657     QVector<QWizardField>::iterator it = fields.begin();
       
  1658     while (it != fields.end()) {
       
  1659         const QWizardField &field = *it;
       
  1660         if (field.object == object) {
       
  1661             fieldIndexMap.remove(field.name);
       
  1662             it = fields.erase(it);
       
  1663         } else {
       
  1664             ++it;
       
  1665         }
       
  1666     }
       
  1667 }
       
  1668 
       
  1669 void QWizardPrivate::setStyle(QStyle *style)
       
  1670 {
       
  1671     for (int i = 0; i < QWizard::NButtons; i++)
       
  1672         if (btns[i])
       
  1673             btns[i]->setStyle(style);
       
  1674     const PageMap::const_iterator pcend = pageMap.constEnd();
       
  1675     for (PageMap::const_iterator it = pageMap.constBegin(); it != pcend; ++it)
       
  1676         it.value()->setStyle(style);
       
  1677 }
       
  1678 
       
  1679 #ifdef Q_WS_MAC
       
  1680 
       
  1681 QPixmap QWizardPrivate::findDefaultBackgroundPixmap()
       
  1682 {
       
  1683     QCFType<CFURLRef> url;
       
  1684     const int ExpectedImageWidth = 242;
       
  1685     const int ExpectedImageHeight = 414;
       
  1686     if (LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.KeyboardSetupAssistant"),
       
  1687                                  0, 0, &url) == noErr) {
       
  1688         QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, url);
       
  1689         if (bundle) {
       
  1690             url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("tif"), 0);
       
  1691             if (url) {
       
  1692                 QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0);
       
  1693                 QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
       
  1694                 if (image) {
       
  1695                     int width = CGImageGetWidth(image);
       
  1696                     int height = CGImageGetHeight(image);
       
  1697                     if (width == ExpectedImageWidth && height == ExpectedImageHeight)
       
  1698                         return QPixmap::fromMacCGImageRef(image);
       
  1699                 }
       
  1700             }
       
  1701         }
       
  1702     }
       
  1703     return QPixmap();
       
  1704 
       
  1705 }
       
  1706 
       
  1707 #endif
       
  1708 
       
  1709 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1710 void QWizardAntiFlickerWidget::paintEvent(QPaintEvent *)
       
  1711 {
       
  1712     if (wizardPrivate->isVistaThemeEnabled()) {
       
  1713         int leftMargin, topMargin, rightMargin, bottomMargin;
       
  1714         wizardPrivate->buttonLayout->getContentsMargins(
       
  1715             &leftMargin, &topMargin, &rightMargin, &bottomMargin);
       
  1716         const int buttonLayoutTop = wizardPrivate->buttonLayout->contentsRect().top() - topMargin;
       
  1717         QPainter painter(this);
       
  1718         const QBrush brush(QColor(240, 240, 240)); // ### hardcoded for now
       
  1719         painter.fillRect(0, buttonLayoutTop, width(), height() - buttonLayoutTop, brush);
       
  1720         painter.setPen(QPen(QBrush(QColor(223, 223, 223)), 0)); // ### hardcoded for now
       
  1721         painter.drawLine(0, buttonLayoutTop, width(), buttonLayoutTop);
       
  1722         if (wizardPrivate->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
       
  1723             if (window()->isActiveWindow())
       
  1724                 painter.setPen(QPen(QBrush(QColor(169, 191, 214)), 0)); // ### hardcoded for now
       
  1725             else
       
  1726                 painter.setPen(QPen(QBrush(QColor(182, 193, 204)), 0)); // ### hardcoded for now
       
  1727             painter.drawLine(0, 0, width(), 0);
       
  1728         }
       
  1729     }
       
  1730 }
       
  1731 #endif
       
  1732 
       
  1733 /*!
       
  1734     \class QWizard
       
  1735     \since 4.3
       
  1736     \brief The QWizard class provides a framework for wizards.
       
  1737 
       
  1738     A wizard (also called an assistant on Mac OS X) is a special type
       
  1739     of input dialog that consists of a sequence of pages. A wizard's
       
  1740     purpose is to guide the user through a process step by step.
       
  1741     Wizards are useful for complex or infrequent tasks that users may
       
  1742     find difficult to learn.
       
  1743 
       
  1744     QWizard inherits QDialog and represents a wizard. Each page is a
       
  1745     QWizardPage (a QWidget subclass). To create your own wizards, you
       
  1746     can use these classes directly, or you can subclass them for more
       
  1747     control.
       
  1748 
       
  1749     Topics:
       
  1750 
       
  1751     \tableofcontents
       
  1752 
       
  1753     \section1 A Trivial Example
       
  1754 
       
  1755     The following example illustrates how to create wizard pages and
       
  1756     add them to a wizard. For more advanced examples, see
       
  1757     \l{dialogs/classwizard}{Class Wizard} and \l{dialogs/licensewizard}{License
       
  1758     Wizard}.
       
  1759 
       
  1760     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 1
       
  1761     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 3
       
  1762     \dots
       
  1763     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 4
       
  1764     \codeline
       
  1765     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 5
       
  1766     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 7
       
  1767     \dots
       
  1768     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 8
       
  1769     \codeline
       
  1770     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 10
       
  1771 
       
  1772     \section1 Wizard Look and Feel
       
  1773 
       
  1774     QWizard supports four wizard looks:
       
  1775 
       
  1776     \list
       
  1777     \o ClassicStyle
       
  1778     \o ModernStyle
       
  1779     \o MacStyle
       
  1780     \o AeroStyle
       
  1781     \endlist
       
  1782 
       
  1783     You can explicitly set the look to use using setWizardStyle()
       
  1784     (e.g., if you want the same look on all platforms).
       
  1785 
       
  1786     \table
       
  1787     \header \o ClassicStyle
       
  1788             \o ModernStyle
       
  1789             \o MacStyle
       
  1790             \o AeroStyle
       
  1791     \row    \o \inlineimage qtwizard-classic1.png
       
  1792             \o \inlineimage qtwizard-modern1.png
       
  1793             \o \inlineimage qtwizard-mac1.png
       
  1794             \o \inlineimage qtwizard-aero1.png
       
  1795     \row    \o \inlineimage qtwizard-classic2.png
       
  1796             \o \inlineimage qtwizard-modern2.png
       
  1797             \o \inlineimage qtwizard-mac2.png
       
  1798             \o \inlineimage qtwizard-aero2.png
       
  1799     \endtable
       
  1800 
       
  1801     Note: AeroStyle has effect only on a Windows Vista system with alpha compositing enabled.
       
  1802     ModernStyle is used as a fallback when this condition is not met.
       
  1803 
       
  1804     In addition to the wizard style, there are several options that
       
  1805     control the look and feel of the wizard. These can be set using
       
  1806     setOption() or setOptions(). For example, HaveHelpButton makes
       
  1807     QWizard show a \gui Help button along with the other wizard
       
  1808     buttons.
       
  1809 
       
  1810     You can even change the order of the wizard buttons to any
       
  1811     arbitrary order using setButtonLayout(), and you can add up to
       
  1812     three custom buttons (e.g., a \gui Print button) to the button
       
  1813     row. This is achieved by calling setButton() or setButtonText()
       
  1814     with CustomButton1, CustomButton2, or CustomButton3 to set up the
       
  1815     button, and by enabling the HaveCustomButton1, HaveCustomButton2,
       
  1816     or HaveCustomButton3 options. Whenever the user clicks a custom
       
  1817     button, customButtonClicked() is emitted. For example:
       
  1818 
       
  1819     \snippet examples/dialogs/licensewizard/licensewizard.cpp 29
       
  1820 
       
  1821     \section1 Elements of a Wizard Page
       
  1822 
       
  1823     Wizards consist of a sequence of \l{QWizardPage}s. At any time,
       
  1824     only one page is shown. A page has the following attributes:
       
  1825 
       
  1826     \list
       
  1827     \o A \l{QWizardPage::}{title}.
       
  1828     \o A \l{QWizardPage::}{subTitle}.
       
  1829     \o A set of pixmaps, which may or may not be honored, depending
       
  1830        on the wizard's style:
       
  1831         \list
       
  1832         \o WatermarkPixmap (used by ClassicStyle and ModernStyle)
       
  1833         \o BannerPixmap (used by ModernStyle)
       
  1834         \o LogoPixmap (used by ClassicStyle and ModernStyle)
       
  1835         \o BackgroundPixmap (used by MacStyle)
       
  1836         \endlist
       
  1837     \endlist
       
  1838 
       
  1839     The diagram belows shows how QWizard renders these attributes,
       
  1840     assuming they are all present and ModernStyle is used:
       
  1841 
       
  1842     \image qtwizard-nonmacpage.png
       
  1843 
       
  1844     When a \l{QWizardPage::}{subTitle} is set, QWizard displays it
       
  1845     in a header, in which case it also uses the BannerPixmap and the
       
  1846     LogoPixmap to decorate the header. The WatermarkPixmap is
       
  1847     displayed on the left side, below the header. At the bottom,
       
  1848     there is a row of buttons allowing the user to navigate through
       
  1849     the pages.
       
  1850 
       
  1851     The page itself (the \l{QWizardPage} widget) occupies the area
       
  1852     between the header, the watermark, and the button row. Typically,
       
  1853     the page is a QWizardPage on which a QGridLayout is installed,
       
  1854     with standard child widgets (\l{QLabel}s, \l{QLineEdit}s, etc.).
       
  1855 
       
  1856     If the wizard's style is MacStyle, the page looks radically
       
  1857     different:
       
  1858 
       
  1859     \image qtwizard-macpage.png
       
  1860 
       
  1861     The watermark, banner, and logo pixmaps are ignored by the
       
  1862     MacStyle. If the BackgroundPixmap is set, it is used as the
       
  1863     background for the wizard; otherwise, a default "assistant" image
       
  1864     is used.
       
  1865 
       
  1866     The title and subtitle are set by calling
       
  1867     QWizardPage::setTitle() and QWizardPage::setSubTitle() on the
       
  1868     individual pages. They may be plain text or HTML (see titleFormat
       
  1869     and subTitleFormat). The pixmaps can be set globally for the
       
  1870     entire wizard using setPixmap(), or on a per-page basis using
       
  1871     QWizardPage::setPixmap().
       
  1872 
       
  1873     \target field mechanism
       
  1874     \section1 Registering and Using Fields
       
  1875 
       
  1876     In many wizards, the contents of a page may affect the default
       
  1877     values of the fields of a later page. To make it easy to
       
  1878     communicate between pages, QWizard supports a "field" mechanism
       
  1879     that allows you to register a field (e.g., a QLineEdit) on a page
       
  1880     and to access its value from any page. It is also possible to
       
  1881     specify mandatory fields (i.e., fields that must be filled before
       
  1882     the user can advance to the next page).
       
  1883 
       
  1884     To register a field, call QWizardPage::registerField() field.
       
  1885     For example:
       
  1886 
       
  1887     \snippet examples/dialogs/classwizard/classwizard.cpp 8
       
  1888     \dots
       
  1889     \snippet examples/dialogs/classwizard/classwizard.cpp 10
       
  1890     \snippet examples/dialogs/classwizard/classwizard.cpp 11
       
  1891     \dots
       
  1892     \snippet examples/dialogs/classwizard/classwizard.cpp 13
       
  1893 
       
  1894     The above code registers three fields, \c className, \c
       
  1895     baseClass, and \c qobjectMacro, which are associated with three
       
  1896     child widgets. The asterisk (\c *) next to \c className denotes a
       
  1897     mandatory field.
       
  1898 
       
  1899     \target initialize page
       
  1900     The fields of any page are accessible from any other page. For
       
  1901     example:
       
  1902 
       
  1903     \snippet examples/dialogs/classwizard/classwizard.cpp 17
       
  1904 
       
  1905     Here, we call QWizardPage::field() to access the contents of the
       
  1906     \c className field (which was defined in the \c ClassInfoPage)
       
  1907     and use it to initialize the \c OuputFilePage. The field's
       
  1908     contents is returned as a QVariant.
       
  1909 
       
  1910     When we create a field using QWizardPage::registerField(), we
       
  1911     pass a unique field name and a widget. We can also provide a Qt
       
  1912     property name and a "changed" signal (a signal that is emitted
       
  1913     when the property changes) as third and fourth arguments;
       
  1914     however, this is not necessary for the most common Qt widgets,
       
  1915     such as QLineEdit, QCheckBox, and QComboBox, because QWizard
       
  1916     knows which properties to look for.
       
  1917 
       
  1918     \target mandatory fields
       
  1919 
       
  1920     If an asterisk (\c *) is appended to the name when the property
       
  1921     is registered, the field is a \e{mandatory field}. When a page has
       
  1922     mandatory fields, the \gui Next and/or \gui Finish buttons are
       
  1923     enabled only when all mandatory fields are filled.
       
  1924 
       
  1925     To consider a field "filled", QWizard simply checks that the
       
  1926     field's current value doesn't equal the original value (the value
       
  1927     it had when initializePage() was called). For QLineEdit and
       
  1928     QAbstractSpinBox subclasses, QWizard also checks that
       
  1929     \l{QLineEdit::hasAcceptableInput()}{hasAcceptableInput()} returns
       
  1930     true, to honor any validator or mask.
       
  1931 
       
  1932     QWizard's mandatory field mechanism is provided for convenience.
       
  1933     A more powerful (but also more cumbersome) alternative is to
       
  1934     reimplement QWizardPage::isComplete() and to emit the
       
  1935     QWizardPage::completeChanged() signal whenever the page becomes
       
  1936     complete or incomplete.
       
  1937 
       
  1938     The enabled/disabled state of the \gui Next and/or \gui Finish
       
  1939     buttons is one way to perform validation on the user input.
       
  1940     Another way is to reimplement validateCurrentPage() (or
       
  1941     QWizardPage::validatePage()) to perform some last-minute
       
  1942     validation (and show an error message if the user has entered
       
  1943     incomplete or invalid information). If the function returns true,
       
  1944     the next page is shown (or the wizard finishes); otherwise, the
       
  1945     current page stays up.
       
  1946 
       
  1947     \section1 Creating Linear Wizards
       
  1948 
       
  1949     Most wizards have a linear structure, with page 1 followed by
       
  1950     page 2 and so on until the last page. The \l{dialogs/classwizard}{Class
       
  1951     Wizard} example is such a wizard. With QWizard, linear wizards
       
  1952     are created by instantiating the \l{QWizardPage}s and inserting
       
  1953     them using addPage(). By default, the pages are shown in the
       
  1954     order in which they were added. For example:
       
  1955 
       
  1956     \snippet examples/dialogs/classwizard/classwizard.cpp 0
       
  1957     \dots
       
  1958     \snippet examples/dialogs/classwizard/classwizard.cpp 2
       
  1959 
       
  1960     When a page is about to be shown, QWizard calls initializePage()
       
  1961     (which in turn calls QWizardPage::initializePage()) to fill the
       
  1962     page with default values. By default, this function does nothing,
       
  1963     but it can be reimplemented to initialize the page's contents
       
  1964     based on other pages' fields (see the \l{initialize page}{example
       
  1965     above}).
       
  1966 
       
  1967     If the user presses \gui Back, cleanupPage() is called (which in
       
  1968     turn calls QWizardPage::cleanupPage()). The default
       
  1969     implementation resets the page's fields to their original values
       
  1970     (the values they had before initializePage() was called). If you
       
  1971     want the \gui Back button to be non-destructive and keep the
       
  1972     values entered by the user, simply enable the IndependentPages
       
  1973     option.
       
  1974 
       
  1975     \section1 Creating Non-Linear Wizards
       
  1976 
       
  1977     Some wizards are more complex in that they allow different
       
  1978     traversal paths based on the information provided by the user.
       
  1979     The \l{dialogs/licensewizard}{License Wizard} example illustrates this.
       
  1980     It provides five wizard pages; depending on which options are
       
  1981     selected, the user can reach different pages.
       
  1982 
       
  1983     \image licensewizard-flow.png
       
  1984 
       
  1985     In complex wizards, pages are identified by IDs. These IDs are
       
  1986     typically defined using an enum. For example:
       
  1987 
       
  1988     \snippet examples/dialogs/licensewizard/licensewizard.h 0
       
  1989     \dots
       
  1990     \snippet examples/dialogs/licensewizard/licensewizard.h 2
       
  1991     \dots
       
  1992     \snippet examples/dialogs/licensewizard/licensewizard.h 3
       
  1993 
       
  1994     The pages are inserted using setPage(), which takes an ID and an
       
  1995     instance of QWizardPage (or of a subclass):
       
  1996 
       
  1997     \snippet examples/dialogs/licensewizard/licensewizard.cpp 1
       
  1998     \dots
       
  1999     \snippet examples/dialogs/licensewizard/licensewizard.cpp 8
       
  2000 
       
  2001     By default, the pages are shown in increasing ID order. To
       
  2002     provide a dynamic order that depends on the options chosen by the
       
  2003     user, we must reimplement QWizardPage::nextId(). For example:
       
  2004 
       
  2005     \snippet examples/dialogs/licensewizard/licensewizard.cpp 18
       
  2006     \codeline
       
  2007     \snippet examples/dialogs/licensewizard/licensewizard.cpp 23
       
  2008     \codeline
       
  2009     \snippet examples/dialogs/licensewizard/licensewizard.cpp 24
       
  2010     \codeline
       
  2011     \snippet examples/dialogs/licensewizard/licensewizard.cpp 25
       
  2012     \codeline
       
  2013     \snippet examples/dialogs/licensewizard/licensewizard.cpp 26
       
  2014 
       
  2015     It would also be possible to put all the logic in one place, in a
       
  2016     QWizard::nextId() reimplementation. For example:
       
  2017 
       
  2018     \snippet doc/src/snippets/code/src_gui_dialogs_qwizard.cpp 0
       
  2019 
       
  2020     To start at another page than the page with the lowest ID, call
       
  2021     setStartId().
       
  2022 
       
  2023     To test whether a page has been visited or not, call
       
  2024     hasVisitedPage(). For example:
       
  2025 
       
  2026     \snippet examples/dialogs/licensewizard/licensewizard.cpp 27
       
  2027 
       
  2028     \sa QWizardPage, {Class Wizard Example}, {License Wizard Example}
       
  2029 */
       
  2030 
       
  2031 /*!
       
  2032     \enum QWizard::WizardButton
       
  2033 
       
  2034     This enum specifies the buttons in a wizard.
       
  2035 
       
  2036     \value BackButton  The \gui Back button (\gui {Go Back} on Mac OS X)
       
  2037     \value NextButton  The \gui Next button (\gui Continue on Mac OS X)
       
  2038     \value CommitButton  The \gui Commit button
       
  2039     \value FinishButton  The \gui Finish button (\gui Done on Mac OS X)
       
  2040     \value CancelButton  The \gui Cancel button (see also NoCancelButton)
       
  2041     \value HelpButton    The \gui Help button (see also HaveHelpButton)
       
  2042     \value CustomButton1  The first user-defined button (see also HaveCustomButton1)
       
  2043     \value CustomButton2  The second user-defined button (see also HaveCustomButton2)
       
  2044     \value CustomButton3  The third user-defined button (see also HaveCustomButton3)
       
  2045 
       
  2046     The following value is only useful when calling setButtonLayout():
       
  2047 
       
  2048     \value Stretch  A horizontal stretch in the button layout
       
  2049 
       
  2050     \omitvalue NoButton
       
  2051     \omitvalue NStandardButtons
       
  2052     \omitvalue NButtons
       
  2053 
       
  2054     \sa setButton(), setButtonText(), setButtonLayout(), customButtonClicked()
       
  2055 */
       
  2056 
       
  2057 /*!
       
  2058     \enum QWizard::WizardPixmap
       
  2059 
       
  2060     This enum specifies the pixmaps that can be associated with a page.
       
  2061 
       
  2062     \value WatermarkPixmap  The tall pixmap on the left side of a ClassicStyle or ModernStyle page
       
  2063     \value LogoPixmap  The small pixmap on the right side of a ClassicStyle or ModernStyle page header
       
  2064     \value BannerPixmap  The pixmap that occupies the background of a ModernStyle page header
       
  2065     \value BackgroundPixmap  The pixmap that occupies the background of a MacStyle wizard
       
  2066 
       
  2067     \omitvalue NPixmaps
       
  2068 
       
  2069     \sa setPixmap(), QWizardPage::setPixmap(), {Elements of a Wizard Page}
       
  2070 */
       
  2071 
       
  2072 /*!
       
  2073     \enum QWizard::WizardStyle
       
  2074 
       
  2075     This enum specifies the different looks supported by QWizard.
       
  2076 
       
  2077     \value ClassicStyle  Classic Windows look
       
  2078     \value ModernStyle  Modern Windows look
       
  2079     \value MacStyle  Mac OS X look
       
  2080     \value AeroStyle  Windows Aero look
       
  2081 
       
  2082     \omitvalue NStyles
       
  2083 
       
  2084     \sa setWizardStyle(), WizardOption, {Wizard Look and Feel}
       
  2085 */
       
  2086 
       
  2087 /*!
       
  2088     \enum QWizard::WizardOption
       
  2089 
       
  2090     This enum specifies various options that affect the look and feel
       
  2091     of a wizard.
       
  2092 
       
  2093     \value IndependentPages  The pages are independent of each other
       
  2094                              (i.e., they don't derive values from each
       
  2095                              other).
       
  2096     \value IgnoreSubTitles  Don't show any subtitles, even if they are set.
       
  2097     \value ExtendedWatermarkPixmap  Extend any WatermarkPixmap all the
       
  2098                                     way down to the window's edge.
       
  2099     \value NoDefaultButton  Don't make the \gui Next or \gui Finish button the
       
  2100                             dialog's \l{QPushButton::setDefault()}{default button}.
       
  2101     \value NoBackButtonOnStartPage  Don't show the \gui Back button on the start page.
       
  2102     \value NoBackButtonOnLastPage   Don't show the \gui Back button on the last page.
       
  2103     \value DisabledBackButtonOnLastPage  Disable the \gui Back button on the last page.
       
  2104     \value HaveNextButtonOnLastPage  Show the (disabled) \gui Next button on the last page.
       
  2105     \value HaveFinishButtonOnEarlyPages  Show the (disabled) \gui Finish button on non-final pages.
       
  2106     \value NoCancelButton  Don't show the \gui Cancel button.
       
  2107     \value CancelButtonOnLeft  Put the \gui Cancel button on the left of \gui Back (rather than on
       
  2108                                the right of \gui Finish or \gui Next).
       
  2109     \value HaveHelpButton  Show the \gui Help button.
       
  2110     \value HelpButtonOnRight  Put the \gui Help button on the far right of the button layout
       
  2111                               (rather than on the far left).
       
  2112     \value HaveCustomButton1  Show the first user-defined button (CustomButton1).
       
  2113     \value HaveCustomButton2  Show the second user-defined button (CustomButton2).
       
  2114     \value HaveCustomButton3  Show the third user-defined button (CustomButton3).
       
  2115 
       
  2116     \sa setOptions(), setOption(), testOption()
       
  2117 */
       
  2118 
       
  2119 /*!
       
  2120     Constructs a wizard with the given \a parent and window \a flags.
       
  2121 
       
  2122     \sa parent(), windowFlags()
       
  2123 */
       
  2124 QWizard::QWizard(QWidget *parent, Qt::WindowFlags flags)
       
  2125     : QDialog(*new QWizardPrivate, parent, flags)
       
  2126 {
       
  2127     Q_D(QWizard);
       
  2128     d->init();
       
  2129 #ifdef Q_WS_WINCE
       
  2130     if (!qt_wince_is_mobile())
       
  2131         setWindowFlags(windowFlags() & ~Qt::WindowOkButtonHint);
       
  2132 #endif
       
  2133 }
       
  2134 
       
  2135 /*!
       
  2136     Destroys the wizard and its pages, releasing any allocated resources.
       
  2137 */
       
  2138 QWizard::~QWizard()
       
  2139 {
       
  2140     Q_D(QWizard);
       
  2141     delete d->buttonLayout;
       
  2142 }
       
  2143 
       
  2144 /*!
       
  2145     Adds the given \a page to the wizard, and returns the page's ID.
       
  2146 
       
  2147     The ID is guaranteed to be larger than any other ID in the
       
  2148     QWizard so far.
       
  2149 
       
  2150     \sa setPage(), page()
       
  2151 */
       
  2152 int QWizard::addPage(QWizardPage *page)
       
  2153 {
       
  2154     Q_D(QWizard);
       
  2155     int theid = 0;
       
  2156     if (!d->pageMap.isEmpty())
       
  2157         theid = (d->pageMap.constEnd() - 1).key() + 1;
       
  2158     setPage(theid, page);
       
  2159     return theid;
       
  2160 }
       
  2161 
       
  2162 /*!
       
  2163     \fn void QWizard::setPage(int id, QWizardPage *page)
       
  2164 
       
  2165     Adds the given \a page to the wizard with the given \a id.
       
  2166 
       
  2167     \sa addPage(), page()
       
  2168 */
       
  2169 void QWizard::setPage(int theid, QWizardPage *page)
       
  2170 {
       
  2171     Q_D(QWizard);
       
  2172 
       
  2173     if (!page) {
       
  2174         qWarning("QWizard::setPage: Cannot insert null page");
       
  2175         return;
       
  2176     }
       
  2177 
       
  2178     if (theid == -1) {
       
  2179         qWarning("QWizard::setPage: Cannot insert page with ID -1");
       
  2180         return;
       
  2181     }
       
  2182 
       
  2183     if (d->pageMap.contains(theid)) {
       
  2184         qWarning("QWizard::setPage: Page with duplicate ID %d ignored", theid);
       
  2185         return;
       
  2186     }
       
  2187 
       
  2188     page->setParent(d->pageFrame);
       
  2189 
       
  2190     QVector<QWizardField> &pendingFields = page->d_func()->pendingFields;
       
  2191     for (int i = 0; i < pendingFields.count(); ++i)
       
  2192         d->addField(pendingFields.at(i));
       
  2193     pendingFields.clear();
       
  2194 
       
  2195     connect(page, SIGNAL(completeChanged()), this, SLOT(_q_updateButtonStates()));
       
  2196 
       
  2197     d->pageMap.insert(theid, page);
       
  2198     page->d_func()->wizard = this;
       
  2199 
       
  2200     int n = d->pageVBoxLayout->count();
       
  2201 
       
  2202     // disable layout to prevent layout updates while adding
       
  2203     bool pageVBoxLayoutEnabled = d->pageVBoxLayout->isEnabled();
       
  2204     d->pageVBoxLayout->setEnabled(false);
       
  2205 
       
  2206     d->pageVBoxLayout->insertWidget(n - 1, page);
       
  2207 
       
  2208     // hide new page and reset layout to old status
       
  2209     page->hide();
       
  2210     d->pageVBoxLayout->setEnabled(pageVBoxLayoutEnabled);
       
  2211 }
       
  2212 
       
  2213 /*!
       
  2214     Removes the page with the given \a id. cleanupPage() will be called if necessary.
       
  2215     \since 4.5
       
  2216     \sa addPage(), setPage()
       
  2217 */
       
  2218 void QWizard::removePage(int id)
       
  2219 {
       
  2220     Q_D(QWizard);
       
  2221 
       
  2222     QWizardPage *removedPage = 0;
       
  2223 
       
  2224     if (d->start == id)
       
  2225         d->start = -1;
       
  2226 
       
  2227     if (!d->history.contains(id)) {
       
  2228         // Case 1: removing a page not in the history
       
  2229         removedPage = d->pageMap.take(id);
       
  2230         d->updateCurrentPage();
       
  2231     } else if (id != d->current) {
       
  2232         // Case 2: removing a page in the history before the current page
       
  2233         removedPage = d->pageMap.take(id);
       
  2234         d->history.removeOne(id);
       
  2235         d->_q_updateButtonStates();
       
  2236     } else if (d->history.count() == 1) {
       
  2237         // Case 3: removing the current page which is the first (and only) one in the history
       
  2238         d->reset();
       
  2239         removedPage = d->pageMap.take(id);
       
  2240         if (d->pageMap.isEmpty())
       
  2241             d->updateCurrentPage();
       
  2242         else
       
  2243             restart();
       
  2244     } else {
       
  2245         // Case 4: removing the current page which is not the first one in the history
       
  2246         back();
       
  2247         removedPage = d->pageMap.take(id);
       
  2248         d->updateCurrentPage();
       
  2249     }
       
  2250 
       
  2251     if (removedPage) {
       
  2252         if (d->initialized.contains(id)) {
       
  2253             cleanupPage(id);
       
  2254             d->initialized.remove(id);
       
  2255         }
       
  2256 
       
  2257         d->pageVBoxLayout->removeWidget(removedPage);
       
  2258 
       
  2259         for (int i = d->fields.count() - 1; i >= 0; --i) {
       
  2260             if (d->fields.at(i).page == removedPage) {
       
  2261                 removedPage->d_func()->pendingFields += d->fields.at(i);
       
  2262                 d->removeFieldAt(i);
       
  2263             }
       
  2264         }
       
  2265     }
       
  2266 }
       
  2267 
       
  2268 /*!
       
  2269     \fn QWizardPage *QWizard::page(int id) const
       
  2270 
       
  2271     Returns the page with the given \a id, or 0 if there is no such
       
  2272     page.
       
  2273 
       
  2274     \sa addPage(), setPage()
       
  2275 */
       
  2276 QWizardPage *QWizard::page(int theid) const
       
  2277 {
       
  2278     Q_D(const QWizard);
       
  2279     return d->pageMap.value(theid);
       
  2280 }
       
  2281 
       
  2282 /*!
       
  2283     \fn bool QWizard::hasVisitedPage(int id) const
       
  2284 
       
  2285     Returns true if the page history contains page \a id; otherwise,
       
  2286     returns false.
       
  2287 
       
  2288     Pressing \gui Back marks the current page as "unvisited" again.
       
  2289 
       
  2290     \sa visitedPages()
       
  2291 */
       
  2292 bool QWizard::hasVisitedPage(int theid) const
       
  2293 {
       
  2294     Q_D(const QWizard);
       
  2295     return d->history.contains(theid);
       
  2296 }
       
  2297 
       
  2298 /*!
       
  2299     Returns the list of IDs of visited pages, in the order in which the pages
       
  2300     were visited.
       
  2301 
       
  2302     Pressing \gui Back marks the current page as "unvisited" again.
       
  2303 
       
  2304     \sa hasVisitedPage()
       
  2305 */
       
  2306 QList<int> QWizard::visitedPages() const
       
  2307 {
       
  2308     Q_D(const QWizard);
       
  2309     return d->history;
       
  2310 }
       
  2311 
       
  2312 /*!
       
  2313     Returns the list of page IDs.
       
  2314    \since 4.5
       
  2315 */
       
  2316 QList<int> QWizard::pageIds() const
       
  2317 {
       
  2318   Q_D(const QWizard);
       
  2319   return d->pageMap.keys();
       
  2320 }
       
  2321 
       
  2322 /*!
       
  2323     \property QWizard::startId
       
  2324     \brief the ID of the first page
       
  2325 
       
  2326     If this property isn't explicitly set, this property defaults to
       
  2327     the lowest page ID in this wizard, or -1 if no page has been
       
  2328     inserted yet.
       
  2329 
       
  2330     \sa restart(), nextId()
       
  2331 */
       
  2332 void QWizard::setStartId(int theid)
       
  2333 {
       
  2334     Q_D(QWizard);
       
  2335     if (!d->pageMap.contains(theid)) {
       
  2336         qWarning("QWizard::setStartId: Invalid page ID %d", theid);
       
  2337         return;
       
  2338     }
       
  2339     d->start = theid;
       
  2340 }
       
  2341 
       
  2342 int QWizard::startId() const
       
  2343 {
       
  2344     Q_D(const QWizard);
       
  2345     if (d->start != -1)
       
  2346         return d->start;
       
  2347     if (!d->pageMap.isEmpty())
       
  2348         return d->pageMap.constBegin().key();
       
  2349     return -1;
       
  2350 }
       
  2351 
       
  2352 /*!
       
  2353     Returns a pointer to the current page, or 0 if there is no current
       
  2354     page (e.g., before the wizard is shown).
       
  2355 
       
  2356     This is equivalent to calling page(currentId()).
       
  2357 
       
  2358     \sa page(), currentId(), restart()
       
  2359 */
       
  2360 QWizardPage *QWizard::currentPage() const
       
  2361 {
       
  2362     Q_D(const QWizard);
       
  2363     return page(d->current);
       
  2364 }
       
  2365 
       
  2366 /*!
       
  2367     \property QWizard::currentId
       
  2368     \brief the ID of the current page
       
  2369 
       
  2370     This property cannot be set directly. To change the current page,
       
  2371     call next(), back(), or restart().
       
  2372 
       
  2373     By default, this property has a value of -1, indicating that no page is
       
  2374     currently shown.
       
  2375 
       
  2376     \sa currentIdChanged(), currentPage()
       
  2377 */
       
  2378 int QWizard::currentId() const
       
  2379 {
       
  2380     Q_D(const QWizard);
       
  2381     return d->current;
       
  2382 }
       
  2383 
       
  2384 /*!
       
  2385     Sets the value of the field called \a name to \a value.
       
  2386 
       
  2387     This function can be used to set fields on any page of the wizard.
       
  2388 
       
  2389     \sa QWizardPage::registerField(), QWizardPage::setField(), field()
       
  2390 */
       
  2391 void QWizard::setField(const QString &name, const QVariant &value)
       
  2392 {
       
  2393     Q_D(QWizard);
       
  2394 
       
  2395     int index = d->fieldIndexMap.value(name, -1);
       
  2396     if (index != -1) {
       
  2397         const QWizardField &field = d->fields.at(index);
       
  2398         if (!field.object->setProperty(field.property, value))
       
  2399             qWarning("QWizard::setField: Couldn't write to property '%s'",
       
  2400                      field.property.constData());
       
  2401         return;
       
  2402     }
       
  2403 
       
  2404     qWarning("QWizard::setField: No such field '%s'", qPrintable(name));
       
  2405 }
       
  2406 
       
  2407 /*!
       
  2408     Returns the value of the field called \a name.
       
  2409 
       
  2410     This function can be used to access fields on any page of the wizard.
       
  2411 
       
  2412     \sa QWizardPage::registerField(), QWizardPage::field(), setField()
       
  2413 */
       
  2414 QVariant QWizard::field(const QString &name) const
       
  2415 {
       
  2416     Q_D(const QWizard);
       
  2417 
       
  2418     int index = d->fieldIndexMap.value(name, -1);
       
  2419     if (index != -1) {
       
  2420         const QWizardField &field = d->fields.at(index);
       
  2421         return field.object->property(field.property);
       
  2422     }
       
  2423 
       
  2424     qWarning("QWizard::field: No such field '%s'", qPrintable(name));
       
  2425     return QVariant();
       
  2426 }
       
  2427 
       
  2428 /*!
       
  2429     \property QWizard::wizardStyle
       
  2430     \brief the look and feel of the wizard
       
  2431 
       
  2432     By default, QWizard uses the AeroStyle on a Windows Vista system with alpha compositing
       
  2433     enabled, regardless of the current widget style. If this is not the case, the default
       
  2434     wizard style depends on the current widget style as follows: MacStyle is the default if
       
  2435     the current widget style is QMacStyle, ModernStyle is the default if the current widget
       
  2436     style is QWindowsStyle, and ClassicStyle is the default in all other cases.
       
  2437 
       
  2438     \sa {Wizard Look and Feel}, options
       
  2439 */
       
  2440 void QWizard::setWizardStyle(WizardStyle style)
       
  2441 {
       
  2442     Q_D(QWizard);
       
  2443 
       
  2444     const bool styleChange = style != d->wizStyle;
       
  2445 
       
  2446 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2447     const bool aeroStyleChange =
       
  2448         d->vistaInitPending || d->vistaStateChanged || (styleChange && (style == AeroStyle || d->wizStyle == AeroStyle));
       
  2449     d->vistaStateChanged = false;
       
  2450     d->vistaInitPending = false;
       
  2451 #endif
       
  2452 
       
  2453     if (styleChange
       
  2454 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2455         || aeroStyleChange
       
  2456 #endif
       
  2457         ) {
       
  2458         d->disableUpdates();
       
  2459         d->wizStyle = style;
       
  2460         d->updateButtonTexts();
       
  2461         d->updateLayout();
       
  2462         updateGeometry();
       
  2463         d->enableUpdates();
       
  2464 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2465         if (aeroStyleChange)
       
  2466             d->handleAeroStyleChange();
       
  2467 #endif
       
  2468     }
       
  2469 }
       
  2470 
       
  2471 QWizard::WizardStyle QWizard::wizardStyle() const
       
  2472 {
       
  2473     Q_D(const QWizard);
       
  2474     return d->wizStyle;
       
  2475 }
       
  2476 
       
  2477 /*!
       
  2478     Sets the given \a option to be enabled if \a on is true;
       
  2479     otherwise, clears the given \a option.
       
  2480 
       
  2481     \sa options, testOption(), setWizardStyle()
       
  2482 */
       
  2483 void QWizard::setOption(WizardOption option, bool on)
       
  2484 {
       
  2485     Q_D(QWizard);
       
  2486     if (!(d->opts & option) != !on)
       
  2487         setOptions(d->opts ^ option);
       
  2488 }
       
  2489 
       
  2490 /*!
       
  2491     Returns true if the given \a option is enabled; otherwise, returns
       
  2492     false.
       
  2493 
       
  2494     \sa options, setOption(), setWizardStyle()
       
  2495 */
       
  2496 bool QWizard::testOption(WizardOption option) const
       
  2497 {
       
  2498     Q_D(const QWizard);
       
  2499     return (d->opts & option) != 0;
       
  2500 }
       
  2501 
       
  2502 /*!
       
  2503     \property QWizard::options
       
  2504     \brief the various options that affect the look and feel of the wizard
       
  2505 
       
  2506     By default, the following options are set (depending on the platform):
       
  2507 
       
  2508     \list
       
  2509     \o Windows: HelpButtonOnRight.
       
  2510     \o Mac OS X: NoDefaultButton and NoCancelButton.
       
  2511     \o X11 and QWS (Qt for Embedded Linux): none.
       
  2512     \endlist
       
  2513 
       
  2514     \sa wizardStyle
       
  2515 */
       
  2516 void QWizard::setOptions(WizardOptions options)
       
  2517 {
       
  2518     Q_D(QWizard);
       
  2519 
       
  2520     WizardOptions changed = (options ^ d->opts);
       
  2521     if (!changed)
       
  2522         return;
       
  2523 
       
  2524     d->disableUpdates();
       
  2525 
       
  2526     d->opts = options;
       
  2527     if ((changed & IndependentPages) && !(d->opts & IndependentPages))
       
  2528         d->cleanupPagesNotInHistory();
       
  2529 
       
  2530     if (changed & (NoDefaultButton | HaveHelpButton | HelpButtonOnRight | NoCancelButton
       
  2531                    | CancelButtonOnLeft | HaveCustomButton1 | HaveCustomButton2
       
  2532                    | HaveCustomButton3)) {
       
  2533         d->updateButtonLayout();
       
  2534     } else if (changed & (NoBackButtonOnStartPage | NoBackButtonOnLastPage
       
  2535                           | HaveNextButtonOnLastPage | HaveFinishButtonOnEarlyPages
       
  2536                           | DisabledBackButtonOnLastPage)) {
       
  2537         d->_q_updateButtonStates();
       
  2538     }
       
  2539 
       
  2540     d->enableUpdates();
       
  2541     d->updateLayout();
       
  2542 }
       
  2543 
       
  2544 QWizard::WizardOptions QWizard::options() const
       
  2545 {
       
  2546     Q_D(const QWizard);
       
  2547     return d->opts;
       
  2548 }
       
  2549 
       
  2550 /*!
       
  2551     Sets the text on button \a which to be \a text.
       
  2552 
       
  2553     By default, the text on buttons depends on the wizardStyle. For
       
  2554     example, on Mac OS X, the \gui Next button is called \gui
       
  2555     Continue.
       
  2556 
       
  2557     To add extra buttons to the wizard (e.g., a \gui Print button),
       
  2558     one way is to call setButtonText() with CustomButton1,
       
  2559     CustomButton2, or CustomButton3 to set their text, and make the
       
  2560     buttons visible using the HaveCustomButton1, HaveCustomButton2,
       
  2561     and/or HaveCustomButton3 options.
       
  2562 
       
  2563     Button texts may also be set on a per-page basis using QWizardPage::setButtonText().
       
  2564 
       
  2565     \sa setButton(), button(), setButtonLayout(), setOptions(), QWizardPage::setButtonText()
       
  2566 */
       
  2567 void QWizard::setButtonText(WizardButton which, const QString &text)
       
  2568 {
       
  2569     Q_D(QWizard);
       
  2570 
       
  2571     if (!d->ensureButton(which))
       
  2572         return;
       
  2573 
       
  2574     d->buttonCustomTexts.insert(which, text);
       
  2575 
       
  2576     if (!currentPage() || !currentPage()->d_func()->buttonCustomTexts.contains(which))
       
  2577         d->btns[which]->setText(text);
       
  2578 }
       
  2579 
       
  2580 /*!
       
  2581     Returns the text on button \a which.
       
  2582 
       
  2583     If a text has ben set using setButtonText(), this text is returned.
       
  2584 
       
  2585     By default, the text on buttons depends on the wizardStyle. For
       
  2586     example, on Mac OS X, the \gui Next button is called \gui
       
  2587     Continue.
       
  2588 
       
  2589     \sa button(), setButton(), setButtonText(), QWizardPage::buttonText(),
       
  2590     QWizardPage::setButtonText()
       
  2591 */
       
  2592 QString QWizard::buttonText(WizardButton which) const
       
  2593 {
       
  2594     Q_D(const QWizard);
       
  2595 
       
  2596     if (!d->ensureButton(which))
       
  2597         return QString();
       
  2598 
       
  2599     if (d->buttonCustomTexts.contains(which))
       
  2600         return d->buttonCustomTexts.value(which);
       
  2601 
       
  2602     const QString defText = buttonDefaultText(d->wizStyle, which, d);
       
  2603     if(!defText.isNull())
       
  2604         return defText;
       
  2605 
       
  2606     return d->btns[which]->text();
       
  2607 }
       
  2608 
       
  2609 /*!
       
  2610     Sets the order in which buttons are displayed to \a layout, where
       
  2611     \a layout is a list of \l{WizardButton}s.
       
  2612 
       
  2613     The default layout depends on the options (e.g., whether
       
  2614     HelpButtonOnRight) that are set. You can call this function if
       
  2615     you need more control over the buttons' layout than what \l
       
  2616     options already provides.
       
  2617 
       
  2618     You can specify horizontal stretches in the layout using \l
       
  2619     Stretch.
       
  2620 
       
  2621     Example:
       
  2622 
       
  2623     \snippet doc/src/snippets/code/src_gui_dialogs_qwizard.cpp 1
       
  2624 
       
  2625     \sa setButton(), setButtonText(), setOptions()
       
  2626 */
       
  2627 void QWizard::setButtonLayout(const QList<WizardButton> &layout)
       
  2628 {
       
  2629     Q_D(QWizard);
       
  2630 
       
  2631     for (int i = 0; i < layout.count(); ++i) {
       
  2632         WizardButton button1 = layout.at(i);
       
  2633 
       
  2634         if (button1 == NoButton || button1 == Stretch)
       
  2635             continue;
       
  2636         if (!d->ensureButton(button1))
       
  2637             return;
       
  2638 
       
  2639         // O(n^2), but n is very small
       
  2640         for (int j = 0; j < i; ++j) {
       
  2641             WizardButton button2 = layout.at(j);
       
  2642             if (button2 == button1) {
       
  2643                 qWarning("QWizard::setButtonLayout: Duplicate button in layout");
       
  2644                 return;
       
  2645             }
       
  2646         }
       
  2647     }
       
  2648 
       
  2649     d->buttonsHaveCustomLayout = true;
       
  2650     d->buttonsCustomLayout = layout;
       
  2651     d->updateButtonLayout();
       
  2652 }
       
  2653 
       
  2654 /*!
       
  2655     Sets the button corresponding to role \a which to \a button.
       
  2656 
       
  2657     To add extra buttons to the wizard (e.g., a \gui Print button),
       
  2658     one way is to call setButton() with CustomButton1 to
       
  2659     CustomButton3, and make the buttons visible using the
       
  2660     HaveCustomButton1 to HaveCustomButton3 options.
       
  2661 
       
  2662     \sa setButtonText(), setButtonLayout(), options
       
  2663 */
       
  2664 void QWizard::setButton(WizardButton which, QAbstractButton *button)
       
  2665 {
       
  2666     Q_D(QWizard);
       
  2667 
       
  2668     if (uint(which) >= NButtons || d->btns[which] == button)
       
  2669         return;
       
  2670 
       
  2671     if (QAbstractButton *oldButton = d->btns[which]) {
       
  2672         d->buttonLayout->removeWidget(oldButton);
       
  2673         delete oldButton;
       
  2674     }
       
  2675 
       
  2676     d->btns[which] = button;
       
  2677     if (button) {
       
  2678         button->setParent(d->antiFlickerWidget);
       
  2679         d->buttonCustomTexts.insert(which, button->text());
       
  2680         d->connectButton(which);
       
  2681     } else {
       
  2682         d->buttonCustomTexts.remove(which); // ### what about page-specific texts set for 'which'
       
  2683         d->ensureButton(which);             // (QWizardPage::setButtonText())? Clear them as well?
       
  2684     }
       
  2685 
       
  2686     d->updateButtonLayout();
       
  2687 }
       
  2688 
       
  2689 /*!
       
  2690     Returns the button corresponding to role \a which.
       
  2691 
       
  2692     \sa setButton(), setButtonText()
       
  2693 */
       
  2694 QAbstractButton *QWizard::button(WizardButton which) const
       
  2695 {
       
  2696     Q_D(const QWizard);
       
  2697 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2698     if (d->wizStyle == AeroStyle && which == BackButton)
       
  2699         return d->vistaHelper->backButton();
       
  2700 #endif
       
  2701     if (!d->ensureButton(which))
       
  2702         return 0;
       
  2703     return d->btns[which];
       
  2704 }
       
  2705 
       
  2706 /*!
       
  2707     \property QWizard::titleFormat
       
  2708     \brief the text format used by page titles
       
  2709 
       
  2710     The default format is Qt::AutoText.
       
  2711 
       
  2712     \sa QWizardPage::title, subTitleFormat
       
  2713 */
       
  2714 void QWizard::setTitleFormat(Qt::TextFormat format)
       
  2715 {
       
  2716     Q_D(QWizard);
       
  2717     d->titleFmt = format;
       
  2718     d->updateLayout();
       
  2719 }
       
  2720 
       
  2721 Qt::TextFormat QWizard::titleFormat() const
       
  2722 {
       
  2723     Q_D(const QWizard);
       
  2724     return d->titleFmt;
       
  2725 }
       
  2726 
       
  2727 /*!
       
  2728     \property QWizard::subTitleFormat
       
  2729     \brief the text format used by page subtitles
       
  2730 
       
  2731     The default format is Qt::AutoText.
       
  2732 
       
  2733     \sa QWizardPage::title, titleFormat
       
  2734 */
       
  2735 void QWizard::setSubTitleFormat(Qt::TextFormat format)
       
  2736 {
       
  2737     Q_D(QWizard);
       
  2738     d->subTitleFmt = format;
       
  2739     d->updateLayout();
       
  2740 }
       
  2741 
       
  2742 Qt::TextFormat QWizard::subTitleFormat() const
       
  2743 {
       
  2744     Q_D(const QWizard);
       
  2745     return d->subTitleFmt;
       
  2746 }
       
  2747 
       
  2748 /*!
       
  2749     Sets the pixmap for role \a which to \a pixmap.
       
  2750 
       
  2751     The pixmaps are used by QWizard when displaying a page. Which
       
  2752     pixmaps are actually used depend on the \l{Wizard Look and
       
  2753     Feel}{wizard style}.
       
  2754 
       
  2755     Pixmaps can also be set for a specific page using
       
  2756     QWizardPage::setPixmap().
       
  2757 
       
  2758     \sa QWizardPage::setPixmap(), {Elements of a Wizard Page}
       
  2759 */
       
  2760 void QWizard::setPixmap(WizardPixmap which, const QPixmap &pixmap)
       
  2761 {
       
  2762     Q_D(QWizard);
       
  2763     Q_ASSERT(uint(which) < NPixmaps);
       
  2764     d->defaultPixmaps[which] = pixmap;
       
  2765     d->updatePixmap(which);
       
  2766 }
       
  2767 
       
  2768 /*!
       
  2769     Returns the pixmap set for role \a which.
       
  2770 
       
  2771     By default, the only pixmap that is set is the BackgroundPixmap on
       
  2772     Mac OS X.
       
  2773 
       
  2774     \sa QWizardPage::pixmap(), {Elements of a Wizard Page}
       
  2775 */
       
  2776 QPixmap QWizard::pixmap(WizardPixmap which) const
       
  2777 {
       
  2778     Q_D(const QWizard);
       
  2779     Q_ASSERT(uint(which) < NPixmaps);
       
  2780 #ifdef Q_WS_MAC
       
  2781     if (which == BackgroundPixmap && d->defaultPixmaps[BackgroundPixmap].isNull())
       
  2782         d->defaultPixmaps[BackgroundPixmap] = d->findDefaultBackgroundPixmap();
       
  2783 #endif
       
  2784     return d->defaultPixmaps[which];
       
  2785 }
       
  2786 
       
  2787 /*!
       
  2788     Sets the default property for \a className to be \a property,
       
  2789     and the associated change signal to be \a changedSignal.
       
  2790 
       
  2791     The default property is used when an instance of \a className (or
       
  2792     of one of its subclasses) is passed to
       
  2793     QWizardPage::registerField() and no property is specified.
       
  2794 
       
  2795     QWizard knows the most common Qt widgets. For these (or their
       
  2796     subclasses), you don't need to specify a \a property or a \a
       
  2797     changedSignal. The table below lists these widgets:
       
  2798 
       
  2799     \table
       
  2800     \header \o Widget          \o Property                            \o Change Notification Signal
       
  2801     \row    \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()}
       
  2802     \row    \o QAbstractSlider \o int \l{QAbstractSlider::}{value}    \o \l{QAbstractSlider::}{valueChanged()}
       
  2803     \row    \o QComboBox       \o int \l{QComboBox::}{currentIndex}   \o \l{QComboBox::}{currentIndexChanged()}
       
  2804     \row    \o QDateTimeEdit   \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()}
       
  2805     \row    \o QLineEdit       \o QString \l{QLineEdit::}{text}       \o \l{QLineEdit::}{textChanged()}
       
  2806     \row    \o QListWidget     \o int \l{QListWidget::}{currentRow}   \o \l{QListWidget::}{currentRowChanged()}
       
  2807     \row    \o QSpinBox        \o int \l{QSpinBox::}{value}           \o \l{QSpinBox::}{valueChanged()}
       
  2808     \endtable
       
  2809 
       
  2810     \sa QWizardPage::registerField()
       
  2811 */
       
  2812 void QWizard::setDefaultProperty(const char *className, const char *property,
       
  2813                                  const char *changedSignal)
       
  2814 {
       
  2815     Q_D(QWizard);
       
  2816     for (int i = d->defaultPropertyTable.count() - 1; i >= 0; --i) {
       
  2817         if (qstrcmp(d->defaultPropertyTable.at(i).className, className) == 0) {
       
  2818             d->defaultPropertyTable.remove(i);
       
  2819             break;
       
  2820         }
       
  2821     }
       
  2822     d->defaultPropertyTable.append(QWizardDefaultProperty(className, property, changedSignal));
       
  2823 }
       
  2824 
       
  2825 /*!
       
  2826     \reimp
       
  2827 */
       
  2828 void QWizard::setVisible(bool visible)
       
  2829 {
       
  2830     Q_D(QWizard);
       
  2831     if (visible) {
       
  2832         if (d->current == -1)
       
  2833             restart();
       
  2834     }
       
  2835     QDialog::setVisible(visible);
       
  2836 }
       
  2837 
       
  2838 /*!
       
  2839     \reimp
       
  2840 */
       
  2841 QSize QWizard::sizeHint() const
       
  2842 {
       
  2843     Q_D(const QWizard);
       
  2844     QSize result = d->mainLayout->totalSizeHint();
       
  2845 #ifdef Q_WS_S60
       
  2846     QSize extra(QApplication::desktop()->availableGeometry(QCursor::pos()).size());
       
  2847 #else
       
  2848     QSize extra(500, 360);
       
  2849 #endif
       
  2850     if (d->wizStyle == MacStyle && d->current != -1) {
       
  2851         QSize pixmap(currentPage()->pixmap(BackgroundPixmap).size());
       
  2852         extra.setWidth(616);
       
  2853         if (!pixmap.isNull()) {
       
  2854             extra.setHeight(pixmap.height());
       
  2855 
       
  2856             /*
       
  2857                 The width isn't always reliable as a size hint, as
       
  2858                 some wizard backgrounds just cover the leftmost area.
       
  2859                 Use a rule of thumb to determine if the width is
       
  2860                 reliable or not.
       
  2861             */
       
  2862             if (pixmap.width() >= pixmap.height())
       
  2863                 extra.setWidth(pixmap.width());
       
  2864         }
       
  2865     }
       
  2866     return result.expandedTo(extra);
       
  2867 }
       
  2868 
       
  2869 /*!
       
  2870     \fn void QWizard::currentIdChanged(int id)
       
  2871 
       
  2872     This signal is emitted when the current page changes, with the new
       
  2873     current \a id.
       
  2874 
       
  2875     \sa currentId(), currentPage()
       
  2876 */
       
  2877 
       
  2878 /*!
       
  2879     \fn void QWizard::helpRequested()
       
  2880 
       
  2881     This signal is emitted when the user clicks the \gui Help button.
       
  2882 
       
  2883     By default, no \gui Help button is shown. Call
       
  2884     setOption(HaveHelpButton, true) to have one.
       
  2885 
       
  2886     Example:
       
  2887 
       
  2888     \snippet examples/dialogs/licensewizard/licensewizard.cpp 0
       
  2889     \dots
       
  2890     \snippet examples/dialogs/licensewizard/licensewizard.cpp 5
       
  2891     \snippet examples/dialogs/licensewizard/licensewizard.cpp 7
       
  2892     \dots
       
  2893     \snippet examples/dialogs/licensewizard/licensewizard.cpp 8
       
  2894     \codeline
       
  2895     \snippet examples/dialogs/licensewizard/licensewizard.cpp 10
       
  2896     \dots
       
  2897     \snippet examples/dialogs/licensewizard/licensewizard.cpp 12
       
  2898     \codeline
       
  2899     \snippet examples/dialogs/licensewizard/licensewizard.cpp 14
       
  2900     \codeline
       
  2901     \snippet examples/dialogs/licensewizard/licensewizard.cpp 15
       
  2902 
       
  2903     \sa customButtonClicked()
       
  2904 */
       
  2905 
       
  2906 /*!
       
  2907     \fn void QWizard::customButtonClicked(int which)
       
  2908 
       
  2909     This signal is emitted when the user clicks a custom button. \a
       
  2910     which can be CustomButton1, CustomButton2, or CustomButton3.
       
  2911 
       
  2912     By default, no custom button is shown. Call setOption() with
       
  2913     HaveCustomButton1, HaveCustomButton2, or HaveCustomButton3 to have
       
  2914     one, and use setButtonText() or setButton() to configure it.
       
  2915 
       
  2916     \sa helpRequested()
       
  2917 */
       
  2918 
       
  2919 /*!
       
  2920     Goes back to the previous page.
       
  2921 
       
  2922     This is equivalent to pressing the \gui Back button.
       
  2923 
       
  2924     \sa next(), accept(), reject(), restart()
       
  2925 */
       
  2926 void QWizard::back()
       
  2927 {
       
  2928     Q_D(QWizard);
       
  2929     int n = d->history.count() - 2;
       
  2930     if (n < 0)
       
  2931         return;
       
  2932     d->switchToPage(d->history.at(n), QWizardPrivate::Backward);
       
  2933 }
       
  2934 
       
  2935 /*!
       
  2936     Advances to the next page.
       
  2937 
       
  2938     This is equivalent to pressing the \gui Next or \gui Commit button.
       
  2939 
       
  2940     \sa nextId(), back(), accept(), reject(), restart()
       
  2941 */
       
  2942 void QWizard::next()
       
  2943 {
       
  2944     Q_D(QWizard);
       
  2945 
       
  2946     if (d->current == -1)
       
  2947         return;
       
  2948 
       
  2949     if (validateCurrentPage()) {
       
  2950         int next = nextId();
       
  2951         if (next != -1) {
       
  2952             if (d->history.contains(next)) {
       
  2953                 qWarning("QWizard::next: Page %d already met", next);
       
  2954                 return;
       
  2955             }
       
  2956             if (!d->pageMap.contains(next)) {
       
  2957                 qWarning("QWizard::next: No such page %d", next);
       
  2958                 return;
       
  2959             }
       
  2960             d->switchToPage(next, QWizardPrivate::Forward);
       
  2961         }
       
  2962     }
       
  2963 }
       
  2964 
       
  2965 /*!
       
  2966     Restarts the wizard at the start page. This function is called automatically when the
       
  2967     wizard is shown.
       
  2968 
       
  2969     \sa startId()
       
  2970 */
       
  2971 void QWizard::restart()
       
  2972 {
       
  2973     Q_D(QWizard);
       
  2974     d->disableUpdates();
       
  2975     d->reset();
       
  2976     d->switchToPage(startId(), QWizardPrivate::Forward);
       
  2977     d->enableUpdates();
       
  2978 }
       
  2979 
       
  2980 /*!
       
  2981     \reimp
       
  2982 */
       
  2983 bool QWizard::event(QEvent *event)
       
  2984 {
       
  2985     Q_D(QWizard);
       
  2986     if (event->type() == QEvent::StyleChange) { // Propagate style
       
  2987         d->setStyle(style());
       
  2988         d->updateLayout();
       
  2989     }
       
  2990 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2991     else if (event->type() == QEvent::Show && d->vistaInitPending) {
       
  2992         d->vistaInitPending = false;
       
  2993         d->wizStyle = AeroStyle;
       
  2994         d->handleAeroStyleChange();
       
  2995     }
       
  2996     else if (d->isVistaThemeEnabled()) {
       
  2997         d->vistaHelper->mouseEvent(event);
       
  2998     }
       
  2999 #endif
       
  3000     return QDialog::event(event);
       
  3001 }
       
  3002 
       
  3003 /*!
       
  3004     \reimp
       
  3005 */
       
  3006 void QWizard::resizeEvent(QResizeEvent *event)
       
  3007 {
       
  3008     Q_D(QWizard);
       
  3009     int heightOffset = 0;
       
  3010 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3011     if (d->isVistaThemeEnabled()) {
       
  3012         heightOffset = d->vistaHelper->topOffset();
       
  3013         if (d->isVistaThemeEnabled(QVistaHelper::VistaAero))
       
  3014             heightOffset += d->vistaHelper->titleBarSize();
       
  3015     }
       
  3016 #endif
       
  3017     d->antiFlickerWidget->resize(event->size().width(), event->size().height() - heightOffset);
       
  3018 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3019     if (d->isVistaThemeEnabled())
       
  3020         d->vistaHelper->resizeEvent(event);
       
  3021 #endif
       
  3022     QDialog::resizeEvent(event);
       
  3023 }
       
  3024 
       
  3025 /*!
       
  3026     \reimp
       
  3027 */
       
  3028 void QWizard::paintEvent(QPaintEvent * event)
       
  3029 {
       
  3030     Q_D(QWizard);
       
  3031     if (d->wizStyle == MacStyle && currentPage()) {
       
  3032         QPixmap backgroundPixmap = currentPage()->pixmap(BackgroundPixmap);
       
  3033         if (backgroundPixmap.isNull())
       
  3034             return;
       
  3035 
       
  3036         QPainter painter(this);
       
  3037         painter.drawPixmap(0, (height() - backgroundPixmap.height()) / 2, backgroundPixmap);
       
  3038     }
       
  3039 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3040     else if (d->isVistaThemeEnabled()) {
       
  3041         if (d->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
       
  3042             QPainter painter(this);
       
  3043             QColor color = d->vistaHelper->basicWindowFrameColor();
       
  3044             painter.fillRect(0, 0, width(), QVistaHelper::topOffset(), color);
       
  3045         }
       
  3046         d->vistaHelper->paintEvent(event);
       
  3047     }
       
  3048 #else
       
  3049     Q_UNUSED(event);
       
  3050 #endif
       
  3051 }
       
  3052 
       
  3053 #if defined(Q_WS_WIN)
       
  3054 /*!
       
  3055     \reimp
       
  3056 */
       
  3057 bool QWizard::winEvent(MSG *message, long *result)
       
  3058 {
       
  3059 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3060     Q_D(QWizard);
       
  3061     if (d->isVistaThemeEnabled()) {
       
  3062         const bool winEventResult = d->vistaHelper->handleWinEvent(message, result);
       
  3063         if (QVistaHelper::vistaState() != d->vistaState) {
       
  3064             d->vistaState = QVistaHelper::vistaState();
       
  3065             d->vistaStateChanged = true;
       
  3066             setWizardStyle(AeroStyle);
       
  3067         }
       
  3068         return winEventResult;
       
  3069     } else {
       
  3070         return QDialog::winEvent(message, result);
       
  3071     }
       
  3072 #else
       
  3073     return QDialog::winEvent(message, result);
       
  3074 #endif
       
  3075 }
       
  3076 #endif
       
  3077 
       
  3078 /*!
       
  3079     \reimp
       
  3080 */
       
  3081 void QWizard::done(int result)
       
  3082 {
       
  3083     Q_D(QWizard);
       
  3084     // canceling leaves the wizard in a known state
       
  3085     if (result == Rejected) {
       
  3086         d->reset();
       
  3087     } else {
       
  3088         if (!validateCurrentPage())
       
  3089             return;
       
  3090     }
       
  3091     QDialog::done(result);
       
  3092 }
       
  3093 
       
  3094 /*!
       
  3095     \fn void QWizard::initializePage(int id)
       
  3096 
       
  3097     This virtual function is called by QWizard to prepare page \a id
       
  3098     just before it is shown either as a result of QWizard::restart()
       
  3099     being called, or as a result of the user clicking \gui Next. (However, if the \l
       
  3100     QWizard::IndependentPages option is set, this function is only
       
  3101     called the first time the page is shown.)
       
  3102 
       
  3103     By reimplementing this function, you can ensure that the page's
       
  3104     fields are properly initialized based on fields from previous
       
  3105     pages.
       
  3106 
       
  3107     The default implementation calls QWizardPage::initializePage() on
       
  3108     page(\a id).
       
  3109 
       
  3110     \sa QWizardPage::initializePage(), cleanupPage()
       
  3111 */
       
  3112 void QWizard::initializePage(int theid)
       
  3113 {
       
  3114     QWizardPage *page = this->page(theid);
       
  3115     if (page)
       
  3116         page->initializePage();
       
  3117 }
       
  3118 
       
  3119 /*!
       
  3120     \fn void QWizard::cleanupPage(int id)
       
  3121 
       
  3122     This virtual function is called by QWizard to clean up page \a id just before the
       
  3123     user leaves it by clicking \gui Back (unless the \l QWizard::IndependentPages option is set).
       
  3124 
       
  3125     The default implementation calls QWizardPage::cleanupPage() on
       
  3126     page(\a id).
       
  3127 
       
  3128     \sa QWizardPage::cleanupPage(), initializePage()
       
  3129 */
       
  3130 void QWizard::cleanupPage(int theid)
       
  3131 {
       
  3132     QWizardPage *page = this->page(theid);
       
  3133     if (page)
       
  3134         page->cleanupPage();
       
  3135 }
       
  3136 
       
  3137 /*!
       
  3138     This virtual function is called by QWizard when the user clicks
       
  3139     \gui Next or \gui Finish to perform some last-minute validation.
       
  3140     If it returns true, the next page is shown (or the wizard
       
  3141     finishes); otherwise, the current page stays up.
       
  3142 
       
  3143     The default implementation calls QWizardPage::validatePage() on
       
  3144     the currentPage().
       
  3145 
       
  3146     When possible, it is usually better style to disable the \gui
       
  3147     Next or \gui Finish button (by specifying \l{mandatory fields} or
       
  3148     by reimplementing QWizardPage::isComplete()) than to reimplement
       
  3149     validateCurrentPage().
       
  3150 
       
  3151     \sa QWizardPage::validatePage(), currentPage()
       
  3152 */
       
  3153 bool QWizard::validateCurrentPage()
       
  3154 {
       
  3155     QWizardPage *page = currentPage();
       
  3156     if (!page)
       
  3157         return true;
       
  3158 
       
  3159     return page->validatePage();
       
  3160 }
       
  3161 
       
  3162 /*!
       
  3163     This virtual function is called by QWizard to find out which page
       
  3164     to show when the user clicks the \gui Next button.
       
  3165 
       
  3166     The return value is the ID of the next page, or -1 if no page follows.
       
  3167 
       
  3168     The default implementation calls QWizardPage::nextId() on the
       
  3169     currentPage().
       
  3170 
       
  3171     By reimplementing this function, you can specify a dynamic page
       
  3172     order.
       
  3173 
       
  3174     \sa QWizardPage::nextId(), currentPage()
       
  3175 */
       
  3176 int QWizard::nextId() const
       
  3177 {
       
  3178     const QWizardPage *page = currentPage();
       
  3179     if (!page)
       
  3180         return -1;
       
  3181 
       
  3182     return page->nextId();
       
  3183 }
       
  3184 
       
  3185 /*!
       
  3186     \class QWizardPage
       
  3187     \since 4.3
       
  3188     \brief The QWizardPage class is the base class for wizard pages.
       
  3189 
       
  3190     QWizard represents a wizard. Each page is a QWizardPage. When
       
  3191     you create your own wizards, you can use QWizardPage directly,
       
  3192     or you can subclass it for more control.
       
  3193 
       
  3194     A page has the following attributes, which are rendered by
       
  3195     QWizard: a \l title, a \l subTitle, and a \l{setPixmap()}{set of
       
  3196     pixmaps}. See \l{Elements of a Wizard Page} for details. Once a
       
  3197     page is added to the wizard (using QWizard::addPage() or
       
  3198     QWizard::setPage()), wizard() returns a pointer to the
       
  3199     associated QWizard object.
       
  3200 
       
  3201     Page provides five virtual functions that can be reimplemented to
       
  3202     provide custom behavior:
       
  3203 
       
  3204     \list
       
  3205     \o initializePage() is called to initialize the page's contents
       
  3206        when the user clicks the wizard's \gui Next button. If you
       
  3207        want to derive the page's default from what the user entered
       
  3208        on previous pages, this is the function to reimplement.
       
  3209     \o cleanupPage() is called to reset the page's contents when the
       
  3210        user clicks the wizard's \gui Back button.
       
  3211     \o validatePage() validates the page when the user clicks \gui
       
  3212        Next or \gui Finish. It is often used to show an error message
       
  3213        if the user has entered incomplete or invalid information.
       
  3214     \o nextId() returns the ID of the next page. It is useful when
       
  3215        \l{creating non-linear wizards}, which allow different
       
  3216        traversal paths based on the information provided by the user.
       
  3217     \o isComplete() is called to determine whether the \gui Next
       
  3218        and/or \gui Finish button should be enabled or disabled. If
       
  3219        you reimplement isComplete(), also make sure that
       
  3220        completeChanged() is emitted whenever the complete state
       
  3221        changes.
       
  3222     \endlist
       
  3223 
       
  3224     Normally, the \gui Next button and the \gui Finish button of a
       
  3225     wizard are mutually exclusive. If isFinalPage() returns true, \gui
       
  3226     Finish is available; otherwise, \gui Next is available. By
       
  3227     default, isFinalPage() is true only when nextId() returns -1. If
       
  3228     you want to show \gui Next and \gui Final simultaneously for a
       
  3229     page (letting the user perform an "early finish"), call
       
  3230     setFinalPage(true) on that page. For wizards that support early
       
  3231     finishes, you might also want to set the
       
  3232     \l{QWizard::}{HaveNextButtonOnLastPage} and
       
  3233     \l{QWizard::}{HaveFinishButtonOnEarlyPages} options on the
       
  3234     wizard.
       
  3235 
       
  3236     In many wizards, the contents of a page may affect the default
       
  3237     values of the fields of a later page. To make it easy to
       
  3238     communicate between pages, QWizard supports a \l{Registering and
       
  3239     Using Fields}{"field" mechanism} that allows you to register a
       
  3240     field (e.g., a QLineEdit) on a page and to access its value from
       
  3241     any page. Fields are global to the entire wizard and make it easy
       
  3242     for any single page to access information stored by another page,
       
  3243     without having to put all the logic in QWizard or having the
       
  3244     pages know explicitly about each other. Fields are registered
       
  3245     using registerField() and can be accessed at any time using
       
  3246     field() and setField().
       
  3247 
       
  3248     \sa QWizard, {Class Wizard Example}, {License Wizard Example}
       
  3249 */
       
  3250 
       
  3251 /*!
       
  3252     Constructs a wizard page with the given \a parent.
       
  3253 
       
  3254     When the page is inserted into a wizard using QWizard::addPage()
       
  3255     or QWizard::setPage(), the parent is automatically set to be the
       
  3256     wizard.
       
  3257 
       
  3258     \sa wizard()
       
  3259 */
       
  3260 QWizardPage::QWizardPage(QWidget *parent)
       
  3261     : QWidget(*new QWizardPagePrivate, parent, 0)
       
  3262 {
       
  3263     connect(this, SIGNAL(completeChanged()), this, SLOT(_q_updateCachedCompleteState()));
       
  3264 }
       
  3265 
       
  3266 /*!
       
  3267     \property QWizardPage::title
       
  3268     \brief the title of the page
       
  3269 
       
  3270     The title is shown by the QWizard, above the actual page. All
       
  3271     pages should have a title.
       
  3272 
       
  3273     The title may be plain text or HTML, depending on the value of the
       
  3274     \l{QWizard::titleFormat} property.
       
  3275 
       
  3276     By default, this property contains an empty string.
       
  3277 
       
  3278     \sa subTitle, {Elements of a Wizard Page}
       
  3279 */
       
  3280 void QWizardPage::setTitle(const QString &title)
       
  3281 {
       
  3282     Q_D(QWizardPage);
       
  3283     d->title = title;
       
  3284     if (d->wizard && d->wizard->currentPage() == this)
       
  3285         d->wizard->d_func()->updateLayout();
       
  3286 }
       
  3287 
       
  3288 QString QWizardPage::title() const
       
  3289 {
       
  3290     Q_D(const QWizardPage);
       
  3291     return d->title;
       
  3292 }
       
  3293 
       
  3294 /*!
       
  3295     \property QWizardPage::subTitle
       
  3296     \brief the subtitle of the page
       
  3297 
       
  3298     The subtitle is shown by the QWizard, between the title and the
       
  3299     actual page. Subtitles are optional. In
       
  3300     \l{QWizard::ClassicStyle}{ClassicStyle} and
       
  3301     \l{QWizard::ModernStyle}{ModernStyle}, using subtitles is
       
  3302     necessary to make the header appear. In
       
  3303     \l{QWizard::MacStyle}{MacStyle}, the subtitle is shown as a text
       
  3304     label just above the actual page.
       
  3305 
       
  3306     The subtitle may be plain text or HTML, depending on the value of
       
  3307     the \l{QWizard::subTitleFormat} property.
       
  3308 
       
  3309     By default, this property contains an empty string.
       
  3310 
       
  3311     \sa title, QWizard::IgnoreSubTitles, {Elements of a Wizard Page}
       
  3312 */
       
  3313 void QWizardPage::setSubTitle(const QString &subTitle)
       
  3314 {
       
  3315     Q_D(QWizardPage);
       
  3316     d->subTitle = subTitle;
       
  3317     if (d->wizard && d->wizard->currentPage() == this)
       
  3318         d->wizard->d_func()->updateLayout();
       
  3319 }
       
  3320 
       
  3321 QString QWizardPage::subTitle() const
       
  3322 {
       
  3323     Q_D(const QWizardPage);
       
  3324     return d->subTitle;
       
  3325 }
       
  3326 
       
  3327 /*!
       
  3328     Sets the pixmap for role \a which to \a pixmap.
       
  3329 
       
  3330     The pixmaps are used by QWizard when displaying a page. Which
       
  3331     pixmaps are actually used depend on the \l{Wizard Look and
       
  3332     Feel}{wizard style}.
       
  3333 
       
  3334     Pixmaps can also be set for the entire wizard using
       
  3335     QWizard::setPixmap(), in which case they apply for all pages that
       
  3336     don't specify a pixmap.
       
  3337 
       
  3338     \sa QWizard::setPixmap(), {Elements of a Wizard Page}
       
  3339 */
       
  3340 void QWizardPage::setPixmap(QWizard::WizardPixmap which, const QPixmap &pixmap)
       
  3341 {
       
  3342     Q_D(QWizardPage);
       
  3343     Q_ASSERT(uint(which) < QWizard::NPixmaps);
       
  3344     d->pixmaps[which] = pixmap;
       
  3345     if (d->wizard && d->wizard->currentPage() == this)
       
  3346         d->wizard->d_func()->updatePixmap(which);
       
  3347 }
       
  3348 
       
  3349 /*!
       
  3350     Returns the pixmap set for role \a which.
       
  3351 
       
  3352     Pixmaps can also be set for the entire wizard using
       
  3353     QWizard::setPixmap(), in which case they apply for all pages that
       
  3354     don't specify a pixmap.
       
  3355 
       
  3356     \sa QWizard::pixmap(), {Elements of a Wizard Page}
       
  3357 */
       
  3358 QPixmap QWizardPage::pixmap(QWizard::WizardPixmap which) const
       
  3359 {
       
  3360     Q_D(const QWizardPage);
       
  3361     Q_ASSERT(uint(which) < QWizard::NPixmaps);
       
  3362 
       
  3363     const QPixmap &pixmap = d->pixmaps[which];
       
  3364     if (!pixmap.isNull())
       
  3365         return pixmap;
       
  3366 
       
  3367     if (wizard())
       
  3368         return wizard()->pixmap(which);
       
  3369 
       
  3370     return pixmap;
       
  3371 }
       
  3372 
       
  3373 /*!
       
  3374     This virtual function is called by QWizard::initializePage() to
       
  3375     prepare the page just before it is shown either as a result of QWizard::restart()
       
  3376     being called, or as a result of the user clicking \gui Next.
       
  3377     (However, if the \l QWizard::IndependentPages option is set, this function is only
       
  3378     called the first time the page is shown.)
       
  3379 
       
  3380     By reimplementing this function, you can ensure that the page's
       
  3381     fields are properly initialized based on fields from previous
       
  3382     pages. For example:
       
  3383 
       
  3384     \snippet examples/dialogs/classwizard/classwizard.cpp 17
       
  3385 
       
  3386     The default implementation does nothing.
       
  3387 
       
  3388     \sa QWizard::initializePage(), cleanupPage(), QWizard::IndependentPages
       
  3389 */
       
  3390 void QWizardPage::initializePage()
       
  3391 {
       
  3392 }
       
  3393 
       
  3394 /*!
       
  3395     This virtual function is called by QWizard::cleanupPage() when
       
  3396     the user leaves the page by clicking \gui Back (unless the \l QWizard::IndependentPages
       
  3397     option is set).
       
  3398 
       
  3399     The default implementation resets the page's fields to their
       
  3400     original values (the values they had before initializePage() was
       
  3401     called).
       
  3402 
       
  3403     \sa QWizard::cleanupPage(), initializePage(), QWizard::IndependentPages
       
  3404 */
       
  3405 void QWizardPage::cleanupPage()
       
  3406 {
       
  3407     Q_D(QWizardPage);
       
  3408     if (d->wizard) {
       
  3409         QVector<QWizardField> &fields = d->wizard->d_func()->fields;
       
  3410         for (int i = 0; i < fields.count(); ++i) {
       
  3411             const QWizardField &field = fields.at(i);
       
  3412             if (field.page == this)
       
  3413                 field.object->setProperty(field.property, field.initialValue);
       
  3414         }
       
  3415     }
       
  3416 }
       
  3417 
       
  3418 /*!
       
  3419     This virtual function is called by QWizard::validateCurrentPage()
       
  3420     when the user clicks \gui Next or \gui Finish to perform some
       
  3421     last-minute validation. If it returns true, the next page is shown
       
  3422     (or the wizard finishes); otherwise, the current page stays up.
       
  3423 
       
  3424     The default implementation returns true.
       
  3425 
       
  3426     When possible, it is usually better style to disable the \gui
       
  3427     Next or \gui Finish button (by specifying \l{mandatory fields} or
       
  3428     reimplementing isComplete()) than to reimplement validatePage().
       
  3429 
       
  3430     \sa QWizard::validateCurrentPage(), isComplete()
       
  3431 */
       
  3432 bool QWizardPage::validatePage()
       
  3433 {
       
  3434     return true;
       
  3435 }
       
  3436 
       
  3437 /*!
       
  3438     This virtual function is called by QWizard to determine whether
       
  3439     the \gui Next or \gui Finish button should be enabled or
       
  3440     disabled.
       
  3441 
       
  3442     The default implementation returns true if all \l{mandatory
       
  3443     fields} are filled; otherwise, it returns false.
       
  3444 
       
  3445     If you reimplement this function, make sure to emit completeChanged(),
       
  3446     from the rest of your implementation, whenever the value of isComplete()
       
  3447     changes. This ensures that QWizard updates the enabled or disabled state of
       
  3448     its buttons. An example of the reimplementation is
       
  3449     available \l{http://qt.nokia.com/doc/qq/qq22-qwizard.html#validatebeforeitstoolate}
       
  3450     {here}.
       
  3451 
       
  3452     \sa completeChanged(), isFinalPage()
       
  3453 */
       
  3454 bool QWizardPage::isComplete() const
       
  3455 {
       
  3456     Q_D(const QWizardPage);
       
  3457 
       
  3458     if (!d->wizard)
       
  3459         return true;
       
  3460 
       
  3461     const QVector<QWizardField> &wizardFields = d->wizard->d_func()->fields;
       
  3462     for (int i = wizardFields.count() - 1; i >= 0; --i) {
       
  3463         const QWizardField &field = wizardFields.at(i);
       
  3464         if (field.page == this && field.mandatory) {
       
  3465             QVariant value = field.object->property(field.property);
       
  3466             if (value == field.initialValue)
       
  3467                 return false;
       
  3468 
       
  3469 #ifndef QT_NO_LINEEDIT
       
  3470             if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(field.object)) {
       
  3471                 if (!lineEdit->hasAcceptableInput())
       
  3472                     return false;
       
  3473             }
       
  3474 #endif
       
  3475 #ifndef QT_NO_SPINBOX
       
  3476             if (QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(field.object)) {
       
  3477                 if (!spinBox->hasAcceptableInput())
       
  3478                     return false;
       
  3479             }
       
  3480 #endif
       
  3481         }
       
  3482     }
       
  3483     return true;
       
  3484 }
       
  3485 
       
  3486 /*!
       
  3487     Explicitly sets this page to be final if \a finalPage is true.
       
  3488 
       
  3489     After calling setFinalPage(true), isFinalPage() returns true and the \gui
       
  3490     Finish button is visible (and enabled if isComplete() returns
       
  3491     true).
       
  3492 
       
  3493     After calling setFinalPage(false), isFinalPage() returns true if
       
  3494     nextId() returns -1; otherwise, it returns false.
       
  3495 
       
  3496     \sa isComplete(), QWizard::HaveFinishButtonOnEarlyPages
       
  3497 */
       
  3498 void QWizardPage::setFinalPage(bool finalPage)
       
  3499 {
       
  3500     Q_D(QWizardPage);
       
  3501     d->explicitlyFinal = finalPage;
       
  3502     QWizard *wizard = this->wizard();
       
  3503     if (wizard && wizard->currentPage() == this)
       
  3504         wizard->d_func()->updateCurrentPage();
       
  3505 }
       
  3506 
       
  3507 /*!
       
  3508     This function is called by QWizard to determine whether the \gui
       
  3509     Finish button should be shown for this page or not.
       
  3510 
       
  3511     By default, it returns true if there is no next page
       
  3512     (i.e., nextId() returns -1); otherwise, it returns false.
       
  3513 
       
  3514     By explicitly calling setFinalPage(true), you can let the user perform an
       
  3515     "early finish".
       
  3516 
       
  3517     \sa isComplete(), QWizard::HaveFinishButtonOnEarlyPages
       
  3518 */
       
  3519 bool QWizardPage::isFinalPage() const
       
  3520 {
       
  3521     Q_D(const QWizardPage);
       
  3522     if (d->explicitlyFinal)
       
  3523         return true;
       
  3524 
       
  3525     QWizard *wizard = this->wizard();
       
  3526     if (wizard && wizard->currentPage() == this) {
       
  3527         // try to use the QWizard implementation if possible
       
  3528         return wizard->nextId() == -1;
       
  3529     } else {
       
  3530         return nextId() == -1;
       
  3531     }
       
  3532 }
       
  3533 
       
  3534 /*!
       
  3535     Sets this page to be a commit page if \a commitPage is true; otherwise,
       
  3536     sets it to be a normal page.
       
  3537 
       
  3538     A commit page is a page that represents an action which cannot be undone
       
  3539     by clicking \gui Back or \gui Cancel.
       
  3540 
       
  3541     A \gui Commit button replaces the \gui Next button on a commit page. Clicking this
       
  3542     button simply calls QWizard::next() just like clicking \gui Next does.
       
  3543 
       
  3544     A page entered directly from a commit page has its \gui Back button disabled.
       
  3545 
       
  3546     \sa isCommitPage()
       
  3547 */
       
  3548 void QWizardPage::setCommitPage(bool commitPage)
       
  3549 {
       
  3550     Q_D(QWizardPage);
       
  3551     d->commit = commitPage;
       
  3552     QWizard *wizard = this->wizard();
       
  3553     if (wizard && wizard->currentPage() == this)
       
  3554         wizard->d_func()->updateCurrentPage();
       
  3555 }
       
  3556 
       
  3557 /*!
       
  3558     Returns true if this page is a commit page; otherwise returns false.
       
  3559 
       
  3560     \sa setCommitPage()
       
  3561 */
       
  3562 bool QWizardPage::isCommitPage() const
       
  3563 {
       
  3564     Q_D(const QWizardPage);
       
  3565     return d->commit;
       
  3566 }
       
  3567 
       
  3568 /*!
       
  3569     Sets the text on button \a which to be \a text on this page.
       
  3570 
       
  3571     By default, the text on buttons depends on the QWizard::wizardStyle,
       
  3572     but may be redefined for the wizard as a whole using QWizard::setButtonText().
       
  3573 
       
  3574     \sa buttonText(), QWizard::setButtonText(), QWizard::buttonText()
       
  3575 */
       
  3576 void QWizardPage::setButtonText(QWizard::WizardButton which, const QString &text)
       
  3577 {
       
  3578     Q_D(QWizardPage);
       
  3579     d->buttonCustomTexts.insert(which, text);
       
  3580     if (wizard() && wizard()->currentPage() == this && wizard()->d_func()->btns[which])
       
  3581         wizard()->d_func()->btns[which]->setText(text);
       
  3582 }
       
  3583 
       
  3584 /*!
       
  3585     Returns the text on button \a which on this page.
       
  3586 
       
  3587     If a text has ben set using setButtonText(), this text is returned.
       
  3588     Otherwise, if a text has been set using QWizard::setButtonText(),
       
  3589     this text is returned.
       
  3590 
       
  3591     By default, the text on buttons depends on the QWizard::wizardStyle.
       
  3592     For example, on Mac OS X, the \gui Next button is called \gui
       
  3593     Continue.
       
  3594 
       
  3595     \sa setButtonText(), QWizard::buttonText(), QWizard::setButtonText()
       
  3596 */
       
  3597 QString QWizardPage::buttonText(QWizard::WizardButton which) const
       
  3598 {
       
  3599     Q_D(const QWizardPage);
       
  3600 
       
  3601     if (d->buttonCustomTexts.contains(which))
       
  3602         return d->buttonCustomTexts.value(which);
       
  3603 
       
  3604     if (wizard())
       
  3605         return wizard()->buttonText(which);
       
  3606 
       
  3607     return QString();
       
  3608 }
       
  3609 
       
  3610 /*!
       
  3611     This virtual function is called by QWizard::nextId() to find
       
  3612     out which page to show when the user clicks the \gui Next button.
       
  3613 
       
  3614     The return value is the ID of the next page, or -1 if no page follows.
       
  3615 
       
  3616     By default, this function returns the lowest ID greater than the ID
       
  3617     of the current page, or -1 if there is no such ID.
       
  3618 
       
  3619     By reimplementing this function, you can specify a dynamic page
       
  3620     order. For example:
       
  3621 
       
  3622     \snippet examples/dialogs/licensewizard/licensewizard.cpp 18
       
  3623 
       
  3624     \sa QWizard::nextId()
       
  3625 */
       
  3626 int QWizardPage::nextId() const
       
  3627 {
       
  3628     Q_D(const QWizardPage);
       
  3629 
       
  3630     if (!d->wizard)
       
  3631         return -1;
       
  3632 
       
  3633     bool foundCurrentPage = false;
       
  3634 
       
  3635     const QWizardPrivate::PageMap &pageMap = d->wizard->d_func()->pageMap;
       
  3636     QWizardPrivate::PageMap::const_iterator i = pageMap.constBegin();
       
  3637     QWizardPrivate::PageMap::const_iterator end = pageMap.constEnd();
       
  3638 
       
  3639     for (; i != end; ++i) {
       
  3640         if (i.value() == this) {
       
  3641             foundCurrentPage = true;
       
  3642         } else if (foundCurrentPage) {
       
  3643             return i.key();
       
  3644         }
       
  3645     }
       
  3646     return -1;
       
  3647 }
       
  3648 
       
  3649 /*!
       
  3650     \fn void QWizardPage::completeChanged()
       
  3651 
       
  3652     This signal is emitted whenever the complete state of the page
       
  3653     (i.e., the value of isComplete()) changes.
       
  3654 
       
  3655     If you reimplement isComplete(), make sure to emit
       
  3656     completeChanged() whenever the value of isComplete() changes, to
       
  3657     ensure that QWizard updates the enabled or disabled state of its
       
  3658     buttons.
       
  3659 
       
  3660     \sa isComplete()
       
  3661 */
       
  3662 
       
  3663 /*!
       
  3664     Sets the value of the field called \a name to \a value.
       
  3665 
       
  3666     This function can be used to set fields on any page of the wizard.
       
  3667     It is equivalent to calling
       
  3668     wizard()->\l{QWizard::setField()}{setField(\a name, \a value)}.
       
  3669 
       
  3670     \sa QWizard::setField(), field(), registerField()
       
  3671 */
       
  3672 void QWizardPage::setField(const QString &name, const QVariant &value)
       
  3673 {
       
  3674     Q_D(QWizardPage);
       
  3675     if (!d->wizard)
       
  3676         return;
       
  3677     d->wizard->setField(name, value);
       
  3678 }
       
  3679 
       
  3680 /*!
       
  3681     Returns the value of the field called \a name.
       
  3682 
       
  3683     This function can be used to access fields on any page of the
       
  3684     wizard. It is equivalent to calling
       
  3685     wizard()->\l{QWizard::field()}{field(\a name)}.
       
  3686 
       
  3687     Example:
       
  3688 
       
  3689     \snippet examples/dialogs/classwizard/classwizard.cpp 17
       
  3690 
       
  3691     \sa QWizard::field(), setField(), registerField()
       
  3692 */
       
  3693 QVariant QWizardPage::field(const QString &name) const
       
  3694 {
       
  3695     Q_D(const QWizardPage);
       
  3696     if (!d->wizard)
       
  3697         return QVariant();
       
  3698     return d->wizard->field(name);
       
  3699 }
       
  3700 
       
  3701 /*!
       
  3702     Creates a field called \a name associated with the given \a
       
  3703     property of the given \a widget. From then on, that property
       
  3704     becomes accessible using field() and setField().
       
  3705 
       
  3706     Fields are global to the entire wizard and make it easy for any
       
  3707     single page to access information stored by another page, without
       
  3708     having to put all the logic in QWizard or having the pages know
       
  3709     explicitly about each other.
       
  3710 
       
  3711     If \a name ends with an asterisk (\c *), the field is a mandatory
       
  3712     field. When a page has mandatory fields, the \gui Next and/or
       
  3713     \gui Finish buttons are enabled only when all mandatory fields
       
  3714     are filled. This requires a \a changedSignal to be specified, to
       
  3715     tell QWizard to recheck the value stored by the mandatory field.
       
  3716 
       
  3717     QWizard knows the most common Qt widgets. For these (or their
       
  3718     subclasses), you don't need to specify a \a property or a \a
       
  3719     changedSignal. The table below lists these widgets:
       
  3720 
       
  3721     \table
       
  3722     \header \o Widget          \o Property                            \o Change Notification Signal
       
  3723     \row    \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()}
       
  3724     \row    \o QAbstractSlider \o int \l{QAbstractSlider::}{value}    \o \l{QAbstractSlider::}{valueChanged()}
       
  3725     \row    \o QComboBox       \o int \l{QComboBox::}{currentIndex}   \o \l{QComboBox::}{currentIndexChanged()}
       
  3726     \row    \o QDateTimeEdit   \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()}
       
  3727     \row    \o QLineEdit       \o QString \l{QLineEdit::}{text}       \o \l{QLineEdit::}{textChanged()}
       
  3728     \row    \o QListWidget     \o int \l{QListWidget::}{currentRow}   \o \l{QListWidget::}{currentRowChanged()}
       
  3729     \row    \o QSpinBox        \o int \l{QSpinBox::}{value}           \o \l{QSpinBox::}{valueChanged()}
       
  3730     \endtable
       
  3731 
       
  3732     You can use QWizard::setDefaultProperty() to add entries to this
       
  3733     table or to override existing entries.
       
  3734 
       
  3735     To consider a field "filled", QWizard simply checks that their
       
  3736     current value doesn't equal their original value (the value they
       
  3737     had before initializePage() was called). For QLineEdit, it also
       
  3738     checks that
       
  3739     \l{QLineEdit::hasAcceptableInput()}{hasAcceptableInput()} returns
       
  3740     true, to honor any validator or mask.
       
  3741 
       
  3742     QWizard's mandatory field mechanism is provided for convenience.
       
  3743     It can be bypassed by reimplementing QWizardPage::isComplete().
       
  3744 
       
  3745     \sa field(), setField(), QWizard::setDefaultProperty()
       
  3746 */
       
  3747 void QWizardPage::registerField(const QString &name, QWidget *widget, const char *property,
       
  3748                                 const char *changedSignal)
       
  3749 {
       
  3750     Q_D(QWizardPage);
       
  3751     QWizardField field(this, name, widget, property, changedSignal);
       
  3752     if (d->wizard) {
       
  3753         d->wizard->d_func()->addField(field);
       
  3754     } else {
       
  3755         d->pendingFields += field;
       
  3756     }
       
  3757 }
       
  3758 
       
  3759 /*!
       
  3760     Returns the wizard associated with this page, or 0 if this page
       
  3761     hasn't been inserted into a QWizard yet.
       
  3762 
       
  3763     \sa QWizard::addPage(), QWizard::setPage()
       
  3764 */
       
  3765 QWizard *QWizardPage::wizard() const
       
  3766 {
       
  3767     Q_D(const QWizardPage);
       
  3768     return d->wizard;
       
  3769 }
       
  3770 
       
  3771 QT_END_NAMESPACE
       
  3772 
       
  3773 #include "moc_qwizard.cpp"
       
  3774 
       
  3775 #endif // QT_NO_WIZARD