util/src/gui/dialogs/qwizard.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 #ifndef QT_NO_CURSOR
       
  1541         q->unsetCursor(); // ### ditto
       
  1542 #endif
       
  1543         antiFlickerWidget->move(0, 0);
       
  1544         vistaHelper->hideBackButton();
       
  1545         vistaHelper->setTitleBarIconAndCaptionVisible(true);
       
  1546     }
       
  1547 
       
  1548     _q_updateButtonStates();
       
  1549 
       
  1550     if (q->isVisible())
       
  1551         vistaHelper->setWindowPosHack();
       
  1552 
       
  1553     inHandleAeroStyleChange = false;
       
  1554 }
       
  1555 #endif
       
  1556 
       
  1557 bool QWizardPrivate::isVistaThemeEnabled() const
       
  1558 {
       
  1559 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1560     return isVistaThemeEnabled(QVistaHelper::VistaAero)
       
  1561         || isVistaThemeEnabled(QVistaHelper::VistaBasic);
       
  1562 #else
       
  1563     return false;
       
  1564 #endif
       
  1565 }
       
  1566 
       
  1567 void QWizardPrivate::disableUpdates()
       
  1568 {
       
  1569     Q_Q(QWizard);
       
  1570     if (disableUpdatesCount++ == 0) {
       
  1571         q->setUpdatesEnabled(false);
       
  1572         antiFlickerWidget->hide();
       
  1573     }
       
  1574 }
       
  1575 
       
  1576 void QWizardPrivate::enableUpdates()
       
  1577 {
       
  1578     Q_Q(QWizard);
       
  1579     if (--disableUpdatesCount == 0) {
       
  1580         antiFlickerWidget->show();
       
  1581         q->setUpdatesEnabled(true);
       
  1582     }
       
  1583 }
       
  1584 
       
  1585 void QWizardPrivate::_q_emitCustomButtonClicked()
       
  1586 {
       
  1587     Q_Q(QWizard);
       
  1588     QObject *button = q->sender();
       
  1589     for (int i = QWizard::NStandardButtons; i < QWizard::NButtons; ++i) {
       
  1590         if (btns[i] == button) {
       
  1591             emit q->customButtonClicked(QWizard::WizardButton(i));
       
  1592             break;
       
  1593         }
       
  1594     }
       
  1595 }
       
  1596 
       
  1597 void QWizardPrivate::_q_updateButtonStates()
       
  1598 {
       
  1599     Q_Q(QWizard);
       
  1600 
       
  1601     disableUpdates();
       
  1602 
       
  1603     const QWizardPage *page = q->currentPage();
       
  1604     bool complete = page && page->isComplete();
       
  1605 
       
  1606     btn.back->setEnabled(history.count() > 1
       
  1607                          && !q->page(history.at(history.count() - 2))->isCommitPage()
       
  1608                          && (!canFinish || !(opts & QWizard::DisabledBackButtonOnLastPage)));
       
  1609     btn.next->setEnabled(canContinue && complete);
       
  1610     btn.commit->setEnabled(canContinue && complete);
       
  1611     btn.finish->setEnabled(canFinish && complete);
       
  1612 
       
  1613     const bool backButtonVisible = buttonLayoutContains(QWizard::BackButton)
       
  1614         && (history.count() > 1 || !(opts & QWizard::NoBackButtonOnStartPage))
       
  1615         && (canContinue || !(opts & QWizard::NoBackButtonOnLastPage));
       
  1616     bool commitPage = page && page->isCommitPage();
       
  1617     btn.back->setVisible(backButtonVisible);
       
  1618     btn.next->setVisible(buttonLayoutContains(QWizard::NextButton) && !commitPage
       
  1619                          && (canContinue || (opts & QWizard::HaveNextButtonOnLastPage)));
       
  1620     btn.commit->setVisible(buttonLayoutContains(QWizard::CommitButton) && commitPage
       
  1621                            && canContinue);
       
  1622     btn.finish->setVisible(buttonLayoutContains(QWizard::FinishButton)
       
  1623                            && (canFinish || (opts & QWizard::HaveFinishButtonOnEarlyPages)));
       
  1624 
       
  1625     bool useDefault = !(opts & QWizard::NoDefaultButton);
       
  1626     if (QPushButton *nextPush = qobject_cast<QPushButton *>(btn.next))
       
  1627         nextPush->setDefault(canContinue && useDefault && !commitPage);
       
  1628     if (QPushButton *commitPush = qobject_cast<QPushButton *>(btn.commit))
       
  1629         commitPush->setDefault(canContinue && useDefault && commitPage);
       
  1630     if (QPushButton *finishPush = qobject_cast<QPushButton *>(btn.finish))
       
  1631         finishPush->setDefault(!canContinue && useDefault);
       
  1632 
       
  1633 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1634     if (isVistaThemeEnabled()) {
       
  1635         vistaHelper->backButton()->setEnabled(btn.back->isEnabled());
       
  1636         vistaHelper->backButton()->setVisible(backButtonVisible);
       
  1637         btn.back->setVisible(false);
       
  1638     }
       
  1639 #endif
       
  1640 
       
  1641 #ifdef QT_SOFTKEYS_ENABLED
       
  1642     QAbstractButton *wizardButton;
       
  1643     for (int i = 0; i < QWizard::NButtons; ++i) {
       
  1644         wizardButton = btns[i];
       
  1645         if (wizardButton && !wizardButton->testAttribute(Qt::WA_WState_Hidden)) {
       
  1646             wizardButton->hide();
       
  1647             q->addAction(softKeys[i]);
       
  1648         } else {
       
  1649             q->removeAction(softKeys[i]);
       
  1650         }
       
  1651     }
       
  1652 #endif
       
  1653 
       
  1654     enableUpdates();
       
  1655 }
       
  1656 
       
  1657 void QWizardPrivate::_q_handleFieldObjectDestroyed(QObject *object)
       
  1658 {
       
  1659     QVector<QWizardField>::iterator it = fields.begin();
       
  1660     while (it != fields.end()) {
       
  1661         const QWizardField &field = *it;
       
  1662         if (field.object == object) {
       
  1663             fieldIndexMap.remove(field.name);
       
  1664             it = fields.erase(it);
       
  1665         } else {
       
  1666             ++it;
       
  1667         }
       
  1668     }
       
  1669 }
       
  1670 
       
  1671 void QWizardPrivate::setStyle(QStyle *style)
       
  1672 {
       
  1673     for (int i = 0; i < QWizard::NButtons; i++)
       
  1674         if (btns[i])
       
  1675             btns[i]->setStyle(style);
       
  1676     const PageMap::const_iterator pcend = pageMap.constEnd();
       
  1677     for (PageMap::const_iterator it = pageMap.constBegin(); it != pcend; ++it)
       
  1678         it.value()->setStyle(style);
       
  1679 }
       
  1680 
       
  1681 #ifdef Q_WS_MAC
       
  1682 
       
  1683 QPixmap QWizardPrivate::findDefaultBackgroundPixmap()
       
  1684 {
       
  1685     QCFType<CFURLRef> url;
       
  1686     const int ExpectedImageWidth = 242;
       
  1687     const int ExpectedImageHeight = 414;
       
  1688     if (LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.KeyboardSetupAssistant"),
       
  1689                                  0, 0, &url) == noErr) {
       
  1690         QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, url);
       
  1691         if (bundle) {
       
  1692             url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("tif"), 0);
       
  1693             if (url) {
       
  1694                 QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0);
       
  1695                 QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
       
  1696                 if (image) {
       
  1697                     int width = CGImageGetWidth(image);
       
  1698                     int height = CGImageGetHeight(image);
       
  1699                     if (width == ExpectedImageWidth && height == ExpectedImageHeight)
       
  1700                         return QPixmap::fromMacCGImageRef(image);
       
  1701                 }
       
  1702             }
       
  1703         }
       
  1704     }
       
  1705     return QPixmap();
       
  1706 
       
  1707 }
       
  1708 
       
  1709 #endif
       
  1710 
       
  1711 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  1712 void QWizardAntiFlickerWidget::paintEvent(QPaintEvent *)
       
  1713 {
       
  1714     if (wizardPrivate->isVistaThemeEnabled()) {
       
  1715         int leftMargin, topMargin, rightMargin, bottomMargin;
       
  1716         wizardPrivate->buttonLayout->getContentsMargins(
       
  1717             &leftMargin, &topMargin, &rightMargin, &bottomMargin);
       
  1718         const int buttonLayoutTop = wizardPrivate->buttonLayout->contentsRect().top() - topMargin;
       
  1719         QPainter painter(this);
       
  1720         const QBrush brush(QColor(240, 240, 240)); // ### hardcoded for now
       
  1721         painter.fillRect(0, buttonLayoutTop, width(), height() - buttonLayoutTop, brush);
       
  1722         painter.setPen(QPen(QBrush(QColor(223, 223, 223)), 0)); // ### hardcoded for now
       
  1723         painter.drawLine(0, buttonLayoutTop, width(), buttonLayoutTop);
       
  1724         if (wizardPrivate->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
       
  1725             if (window()->isActiveWindow())
       
  1726                 painter.setPen(QPen(QBrush(QColor(169, 191, 214)), 0)); // ### hardcoded for now
       
  1727             else
       
  1728                 painter.setPen(QPen(QBrush(QColor(182, 193, 204)), 0)); // ### hardcoded for now
       
  1729             painter.drawLine(0, 0, width(), 0);
       
  1730         }
       
  1731     }
       
  1732 }
       
  1733 #endif
       
  1734 
       
  1735 /*!
       
  1736     \class QWizard
       
  1737     \since 4.3
       
  1738     \brief The QWizard class provides a framework for wizards.
       
  1739 
       
  1740     A wizard (also called an assistant on Mac OS X) is a special type
       
  1741     of input dialog that consists of a sequence of pages. A wizard's
       
  1742     purpose is to guide the user through a process step by step.
       
  1743     Wizards are useful for complex or infrequent tasks that users may
       
  1744     find difficult to learn.
       
  1745 
       
  1746     QWizard inherits QDialog and represents a wizard. Each page is a
       
  1747     QWizardPage (a QWidget subclass). To create your own wizards, you
       
  1748     can use these classes directly, or you can subclass them for more
       
  1749     control.
       
  1750 
       
  1751     Topics:
       
  1752 
       
  1753     \tableofcontents
       
  1754 
       
  1755     \section1 A Trivial Example
       
  1756 
       
  1757     The following example illustrates how to create wizard pages and
       
  1758     add them to a wizard. For more advanced examples, see
       
  1759     \l{dialogs/classwizard}{Class Wizard} and \l{dialogs/licensewizard}{License
       
  1760     Wizard}.
       
  1761 
       
  1762     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 1
       
  1763     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 3
       
  1764     \dots
       
  1765     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 4
       
  1766     \codeline
       
  1767     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 5
       
  1768     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 7
       
  1769     \dots
       
  1770     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 8
       
  1771     \codeline
       
  1772     \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 10
       
  1773 
       
  1774     \section1 Wizard Look and Feel
       
  1775 
       
  1776     QWizard supports four wizard looks:
       
  1777 
       
  1778     \list
       
  1779     \o ClassicStyle
       
  1780     \o ModernStyle
       
  1781     \o MacStyle
       
  1782     \o AeroStyle
       
  1783     \endlist
       
  1784 
       
  1785     You can explicitly set the look to use using setWizardStyle()
       
  1786     (e.g., if you want the same look on all platforms).
       
  1787 
       
  1788     \table
       
  1789     \header \o ClassicStyle
       
  1790             \o ModernStyle
       
  1791             \o MacStyle
       
  1792             \o AeroStyle
       
  1793     \row    \o \inlineimage qtwizard-classic1.png
       
  1794             \o \inlineimage qtwizard-modern1.png
       
  1795             \o \inlineimage qtwizard-mac1.png
       
  1796             \o \inlineimage qtwizard-aero1.png
       
  1797     \row    \o \inlineimage qtwizard-classic2.png
       
  1798             \o \inlineimage qtwizard-modern2.png
       
  1799             \o \inlineimage qtwizard-mac2.png
       
  1800             \o \inlineimage qtwizard-aero2.png
       
  1801     \endtable
       
  1802 
       
  1803     Note: AeroStyle has effect only on a Windows Vista system with alpha compositing enabled.
       
  1804     ModernStyle is used as a fallback when this condition is not met.
       
  1805 
       
  1806     In addition to the wizard style, there are several options that
       
  1807     control the look and feel of the wizard. These can be set using
       
  1808     setOption() or setOptions(). For example, HaveHelpButton makes
       
  1809     QWizard show a \gui Help button along with the other wizard
       
  1810     buttons.
       
  1811 
       
  1812     You can even change the order of the wizard buttons to any
       
  1813     arbitrary order using setButtonLayout(), and you can add up to
       
  1814     three custom buttons (e.g., a \gui Print button) to the button
       
  1815     row. This is achieved by calling setButton() or setButtonText()
       
  1816     with CustomButton1, CustomButton2, or CustomButton3 to set up the
       
  1817     button, and by enabling the HaveCustomButton1, HaveCustomButton2,
       
  1818     or HaveCustomButton3 options. Whenever the user clicks a custom
       
  1819     button, customButtonClicked() is emitted. For example:
       
  1820 
       
  1821     \snippet examples/dialogs/licensewizard/licensewizard.cpp 29
       
  1822 
       
  1823     \section1 Elements of a Wizard Page
       
  1824 
       
  1825     Wizards consist of a sequence of \l{QWizardPage}s. At any time,
       
  1826     only one page is shown. A page has the following attributes:
       
  1827 
       
  1828     \list
       
  1829     \o A \l{QWizardPage::}{title}.
       
  1830     \o A \l{QWizardPage::}{subTitle}.
       
  1831     \o A set of pixmaps, which may or may not be honored, depending
       
  1832        on the wizard's style:
       
  1833         \list
       
  1834         \o WatermarkPixmap (used by ClassicStyle and ModernStyle)
       
  1835         \o BannerPixmap (used by ModernStyle)
       
  1836         \o LogoPixmap (used by ClassicStyle and ModernStyle)
       
  1837         \o BackgroundPixmap (used by MacStyle)
       
  1838         \endlist
       
  1839     \endlist
       
  1840 
       
  1841     The diagram belows shows how QWizard renders these attributes,
       
  1842     assuming they are all present and ModernStyle is used:
       
  1843 
       
  1844     \image qtwizard-nonmacpage.png
       
  1845 
       
  1846     When a \l{QWizardPage::}{subTitle} is set, QWizard displays it
       
  1847     in a header, in which case it also uses the BannerPixmap and the
       
  1848     LogoPixmap to decorate the header. The WatermarkPixmap is
       
  1849     displayed on the left side, below the header. At the bottom,
       
  1850     there is a row of buttons allowing the user to navigate through
       
  1851     the pages.
       
  1852 
       
  1853     The page itself (the \l{QWizardPage} widget) occupies the area
       
  1854     between the header, the watermark, and the button row. Typically,
       
  1855     the page is a QWizardPage on which a QGridLayout is installed,
       
  1856     with standard child widgets (\l{QLabel}s, \l{QLineEdit}s, etc.).
       
  1857 
       
  1858     If the wizard's style is MacStyle, the page looks radically
       
  1859     different:
       
  1860 
       
  1861     \image qtwizard-macpage.png
       
  1862 
       
  1863     The watermark, banner, and logo pixmaps are ignored by the
       
  1864     MacStyle. If the BackgroundPixmap is set, it is used as the
       
  1865     background for the wizard; otherwise, a default "assistant" image
       
  1866     is used.
       
  1867 
       
  1868     The title and subtitle are set by calling
       
  1869     QWizardPage::setTitle() and QWizardPage::setSubTitle() on the
       
  1870     individual pages. They may be plain text or HTML (see titleFormat
       
  1871     and subTitleFormat). The pixmaps can be set globally for the
       
  1872     entire wizard using setPixmap(), or on a per-page basis using
       
  1873     QWizardPage::setPixmap().
       
  1874 
       
  1875     \target field mechanism
       
  1876     \section1 Registering and Using Fields
       
  1877 
       
  1878     In many wizards, the contents of a page may affect the default
       
  1879     values of the fields of a later page. To make it easy to
       
  1880     communicate between pages, QWizard supports a "field" mechanism
       
  1881     that allows you to register a field (e.g., a QLineEdit) on a page
       
  1882     and to access its value from any page. It is also possible to
       
  1883     specify mandatory fields (i.e., fields that must be filled before
       
  1884     the user can advance to the next page).
       
  1885 
       
  1886     To register a field, call QWizardPage::registerField() field.
       
  1887     For example:
       
  1888 
       
  1889     \snippet examples/dialogs/classwizard/classwizard.cpp 8
       
  1890     \dots
       
  1891     \snippet examples/dialogs/classwizard/classwizard.cpp 10
       
  1892     \snippet examples/dialogs/classwizard/classwizard.cpp 11
       
  1893     \dots
       
  1894     \snippet examples/dialogs/classwizard/classwizard.cpp 13
       
  1895 
       
  1896     The above code registers three fields, \c className, \c
       
  1897     baseClass, and \c qobjectMacro, which are associated with three
       
  1898     child widgets. The asterisk (\c *) next to \c className denotes a
       
  1899     mandatory field.
       
  1900 
       
  1901     \target initialize page
       
  1902     The fields of any page are accessible from any other page. For
       
  1903     example:
       
  1904 
       
  1905     \snippet examples/dialogs/classwizard/classwizard.cpp 17
       
  1906 
       
  1907     Here, we call QWizardPage::field() to access the contents of the
       
  1908     \c className field (which was defined in the \c ClassInfoPage)
       
  1909     and use it to initialize the \c OuputFilePage. The field's
       
  1910     contents is returned as a QVariant.
       
  1911 
       
  1912     When we create a field using QWizardPage::registerField(), we
       
  1913     pass a unique field name and a widget. We can also provide a Qt
       
  1914     property name and a "changed" signal (a signal that is emitted
       
  1915     when the property changes) as third and fourth arguments;
       
  1916     however, this is not necessary for the most common Qt widgets,
       
  1917     such as QLineEdit, QCheckBox, and QComboBox, because QWizard
       
  1918     knows which properties to look for.
       
  1919 
       
  1920     \target mandatory fields
       
  1921 
       
  1922     If an asterisk (\c *) is appended to the name when the property
       
  1923     is registered, the field is a \e{mandatory field}. When a page has
       
  1924     mandatory fields, the \gui Next and/or \gui Finish buttons are
       
  1925     enabled only when all mandatory fields are filled.
       
  1926 
       
  1927     To consider a field "filled", QWizard simply checks that the
       
  1928     field's current value doesn't equal the original value (the value
       
  1929     it had when initializePage() was called). For QLineEdit and
       
  1930     QAbstractSpinBox subclasses, QWizard also checks that
       
  1931     \l{QLineEdit::hasAcceptableInput()}{hasAcceptableInput()} returns
       
  1932     true, to honor any validator or mask.
       
  1933 
       
  1934     QWizard's mandatory field mechanism is provided for convenience.
       
  1935     A more powerful (but also more cumbersome) alternative is to
       
  1936     reimplement QWizardPage::isComplete() and to emit the
       
  1937     QWizardPage::completeChanged() signal whenever the page becomes
       
  1938     complete or incomplete.
       
  1939 
       
  1940     The enabled/disabled state of the \gui Next and/or \gui Finish
       
  1941     buttons is one way to perform validation on the user input.
       
  1942     Another way is to reimplement validateCurrentPage() (or
       
  1943     QWizardPage::validatePage()) to perform some last-minute
       
  1944     validation (and show an error message if the user has entered
       
  1945     incomplete or invalid information). If the function returns true,
       
  1946     the next page is shown (or the wizard finishes); otherwise, the
       
  1947     current page stays up.
       
  1948 
       
  1949     \section1 Creating Linear Wizards
       
  1950 
       
  1951     Most wizards have a linear structure, with page 1 followed by
       
  1952     page 2 and so on until the last page. The \l{dialogs/classwizard}{Class
       
  1953     Wizard} example is such a wizard. With QWizard, linear wizards
       
  1954     are created by instantiating the \l{QWizardPage}s and inserting
       
  1955     them using addPage(). By default, the pages are shown in the
       
  1956     order in which they were added. For example:
       
  1957 
       
  1958     \snippet examples/dialogs/classwizard/classwizard.cpp 0
       
  1959     \dots
       
  1960     \snippet examples/dialogs/classwizard/classwizard.cpp 2
       
  1961 
       
  1962     When a page is about to be shown, QWizard calls initializePage()
       
  1963     (which in turn calls QWizardPage::initializePage()) to fill the
       
  1964     page with default values. By default, this function does nothing,
       
  1965     but it can be reimplemented to initialize the page's contents
       
  1966     based on other pages' fields (see the \l{initialize page}{example
       
  1967     above}).
       
  1968 
       
  1969     If the user presses \gui Back, cleanupPage() is called (which in
       
  1970     turn calls QWizardPage::cleanupPage()). The default
       
  1971     implementation resets the page's fields to their original values
       
  1972     (the values they had before initializePage() was called). If you
       
  1973     want the \gui Back button to be non-destructive and keep the
       
  1974     values entered by the user, simply enable the IndependentPages
       
  1975     option.
       
  1976 
       
  1977     \section1 Creating Non-Linear Wizards
       
  1978 
       
  1979     Some wizards are more complex in that they allow different
       
  1980     traversal paths based on the information provided by the user.
       
  1981     The \l{dialogs/licensewizard}{License Wizard} example illustrates this.
       
  1982     It provides five wizard pages; depending on which options are
       
  1983     selected, the user can reach different pages.
       
  1984 
       
  1985     \image licensewizard-flow.png
       
  1986 
       
  1987     In complex wizards, pages are identified by IDs. These IDs are
       
  1988     typically defined using an enum. For example:
       
  1989 
       
  1990     \snippet examples/dialogs/licensewizard/licensewizard.h 0
       
  1991     \dots
       
  1992     \snippet examples/dialogs/licensewizard/licensewizard.h 2
       
  1993     \dots
       
  1994     \snippet examples/dialogs/licensewizard/licensewizard.h 3
       
  1995 
       
  1996     The pages are inserted using setPage(), which takes an ID and an
       
  1997     instance of QWizardPage (or of a subclass):
       
  1998 
       
  1999     \snippet examples/dialogs/licensewizard/licensewizard.cpp 1
       
  2000     \dots
       
  2001     \snippet examples/dialogs/licensewizard/licensewizard.cpp 8
       
  2002 
       
  2003     By default, the pages are shown in increasing ID order. To
       
  2004     provide a dynamic order that depends on the options chosen by the
       
  2005     user, we must reimplement QWizardPage::nextId(). For example:
       
  2006 
       
  2007     \snippet examples/dialogs/licensewizard/licensewizard.cpp 18
       
  2008     \codeline
       
  2009     \snippet examples/dialogs/licensewizard/licensewizard.cpp 23
       
  2010     \codeline
       
  2011     \snippet examples/dialogs/licensewizard/licensewizard.cpp 24
       
  2012     \codeline
       
  2013     \snippet examples/dialogs/licensewizard/licensewizard.cpp 25
       
  2014     \codeline
       
  2015     \snippet examples/dialogs/licensewizard/licensewizard.cpp 26
       
  2016 
       
  2017     It would also be possible to put all the logic in one place, in a
       
  2018     QWizard::nextId() reimplementation. For example:
       
  2019 
       
  2020     \snippet doc/src/snippets/code/src_gui_dialogs_qwizard.cpp 0
       
  2021 
       
  2022     To start at another page than the page with the lowest ID, call
       
  2023     setStartId().
       
  2024 
       
  2025     To test whether a page has been visited or not, call
       
  2026     hasVisitedPage(). For example:
       
  2027 
       
  2028     \snippet examples/dialogs/licensewizard/licensewizard.cpp 27
       
  2029 
       
  2030     \sa QWizardPage, {Class Wizard Example}, {License Wizard Example}
       
  2031 */
       
  2032 
       
  2033 /*!
       
  2034     \enum QWizard::WizardButton
       
  2035 
       
  2036     This enum specifies the buttons in a wizard.
       
  2037 
       
  2038     \value BackButton  The \gui Back button (\gui {Go Back} on Mac OS X)
       
  2039     \value NextButton  The \gui Next button (\gui Continue on Mac OS X)
       
  2040     \value CommitButton  The \gui Commit button
       
  2041     \value FinishButton  The \gui Finish button (\gui Done on Mac OS X)
       
  2042     \value CancelButton  The \gui Cancel button (see also NoCancelButton)
       
  2043     \value HelpButton    The \gui Help button (see also HaveHelpButton)
       
  2044     \value CustomButton1  The first user-defined button (see also HaveCustomButton1)
       
  2045     \value CustomButton2  The second user-defined button (see also HaveCustomButton2)
       
  2046     \value CustomButton3  The third user-defined button (see also HaveCustomButton3)
       
  2047 
       
  2048     The following value is only useful when calling setButtonLayout():
       
  2049 
       
  2050     \value Stretch  A horizontal stretch in the button layout
       
  2051 
       
  2052     \omitvalue NoButton
       
  2053     \omitvalue NStandardButtons
       
  2054     \omitvalue NButtons
       
  2055 
       
  2056     \sa setButton(), setButtonText(), setButtonLayout(), customButtonClicked()
       
  2057 */
       
  2058 
       
  2059 /*!
       
  2060     \enum QWizard::WizardPixmap
       
  2061 
       
  2062     This enum specifies the pixmaps that can be associated with a page.
       
  2063 
       
  2064     \value WatermarkPixmap  The tall pixmap on the left side of a ClassicStyle or ModernStyle page
       
  2065     \value LogoPixmap  The small pixmap on the right side of a ClassicStyle or ModernStyle page header
       
  2066     \value BannerPixmap  The pixmap that occupies the background of a ModernStyle page header
       
  2067     \value BackgroundPixmap  The pixmap that occupies the background of a MacStyle wizard
       
  2068 
       
  2069     \omitvalue NPixmaps
       
  2070 
       
  2071     \sa setPixmap(), QWizardPage::setPixmap(), {Elements of a Wizard Page}
       
  2072 */
       
  2073 
       
  2074 /*!
       
  2075     \enum QWizard::WizardStyle
       
  2076 
       
  2077     This enum specifies the different looks supported by QWizard.
       
  2078 
       
  2079     \value ClassicStyle  Classic Windows look
       
  2080     \value ModernStyle  Modern Windows look
       
  2081     \value MacStyle  Mac OS X look
       
  2082     \value AeroStyle  Windows Aero look
       
  2083 
       
  2084     \omitvalue NStyles
       
  2085 
       
  2086     \sa setWizardStyle(), WizardOption, {Wizard Look and Feel}
       
  2087 */
       
  2088 
       
  2089 /*!
       
  2090     \enum QWizard::WizardOption
       
  2091 
       
  2092     This enum specifies various options that affect the look and feel
       
  2093     of a wizard.
       
  2094 
       
  2095     \value IndependentPages  The pages are independent of each other
       
  2096                              (i.e., they don't derive values from each
       
  2097                              other).
       
  2098     \value IgnoreSubTitles  Don't show any subtitles, even if they are set.
       
  2099     \value ExtendedWatermarkPixmap  Extend any WatermarkPixmap all the
       
  2100                                     way down to the window's edge.
       
  2101     \value NoDefaultButton  Don't make the \gui Next or \gui Finish button the
       
  2102                             dialog's \l{QPushButton::setDefault()}{default button}.
       
  2103     \value NoBackButtonOnStartPage  Don't show the \gui Back button on the start page.
       
  2104     \value NoBackButtonOnLastPage   Don't show the \gui Back button on the last page.
       
  2105     \value DisabledBackButtonOnLastPage  Disable the \gui Back button on the last page.
       
  2106     \value HaveNextButtonOnLastPage  Show the (disabled) \gui Next button on the last page.
       
  2107     \value HaveFinishButtonOnEarlyPages  Show the (disabled) \gui Finish button on non-final pages.
       
  2108     \value NoCancelButton  Don't show the \gui Cancel button.
       
  2109     \value CancelButtonOnLeft  Put the \gui Cancel button on the left of \gui Back (rather than on
       
  2110                                the right of \gui Finish or \gui Next).
       
  2111     \value HaveHelpButton  Show the \gui Help button.
       
  2112     \value HelpButtonOnRight  Put the \gui Help button on the far right of the button layout
       
  2113                               (rather than on the far left).
       
  2114     \value HaveCustomButton1  Show the first user-defined button (CustomButton1).
       
  2115     \value HaveCustomButton2  Show the second user-defined button (CustomButton2).
       
  2116     \value HaveCustomButton3  Show the third user-defined button (CustomButton3).
       
  2117 
       
  2118     \sa setOptions(), setOption(), testOption()
       
  2119 */
       
  2120 
       
  2121 /*!
       
  2122     Constructs a wizard with the given \a parent and window \a flags.
       
  2123 
       
  2124     \sa parent(), windowFlags()
       
  2125 */
       
  2126 QWizard::QWizard(QWidget *parent, Qt::WindowFlags flags)
       
  2127     : QDialog(*new QWizardPrivate, parent, flags)
       
  2128 {
       
  2129     Q_D(QWizard);
       
  2130     d->init();
       
  2131 #ifdef Q_WS_WINCE
       
  2132     if (!qt_wince_is_mobile())
       
  2133         setWindowFlags(windowFlags() & ~Qt::WindowOkButtonHint);
       
  2134 #endif
       
  2135 }
       
  2136 
       
  2137 /*!
       
  2138     Destroys the wizard and its pages, releasing any allocated resources.
       
  2139 */
       
  2140 QWizard::~QWizard()
       
  2141 {
       
  2142     Q_D(QWizard);
       
  2143     delete d->buttonLayout;
       
  2144 }
       
  2145 
       
  2146 /*!
       
  2147     Adds the given \a page to the wizard, and returns the page's ID.
       
  2148 
       
  2149     The ID is guaranteed to be larger than any other ID in the
       
  2150     QWizard so far.
       
  2151 
       
  2152     \sa setPage(), page()
       
  2153 */
       
  2154 int QWizard::addPage(QWizardPage *page)
       
  2155 {
       
  2156     Q_D(QWizard);
       
  2157     int theid = 0;
       
  2158     if (!d->pageMap.isEmpty())
       
  2159         theid = (d->pageMap.constEnd() - 1).key() + 1;
       
  2160     setPage(theid, page);
       
  2161     return theid;
       
  2162 }
       
  2163 
       
  2164 /*!
       
  2165     \fn void QWizard::setPage(int id, QWizardPage *page)
       
  2166 
       
  2167     Adds the given \a page to the wizard with the given \a id.
       
  2168 
       
  2169     \sa addPage(), page()
       
  2170 */
       
  2171 void QWizard::setPage(int theid, QWizardPage *page)
       
  2172 {
       
  2173     Q_D(QWizard);
       
  2174 
       
  2175     if (!page) {
       
  2176         qWarning("QWizard::setPage: Cannot insert null page");
       
  2177         return;
       
  2178     }
       
  2179 
       
  2180     if (theid == -1) {
       
  2181         qWarning("QWizard::setPage: Cannot insert page with ID -1");
       
  2182         return;
       
  2183     }
       
  2184 
       
  2185     if (d->pageMap.contains(theid)) {
       
  2186         qWarning("QWizard::setPage: Page with duplicate ID %d ignored", theid);
       
  2187         return;
       
  2188     }
       
  2189 
       
  2190     page->setParent(d->pageFrame);
       
  2191 
       
  2192     QVector<QWizardField> &pendingFields = page->d_func()->pendingFields;
       
  2193     for (int i = 0; i < pendingFields.count(); ++i)
       
  2194         d->addField(pendingFields.at(i));
       
  2195     pendingFields.clear();
       
  2196 
       
  2197     connect(page, SIGNAL(completeChanged()), this, SLOT(_q_updateButtonStates()));
       
  2198 
       
  2199     d->pageMap.insert(theid, page);
       
  2200     page->d_func()->wizard = this;
       
  2201 
       
  2202     int n = d->pageVBoxLayout->count();
       
  2203 
       
  2204     // disable layout to prevent layout updates while adding
       
  2205     bool pageVBoxLayoutEnabled = d->pageVBoxLayout->isEnabled();
       
  2206     d->pageVBoxLayout->setEnabled(false);
       
  2207 
       
  2208     d->pageVBoxLayout->insertWidget(n - 1, page);
       
  2209 
       
  2210     // hide new page and reset layout to old status
       
  2211     page->hide();
       
  2212     d->pageVBoxLayout->setEnabled(pageVBoxLayoutEnabled);
       
  2213 }
       
  2214 
       
  2215 /*!
       
  2216     Removes the page with the given \a id. cleanupPage() will be called if necessary.
       
  2217     \since 4.5
       
  2218     \sa addPage(), setPage()
       
  2219 */
       
  2220 void QWizard::removePage(int id)
       
  2221 {
       
  2222     Q_D(QWizard);
       
  2223 
       
  2224     QWizardPage *removedPage = 0;
       
  2225 
       
  2226     if (d->start == id)
       
  2227         d->start = -1;
       
  2228 
       
  2229     if (!d->history.contains(id)) {
       
  2230         // Case 1: removing a page not in the history
       
  2231         removedPage = d->pageMap.take(id);
       
  2232         d->updateCurrentPage();
       
  2233     } else if (id != d->current) {
       
  2234         // Case 2: removing a page in the history before the current page
       
  2235         removedPage = d->pageMap.take(id);
       
  2236         d->history.removeOne(id);
       
  2237         d->_q_updateButtonStates();
       
  2238     } else if (d->history.count() == 1) {
       
  2239         // Case 3: removing the current page which is the first (and only) one in the history
       
  2240         d->reset();
       
  2241         removedPage = d->pageMap.take(id);
       
  2242         if (d->pageMap.isEmpty())
       
  2243             d->updateCurrentPage();
       
  2244         else
       
  2245             restart();
       
  2246     } else {
       
  2247         // Case 4: removing the current page which is not the first one in the history
       
  2248         back();
       
  2249         removedPage = d->pageMap.take(id);
       
  2250         d->updateCurrentPage();
       
  2251     }
       
  2252 
       
  2253     if (removedPage) {
       
  2254         if (d->initialized.contains(id)) {
       
  2255             cleanupPage(id);
       
  2256             d->initialized.remove(id);
       
  2257         }
       
  2258 
       
  2259         d->pageVBoxLayout->removeWidget(removedPage);
       
  2260 
       
  2261         for (int i = d->fields.count() - 1; i >= 0; --i) {
       
  2262             if (d->fields.at(i).page == removedPage) {
       
  2263                 removedPage->d_func()->pendingFields += d->fields.at(i);
       
  2264                 d->removeFieldAt(i);
       
  2265             }
       
  2266         }
       
  2267     }
       
  2268 }
       
  2269 
       
  2270 /*!
       
  2271     \fn QWizardPage *QWizard::page(int id) const
       
  2272 
       
  2273     Returns the page with the given \a id, or 0 if there is no such
       
  2274     page.
       
  2275 
       
  2276     \sa addPage(), setPage()
       
  2277 */
       
  2278 QWizardPage *QWizard::page(int theid) const
       
  2279 {
       
  2280     Q_D(const QWizard);
       
  2281     return d->pageMap.value(theid);
       
  2282 }
       
  2283 
       
  2284 /*!
       
  2285     \fn bool QWizard::hasVisitedPage(int id) const
       
  2286 
       
  2287     Returns true if the page history contains page \a id; otherwise,
       
  2288     returns false.
       
  2289 
       
  2290     Pressing \gui Back marks the current page as "unvisited" again.
       
  2291 
       
  2292     \sa visitedPages()
       
  2293 */
       
  2294 bool QWizard::hasVisitedPage(int theid) const
       
  2295 {
       
  2296     Q_D(const QWizard);
       
  2297     return d->history.contains(theid);
       
  2298 }
       
  2299 
       
  2300 /*!
       
  2301     Returns the list of IDs of visited pages, in the order in which the pages
       
  2302     were visited.
       
  2303 
       
  2304     Pressing \gui Back marks the current page as "unvisited" again.
       
  2305 
       
  2306     \sa hasVisitedPage()
       
  2307 */
       
  2308 QList<int> QWizard::visitedPages() const
       
  2309 {
       
  2310     Q_D(const QWizard);
       
  2311     return d->history;
       
  2312 }
       
  2313 
       
  2314 /*!
       
  2315     Returns the list of page IDs.
       
  2316    \since 4.5
       
  2317 */
       
  2318 QList<int> QWizard::pageIds() const
       
  2319 {
       
  2320   Q_D(const QWizard);
       
  2321   return d->pageMap.keys();
       
  2322 }
       
  2323 
       
  2324 /*!
       
  2325     \property QWizard::startId
       
  2326     \brief the ID of the first page
       
  2327 
       
  2328     If this property isn't explicitly set, this property defaults to
       
  2329     the lowest page ID in this wizard, or -1 if no page has been
       
  2330     inserted yet.
       
  2331 
       
  2332     \sa restart(), nextId()
       
  2333 */
       
  2334 void QWizard::setStartId(int theid)
       
  2335 {
       
  2336     Q_D(QWizard);
       
  2337     if (!d->pageMap.contains(theid)) {
       
  2338         qWarning("QWizard::setStartId: Invalid page ID %d", theid);
       
  2339         return;
       
  2340     }
       
  2341     d->start = theid;
       
  2342 }
       
  2343 
       
  2344 int QWizard::startId() const
       
  2345 {
       
  2346     Q_D(const QWizard);
       
  2347     if (d->start != -1)
       
  2348         return d->start;
       
  2349     if (!d->pageMap.isEmpty())
       
  2350         return d->pageMap.constBegin().key();
       
  2351     return -1;
       
  2352 }
       
  2353 
       
  2354 /*!
       
  2355     Returns a pointer to the current page, or 0 if there is no current
       
  2356     page (e.g., before the wizard is shown).
       
  2357 
       
  2358     This is equivalent to calling page(currentId()).
       
  2359 
       
  2360     \sa page(), currentId(), restart()
       
  2361 */
       
  2362 QWizardPage *QWizard::currentPage() const
       
  2363 {
       
  2364     Q_D(const QWizard);
       
  2365     return page(d->current);
       
  2366 }
       
  2367 
       
  2368 /*!
       
  2369     \property QWizard::currentId
       
  2370     \brief the ID of the current page
       
  2371 
       
  2372     This property cannot be set directly. To change the current page,
       
  2373     call next(), back(), or restart().
       
  2374 
       
  2375     By default, this property has a value of -1, indicating that no page is
       
  2376     currently shown.
       
  2377 
       
  2378     \sa currentIdChanged(), currentPage()
       
  2379 */
       
  2380 int QWizard::currentId() const
       
  2381 {
       
  2382     Q_D(const QWizard);
       
  2383     return d->current;
       
  2384 }
       
  2385 
       
  2386 /*!
       
  2387     Sets the value of the field called \a name to \a value.
       
  2388 
       
  2389     This function can be used to set fields on any page of the wizard.
       
  2390 
       
  2391     \sa QWizardPage::registerField(), QWizardPage::setField(), field()
       
  2392 */
       
  2393 void QWizard::setField(const QString &name, const QVariant &value)
       
  2394 {
       
  2395     Q_D(QWizard);
       
  2396 
       
  2397     int index = d->fieldIndexMap.value(name, -1);
       
  2398     if (index != -1) {
       
  2399         const QWizardField &field = d->fields.at(index);
       
  2400         if (!field.object->setProperty(field.property, value))
       
  2401             qWarning("QWizard::setField: Couldn't write to property '%s'",
       
  2402                      field.property.constData());
       
  2403         return;
       
  2404     }
       
  2405 
       
  2406     qWarning("QWizard::setField: No such field '%s'", qPrintable(name));
       
  2407 }
       
  2408 
       
  2409 /*!
       
  2410     Returns the value of the field called \a name.
       
  2411 
       
  2412     This function can be used to access fields on any page of the wizard.
       
  2413 
       
  2414     \sa QWizardPage::registerField(), QWizardPage::field(), setField()
       
  2415 */
       
  2416 QVariant QWizard::field(const QString &name) const
       
  2417 {
       
  2418     Q_D(const QWizard);
       
  2419 
       
  2420     int index = d->fieldIndexMap.value(name, -1);
       
  2421     if (index != -1) {
       
  2422         const QWizardField &field = d->fields.at(index);
       
  2423         return field.object->property(field.property);
       
  2424     }
       
  2425 
       
  2426     qWarning("QWizard::field: No such field '%s'", qPrintable(name));
       
  2427     return QVariant();
       
  2428 }
       
  2429 
       
  2430 /*!
       
  2431     \property QWizard::wizardStyle
       
  2432     \brief the look and feel of the wizard
       
  2433 
       
  2434     By default, QWizard uses the AeroStyle on a Windows Vista system with alpha compositing
       
  2435     enabled, regardless of the current widget style. If this is not the case, the default
       
  2436     wizard style depends on the current widget style as follows: MacStyle is the default if
       
  2437     the current widget style is QMacStyle, ModernStyle is the default if the current widget
       
  2438     style is QWindowsStyle, and ClassicStyle is the default in all other cases.
       
  2439 
       
  2440     \sa {Wizard Look and Feel}, options
       
  2441 */
       
  2442 void QWizard::setWizardStyle(WizardStyle style)
       
  2443 {
       
  2444     Q_D(QWizard);
       
  2445 
       
  2446     const bool styleChange = style != d->wizStyle;
       
  2447 
       
  2448 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2449     const bool aeroStyleChange =
       
  2450         d->vistaInitPending || d->vistaStateChanged || (styleChange && (style == AeroStyle || d->wizStyle == AeroStyle));
       
  2451     d->vistaStateChanged = false;
       
  2452     d->vistaInitPending = false;
       
  2453 #endif
       
  2454 
       
  2455     if (styleChange
       
  2456 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2457         || aeroStyleChange
       
  2458 #endif
       
  2459         ) {
       
  2460         d->disableUpdates();
       
  2461         d->wizStyle = style;
       
  2462         d->updateButtonTexts();
       
  2463         d->updateLayout();
       
  2464         updateGeometry();
       
  2465         d->enableUpdates();
       
  2466 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2467         if (aeroStyleChange)
       
  2468             d->handleAeroStyleChange();
       
  2469 #endif
       
  2470     }
       
  2471 }
       
  2472 
       
  2473 QWizard::WizardStyle QWizard::wizardStyle() const
       
  2474 {
       
  2475     Q_D(const QWizard);
       
  2476     return d->wizStyle;
       
  2477 }
       
  2478 
       
  2479 /*!
       
  2480     Sets the given \a option to be enabled if \a on is true;
       
  2481     otherwise, clears the given \a option.
       
  2482 
       
  2483     \sa options, testOption(), setWizardStyle()
       
  2484 */
       
  2485 void QWizard::setOption(WizardOption option, bool on)
       
  2486 {
       
  2487     Q_D(QWizard);
       
  2488     if (!(d->opts & option) != !on)
       
  2489         setOptions(d->opts ^ option);
       
  2490 }
       
  2491 
       
  2492 /*!
       
  2493     Returns true if the given \a option is enabled; otherwise, returns
       
  2494     false.
       
  2495 
       
  2496     \sa options, setOption(), setWizardStyle()
       
  2497 */
       
  2498 bool QWizard::testOption(WizardOption option) const
       
  2499 {
       
  2500     Q_D(const QWizard);
       
  2501     return (d->opts & option) != 0;
       
  2502 }
       
  2503 
       
  2504 /*!
       
  2505     \property QWizard::options
       
  2506     \brief the various options that affect the look and feel of the wizard
       
  2507 
       
  2508     By default, the following options are set (depending on the platform):
       
  2509 
       
  2510     \list
       
  2511     \o Windows: HelpButtonOnRight.
       
  2512     \o Mac OS X: NoDefaultButton and NoCancelButton.
       
  2513     \o X11 and QWS (Qt for Embedded Linux): none.
       
  2514     \endlist
       
  2515 
       
  2516     \sa wizardStyle
       
  2517 */
       
  2518 void QWizard::setOptions(WizardOptions options)
       
  2519 {
       
  2520     Q_D(QWizard);
       
  2521 
       
  2522     WizardOptions changed = (options ^ d->opts);
       
  2523     if (!changed)
       
  2524         return;
       
  2525 
       
  2526     d->disableUpdates();
       
  2527 
       
  2528     d->opts = options;
       
  2529     if ((changed & IndependentPages) && !(d->opts & IndependentPages))
       
  2530         d->cleanupPagesNotInHistory();
       
  2531 
       
  2532     if (changed & (NoDefaultButton | HaveHelpButton | HelpButtonOnRight | NoCancelButton
       
  2533                    | CancelButtonOnLeft | HaveCustomButton1 | HaveCustomButton2
       
  2534                    | HaveCustomButton3)) {
       
  2535         d->updateButtonLayout();
       
  2536     } else if (changed & (NoBackButtonOnStartPage | NoBackButtonOnLastPage
       
  2537                           | HaveNextButtonOnLastPage | HaveFinishButtonOnEarlyPages
       
  2538                           | DisabledBackButtonOnLastPage)) {
       
  2539         d->_q_updateButtonStates();
       
  2540     }
       
  2541 
       
  2542     d->enableUpdates();
       
  2543     d->updateLayout();
       
  2544 }
       
  2545 
       
  2546 QWizard::WizardOptions QWizard::options() const
       
  2547 {
       
  2548     Q_D(const QWizard);
       
  2549     return d->opts;
       
  2550 }
       
  2551 
       
  2552 /*!
       
  2553     Sets the text on button \a which to be \a text.
       
  2554 
       
  2555     By default, the text on buttons depends on the wizardStyle. For
       
  2556     example, on Mac OS X, the \gui Next button is called \gui
       
  2557     Continue.
       
  2558 
       
  2559     To add extra buttons to the wizard (e.g., a \gui Print button),
       
  2560     one way is to call setButtonText() with CustomButton1,
       
  2561     CustomButton2, or CustomButton3 to set their text, and make the
       
  2562     buttons visible using the HaveCustomButton1, HaveCustomButton2,
       
  2563     and/or HaveCustomButton3 options.
       
  2564 
       
  2565     Button texts may also be set on a per-page basis using QWizardPage::setButtonText().
       
  2566 
       
  2567     \sa setButton(), button(), setButtonLayout(), setOptions(), QWizardPage::setButtonText()
       
  2568 */
       
  2569 void QWizard::setButtonText(WizardButton which, const QString &text)
       
  2570 {
       
  2571     Q_D(QWizard);
       
  2572 
       
  2573     if (!d->ensureButton(which))
       
  2574         return;
       
  2575 
       
  2576     d->buttonCustomTexts.insert(which, text);
       
  2577 
       
  2578     if (!currentPage() || !currentPage()->d_func()->buttonCustomTexts.contains(which))
       
  2579         d->btns[which]->setText(text);
       
  2580 }
       
  2581 
       
  2582 /*!
       
  2583     Returns the text on button \a which.
       
  2584 
       
  2585     If a text has ben set using setButtonText(), this text is returned.
       
  2586 
       
  2587     By default, the text on buttons depends on the wizardStyle. For
       
  2588     example, on Mac OS X, the \gui Next button is called \gui
       
  2589     Continue.
       
  2590 
       
  2591     \sa button(), setButton(), setButtonText(), QWizardPage::buttonText(),
       
  2592     QWizardPage::setButtonText()
       
  2593 */
       
  2594 QString QWizard::buttonText(WizardButton which) const
       
  2595 {
       
  2596     Q_D(const QWizard);
       
  2597 
       
  2598     if (!d->ensureButton(which))
       
  2599         return QString();
       
  2600 
       
  2601     if (d->buttonCustomTexts.contains(which))
       
  2602         return d->buttonCustomTexts.value(which);
       
  2603 
       
  2604     const QString defText = buttonDefaultText(d->wizStyle, which, d);
       
  2605     if(!defText.isNull())
       
  2606         return defText;
       
  2607 
       
  2608     return d->btns[which]->text();
       
  2609 }
       
  2610 
       
  2611 /*!
       
  2612     Sets the order in which buttons are displayed to \a layout, where
       
  2613     \a layout is a list of \l{WizardButton}s.
       
  2614 
       
  2615     The default layout depends on the options (e.g., whether
       
  2616     HelpButtonOnRight) that are set. You can call this function if
       
  2617     you need more control over the buttons' layout than what \l
       
  2618     options already provides.
       
  2619 
       
  2620     You can specify horizontal stretches in the layout using \l
       
  2621     Stretch.
       
  2622 
       
  2623     Example:
       
  2624 
       
  2625     \snippet doc/src/snippets/code/src_gui_dialogs_qwizard.cpp 1
       
  2626 
       
  2627     \sa setButton(), setButtonText(), setOptions()
       
  2628 */
       
  2629 void QWizard::setButtonLayout(const QList<WizardButton> &layout)
       
  2630 {
       
  2631     Q_D(QWizard);
       
  2632 
       
  2633     for (int i = 0; i < layout.count(); ++i) {
       
  2634         WizardButton button1 = layout.at(i);
       
  2635 
       
  2636         if (button1 == NoButton || button1 == Stretch)
       
  2637             continue;
       
  2638         if (!d->ensureButton(button1))
       
  2639             return;
       
  2640 
       
  2641         // O(n^2), but n is very small
       
  2642         for (int j = 0; j < i; ++j) {
       
  2643             WizardButton button2 = layout.at(j);
       
  2644             if (button2 == button1) {
       
  2645                 qWarning("QWizard::setButtonLayout: Duplicate button in layout");
       
  2646                 return;
       
  2647             }
       
  2648         }
       
  2649     }
       
  2650 
       
  2651     d->buttonsHaveCustomLayout = true;
       
  2652     d->buttonsCustomLayout = layout;
       
  2653     d->updateButtonLayout();
       
  2654 }
       
  2655 
       
  2656 /*!
       
  2657     Sets the button corresponding to role \a which to \a button.
       
  2658 
       
  2659     To add extra buttons to the wizard (e.g., a \gui Print button),
       
  2660     one way is to call setButton() with CustomButton1 to
       
  2661     CustomButton3, and make the buttons visible using the
       
  2662     HaveCustomButton1 to HaveCustomButton3 options.
       
  2663 
       
  2664     \sa setButtonText(), setButtonLayout(), options
       
  2665 */
       
  2666 void QWizard::setButton(WizardButton which, QAbstractButton *button)
       
  2667 {
       
  2668     Q_D(QWizard);
       
  2669 
       
  2670     if (uint(which) >= NButtons || d->btns[which] == button)
       
  2671         return;
       
  2672 
       
  2673     if (QAbstractButton *oldButton = d->btns[which]) {
       
  2674         d->buttonLayout->removeWidget(oldButton);
       
  2675         delete oldButton;
       
  2676     }
       
  2677 
       
  2678     d->btns[which] = button;
       
  2679     if (button) {
       
  2680         button->setParent(d->antiFlickerWidget);
       
  2681         d->buttonCustomTexts.insert(which, button->text());
       
  2682         d->connectButton(which);
       
  2683     } else {
       
  2684         d->buttonCustomTexts.remove(which); // ### what about page-specific texts set for 'which'
       
  2685         d->ensureButton(which);             // (QWizardPage::setButtonText())? Clear them as well?
       
  2686     }
       
  2687 
       
  2688     d->updateButtonLayout();
       
  2689 }
       
  2690 
       
  2691 /*!
       
  2692     Returns the button corresponding to role \a which.
       
  2693 
       
  2694     \sa setButton(), setButtonText()
       
  2695 */
       
  2696 QAbstractButton *QWizard::button(WizardButton which) const
       
  2697 {
       
  2698     Q_D(const QWizard);
       
  2699 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2700     if (d->wizStyle == AeroStyle && which == BackButton)
       
  2701         return d->vistaHelper->backButton();
       
  2702 #endif
       
  2703     if (!d->ensureButton(which))
       
  2704         return 0;
       
  2705     return d->btns[which];
       
  2706 }
       
  2707 
       
  2708 /*!
       
  2709     \property QWizard::titleFormat
       
  2710     \brief the text format used by page titles
       
  2711 
       
  2712     The default format is Qt::AutoText.
       
  2713 
       
  2714     \sa QWizardPage::title, subTitleFormat
       
  2715 */
       
  2716 void QWizard::setTitleFormat(Qt::TextFormat format)
       
  2717 {
       
  2718     Q_D(QWizard);
       
  2719     d->titleFmt = format;
       
  2720     d->updateLayout();
       
  2721 }
       
  2722 
       
  2723 Qt::TextFormat QWizard::titleFormat() const
       
  2724 {
       
  2725     Q_D(const QWizard);
       
  2726     return d->titleFmt;
       
  2727 }
       
  2728 
       
  2729 /*!
       
  2730     \property QWizard::subTitleFormat
       
  2731     \brief the text format used by page subtitles
       
  2732 
       
  2733     The default format is Qt::AutoText.
       
  2734 
       
  2735     \sa QWizardPage::title, titleFormat
       
  2736 */
       
  2737 void QWizard::setSubTitleFormat(Qt::TextFormat format)
       
  2738 {
       
  2739     Q_D(QWizard);
       
  2740     d->subTitleFmt = format;
       
  2741     d->updateLayout();
       
  2742 }
       
  2743 
       
  2744 Qt::TextFormat QWizard::subTitleFormat() const
       
  2745 {
       
  2746     Q_D(const QWizard);
       
  2747     return d->subTitleFmt;
       
  2748 }
       
  2749 
       
  2750 /*!
       
  2751     Sets the pixmap for role \a which to \a pixmap.
       
  2752 
       
  2753     The pixmaps are used by QWizard when displaying a page. Which
       
  2754     pixmaps are actually used depend on the \l{Wizard Look and
       
  2755     Feel}{wizard style}.
       
  2756 
       
  2757     Pixmaps can also be set for a specific page using
       
  2758     QWizardPage::setPixmap().
       
  2759 
       
  2760     \sa QWizardPage::setPixmap(), {Elements of a Wizard Page}
       
  2761 */
       
  2762 void QWizard::setPixmap(WizardPixmap which, const QPixmap &pixmap)
       
  2763 {
       
  2764     Q_D(QWizard);
       
  2765     Q_ASSERT(uint(which) < NPixmaps);
       
  2766     d->defaultPixmaps[which] = pixmap;
       
  2767     d->updatePixmap(which);
       
  2768 }
       
  2769 
       
  2770 /*!
       
  2771     Returns the pixmap set for role \a which.
       
  2772 
       
  2773     By default, the only pixmap that is set is the BackgroundPixmap on
       
  2774     Mac OS X.
       
  2775 
       
  2776     \sa QWizardPage::pixmap(), {Elements of a Wizard Page}
       
  2777 */
       
  2778 QPixmap QWizard::pixmap(WizardPixmap which) const
       
  2779 {
       
  2780     Q_D(const QWizard);
       
  2781     Q_ASSERT(uint(which) < NPixmaps);
       
  2782 #ifdef Q_WS_MAC
       
  2783     if (which == BackgroundPixmap && d->defaultPixmaps[BackgroundPixmap].isNull())
       
  2784         d->defaultPixmaps[BackgroundPixmap] = d->findDefaultBackgroundPixmap();
       
  2785 #endif
       
  2786     return d->defaultPixmaps[which];
       
  2787 }
       
  2788 
       
  2789 /*!
       
  2790     Sets the default property for \a className to be \a property,
       
  2791     and the associated change signal to be \a changedSignal.
       
  2792 
       
  2793     The default property is used when an instance of \a className (or
       
  2794     of one of its subclasses) is passed to
       
  2795     QWizardPage::registerField() and no property is specified.
       
  2796 
       
  2797     QWizard knows the most common Qt widgets. For these (or their
       
  2798     subclasses), you don't need to specify a \a property or a \a
       
  2799     changedSignal. The table below lists these widgets:
       
  2800 
       
  2801     \table
       
  2802     \header \o Widget          \o Property                            \o Change Notification Signal
       
  2803     \row    \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()}
       
  2804     \row    \o QAbstractSlider \o int \l{QAbstractSlider::}{value}    \o \l{QAbstractSlider::}{valueChanged()}
       
  2805     \row    \o QComboBox       \o int \l{QComboBox::}{currentIndex}   \o \l{QComboBox::}{currentIndexChanged()}
       
  2806     \row    \o QDateTimeEdit   \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()}
       
  2807     \row    \o QLineEdit       \o QString \l{QLineEdit::}{text}       \o \l{QLineEdit::}{textChanged()}
       
  2808     \row    \o QListWidget     \o int \l{QListWidget::}{currentRow}   \o \l{QListWidget::}{currentRowChanged()}
       
  2809     \row    \o QSpinBox        \o int \l{QSpinBox::}{value}           \o \l{QSpinBox::}{valueChanged()}
       
  2810     \endtable
       
  2811 
       
  2812     \sa QWizardPage::registerField()
       
  2813 */
       
  2814 void QWizard::setDefaultProperty(const char *className, const char *property,
       
  2815                                  const char *changedSignal)
       
  2816 {
       
  2817     Q_D(QWizard);
       
  2818     for (int i = d->defaultPropertyTable.count() - 1; i >= 0; --i) {
       
  2819         if (qstrcmp(d->defaultPropertyTable.at(i).className, className) == 0) {
       
  2820             d->defaultPropertyTable.remove(i);
       
  2821             break;
       
  2822         }
       
  2823     }
       
  2824     d->defaultPropertyTable.append(QWizardDefaultProperty(className, property, changedSignal));
       
  2825 }
       
  2826 
       
  2827 /*!
       
  2828     \reimp
       
  2829 */
       
  2830 void QWizard::setVisible(bool visible)
       
  2831 {
       
  2832     Q_D(QWizard);
       
  2833     if (visible) {
       
  2834         if (d->current == -1)
       
  2835             restart();
       
  2836     }
       
  2837     QDialog::setVisible(visible);
       
  2838 }
       
  2839 
       
  2840 /*!
       
  2841     \reimp
       
  2842 */
       
  2843 QSize QWizard::sizeHint() const
       
  2844 {
       
  2845     Q_D(const QWizard);
       
  2846     QSize result = d->mainLayout->totalSizeHint();
       
  2847 #ifdef Q_WS_S60
       
  2848     QSize extra(QApplication::desktop()->availableGeometry(QCursor::pos()).size());
       
  2849 #else
       
  2850     QSize extra(500, 360);
       
  2851 #endif
       
  2852     if (d->wizStyle == MacStyle && d->current != -1) {
       
  2853         QSize pixmap(currentPage()->pixmap(BackgroundPixmap).size());
       
  2854         extra.setWidth(616);
       
  2855         if (!pixmap.isNull()) {
       
  2856             extra.setHeight(pixmap.height());
       
  2857 
       
  2858             /*
       
  2859                 The width isn't always reliable as a size hint, as
       
  2860                 some wizard backgrounds just cover the leftmost area.
       
  2861                 Use a rule of thumb to determine if the width is
       
  2862                 reliable or not.
       
  2863             */
       
  2864             if (pixmap.width() >= pixmap.height())
       
  2865                 extra.setWidth(pixmap.width());
       
  2866         }
       
  2867     }
       
  2868     return result.expandedTo(extra);
       
  2869 }
       
  2870 
       
  2871 /*!
       
  2872     \fn void QWizard::currentIdChanged(int id)
       
  2873 
       
  2874     This signal is emitted when the current page changes, with the new
       
  2875     current \a id.
       
  2876 
       
  2877     \sa currentId(), currentPage()
       
  2878 */
       
  2879 
       
  2880 /*!
       
  2881     \fn void QWizard::helpRequested()
       
  2882 
       
  2883     This signal is emitted when the user clicks the \gui Help button.
       
  2884 
       
  2885     By default, no \gui Help button is shown. Call
       
  2886     setOption(HaveHelpButton, true) to have one.
       
  2887 
       
  2888     Example:
       
  2889 
       
  2890     \snippet examples/dialogs/licensewizard/licensewizard.cpp 0
       
  2891     \dots
       
  2892     \snippet examples/dialogs/licensewizard/licensewizard.cpp 5
       
  2893     \snippet examples/dialogs/licensewizard/licensewizard.cpp 7
       
  2894     \dots
       
  2895     \snippet examples/dialogs/licensewizard/licensewizard.cpp 8
       
  2896     \codeline
       
  2897     \snippet examples/dialogs/licensewizard/licensewizard.cpp 10
       
  2898     \dots
       
  2899     \snippet examples/dialogs/licensewizard/licensewizard.cpp 12
       
  2900     \codeline
       
  2901     \snippet examples/dialogs/licensewizard/licensewizard.cpp 14
       
  2902     \codeline
       
  2903     \snippet examples/dialogs/licensewizard/licensewizard.cpp 15
       
  2904 
       
  2905     \sa customButtonClicked()
       
  2906 */
       
  2907 
       
  2908 /*!
       
  2909     \fn void QWizard::customButtonClicked(int which)
       
  2910 
       
  2911     This signal is emitted when the user clicks a custom button. \a
       
  2912     which can be CustomButton1, CustomButton2, or CustomButton3.
       
  2913 
       
  2914     By default, no custom button is shown. Call setOption() with
       
  2915     HaveCustomButton1, HaveCustomButton2, or HaveCustomButton3 to have
       
  2916     one, and use setButtonText() or setButton() to configure it.
       
  2917 
       
  2918     \sa helpRequested()
       
  2919 */
       
  2920 
       
  2921 /*!
       
  2922     Goes back to the previous page.
       
  2923 
       
  2924     This is equivalent to pressing the \gui Back button.
       
  2925 
       
  2926     \sa next(), accept(), reject(), restart()
       
  2927 */
       
  2928 void QWizard::back()
       
  2929 {
       
  2930     Q_D(QWizard);
       
  2931     int n = d->history.count() - 2;
       
  2932     if (n < 0)
       
  2933         return;
       
  2934     d->switchToPage(d->history.at(n), QWizardPrivate::Backward);
       
  2935 }
       
  2936 
       
  2937 /*!
       
  2938     Advances to the next page.
       
  2939 
       
  2940     This is equivalent to pressing the \gui Next or \gui Commit button.
       
  2941 
       
  2942     \sa nextId(), back(), accept(), reject(), restart()
       
  2943 */
       
  2944 void QWizard::next()
       
  2945 {
       
  2946     Q_D(QWizard);
       
  2947 
       
  2948     if (d->current == -1)
       
  2949         return;
       
  2950 
       
  2951     if (validateCurrentPage()) {
       
  2952         int next = nextId();
       
  2953         if (next != -1) {
       
  2954             if (d->history.contains(next)) {
       
  2955                 qWarning("QWizard::next: Page %d already met", next);
       
  2956                 return;
       
  2957             }
       
  2958             if (!d->pageMap.contains(next)) {
       
  2959                 qWarning("QWizard::next: No such page %d", next);
       
  2960                 return;
       
  2961             }
       
  2962             d->switchToPage(next, QWizardPrivate::Forward);
       
  2963         }
       
  2964     }
       
  2965 }
       
  2966 
       
  2967 /*!
       
  2968     Restarts the wizard at the start page. This function is called automatically when the
       
  2969     wizard is shown.
       
  2970 
       
  2971     \sa startId()
       
  2972 */
       
  2973 void QWizard::restart()
       
  2974 {
       
  2975     Q_D(QWizard);
       
  2976     d->disableUpdates();
       
  2977     d->reset();
       
  2978     d->switchToPage(startId(), QWizardPrivate::Forward);
       
  2979     d->enableUpdates();
       
  2980 }
       
  2981 
       
  2982 /*!
       
  2983     \reimp
       
  2984 */
       
  2985 bool QWizard::event(QEvent *event)
       
  2986 {
       
  2987     Q_D(QWizard);
       
  2988     if (event->type() == QEvent::StyleChange) { // Propagate style
       
  2989         d->setStyle(style());
       
  2990         d->updateLayout();
       
  2991     }
       
  2992 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  2993     else if (event->type() == QEvent::Show && d->vistaInitPending) {
       
  2994         d->vistaInitPending = false;
       
  2995         d->wizStyle = AeroStyle;
       
  2996         d->handleAeroStyleChange();
       
  2997     }
       
  2998     else if (d->isVistaThemeEnabled()) {
       
  2999         d->vistaHelper->mouseEvent(event);
       
  3000     }
       
  3001 #endif
       
  3002     return QDialog::event(event);
       
  3003 }
       
  3004 
       
  3005 /*!
       
  3006     \reimp
       
  3007 */
       
  3008 void QWizard::resizeEvent(QResizeEvent *event)
       
  3009 {
       
  3010     Q_D(QWizard);
       
  3011     int heightOffset = 0;
       
  3012 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3013     if (d->isVistaThemeEnabled()) {
       
  3014         heightOffset = d->vistaHelper->topOffset();
       
  3015         if (d->isVistaThemeEnabled(QVistaHelper::VistaAero))
       
  3016             heightOffset += d->vistaHelper->titleBarSize();
       
  3017     }
       
  3018 #endif
       
  3019     d->antiFlickerWidget->resize(event->size().width(), event->size().height() - heightOffset);
       
  3020 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3021     if (d->isVistaThemeEnabled())
       
  3022         d->vistaHelper->resizeEvent(event);
       
  3023 #endif
       
  3024     QDialog::resizeEvent(event);
       
  3025 }
       
  3026 
       
  3027 /*!
       
  3028     \reimp
       
  3029 */
       
  3030 void QWizard::paintEvent(QPaintEvent * event)
       
  3031 {
       
  3032     Q_D(QWizard);
       
  3033     if (d->wizStyle == MacStyle && currentPage()) {
       
  3034         QPixmap backgroundPixmap = currentPage()->pixmap(BackgroundPixmap);
       
  3035         if (backgroundPixmap.isNull())
       
  3036             return;
       
  3037 
       
  3038         QPainter painter(this);
       
  3039         painter.drawPixmap(0, (height() - backgroundPixmap.height()) / 2, backgroundPixmap);
       
  3040     }
       
  3041 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3042     else if (d->isVistaThemeEnabled()) {
       
  3043         if (d->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
       
  3044             QPainter painter(this);
       
  3045             QColor color = d->vistaHelper->basicWindowFrameColor();
       
  3046             painter.fillRect(0, 0, width(), QVistaHelper::topOffset(), color);
       
  3047         }
       
  3048         d->vistaHelper->paintEvent(event);
       
  3049     }
       
  3050 #else
       
  3051     Q_UNUSED(event);
       
  3052 #endif
       
  3053 }
       
  3054 
       
  3055 #if defined(Q_WS_WIN)
       
  3056 /*!
       
  3057     \reimp
       
  3058 */
       
  3059 bool QWizard::winEvent(MSG *message, long *result)
       
  3060 {
       
  3061 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
       
  3062     Q_D(QWizard);
       
  3063     if (d->isVistaThemeEnabled()) {
       
  3064         const bool winEventResult = d->vistaHelper->handleWinEvent(message, result);
       
  3065         if (QVistaHelper::vistaState() != d->vistaState) {
       
  3066             d->vistaState = QVistaHelper::vistaState();
       
  3067             d->vistaStateChanged = true;
       
  3068             setWizardStyle(AeroStyle);
       
  3069         }
       
  3070         return winEventResult;
       
  3071     } else {
       
  3072         return QDialog::winEvent(message, result);
       
  3073     }
       
  3074 #else
       
  3075     return QDialog::winEvent(message, result);
       
  3076 #endif
       
  3077 }
       
  3078 #endif
       
  3079 
       
  3080 /*!
       
  3081     \reimp
       
  3082 */
       
  3083 void QWizard::done(int result)
       
  3084 {
       
  3085     Q_D(QWizard);
       
  3086     // canceling leaves the wizard in a known state
       
  3087     if (result == Rejected) {
       
  3088         d->reset();
       
  3089     } else {
       
  3090         if (!validateCurrentPage())
       
  3091             return;
       
  3092     }
       
  3093     QDialog::done(result);
       
  3094 }
       
  3095 
       
  3096 /*!
       
  3097     \fn void QWizard::initializePage(int id)
       
  3098 
       
  3099     This virtual function is called by QWizard to prepare page \a id
       
  3100     just before it is shown either as a result of QWizard::restart()
       
  3101     being called, or as a result of the user clicking \gui Next. (However, if the \l
       
  3102     QWizard::IndependentPages option is set, this function is only
       
  3103     called the first time the page is shown.)
       
  3104 
       
  3105     By reimplementing this function, you can ensure that the page's
       
  3106     fields are properly initialized based on fields from previous
       
  3107     pages.
       
  3108 
       
  3109     The default implementation calls QWizardPage::initializePage() on
       
  3110     page(\a id).
       
  3111 
       
  3112     \sa QWizardPage::initializePage(), cleanupPage()
       
  3113 */
       
  3114 void QWizard::initializePage(int theid)
       
  3115 {
       
  3116     QWizardPage *page = this->page(theid);
       
  3117     if (page)
       
  3118         page->initializePage();
       
  3119 }
       
  3120 
       
  3121 /*!
       
  3122     \fn void QWizard::cleanupPage(int id)
       
  3123 
       
  3124     This virtual function is called by QWizard to clean up page \a id just before the
       
  3125     user leaves it by clicking \gui Back (unless the \l QWizard::IndependentPages option is set).
       
  3126 
       
  3127     The default implementation calls QWizardPage::cleanupPage() on
       
  3128     page(\a id).
       
  3129 
       
  3130     \sa QWizardPage::cleanupPage(), initializePage()
       
  3131 */
       
  3132 void QWizard::cleanupPage(int theid)
       
  3133 {
       
  3134     QWizardPage *page = this->page(theid);
       
  3135     if (page)
       
  3136         page->cleanupPage();
       
  3137 }
       
  3138 
       
  3139 /*!
       
  3140     This virtual function is called by QWizard when the user clicks
       
  3141     \gui Next or \gui Finish to perform some last-minute validation.
       
  3142     If it returns true, the next page is shown (or the wizard
       
  3143     finishes); otherwise, the current page stays up.
       
  3144 
       
  3145     The default implementation calls QWizardPage::validatePage() on
       
  3146     the currentPage().
       
  3147 
       
  3148     When possible, it is usually better style to disable the \gui
       
  3149     Next or \gui Finish button (by specifying \l{mandatory fields} or
       
  3150     by reimplementing QWizardPage::isComplete()) than to reimplement
       
  3151     validateCurrentPage().
       
  3152 
       
  3153     \sa QWizardPage::validatePage(), currentPage()
       
  3154 */
       
  3155 bool QWizard::validateCurrentPage()
       
  3156 {
       
  3157     QWizardPage *page = currentPage();
       
  3158     if (!page)
       
  3159         return true;
       
  3160 
       
  3161     return page->validatePage();
       
  3162 }
       
  3163 
       
  3164 /*!
       
  3165     This virtual function is called by QWizard to find out which page
       
  3166     to show when the user clicks the \gui Next button.
       
  3167 
       
  3168     The return value is the ID of the next page, or -1 if no page follows.
       
  3169 
       
  3170     The default implementation calls QWizardPage::nextId() on the
       
  3171     currentPage().
       
  3172 
       
  3173     By reimplementing this function, you can specify a dynamic page
       
  3174     order.
       
  3175 
       
  3176     \sa QWizardPage::nextId(), currentPage()
       
  3177 */
       
  3178 int QWizard::nextId() const
       
  3179 {
       
  3180     const QWizardPage *page = currentPage();
       
  3181     if (!page)
       
  3182         return -1;
       
  3183 
       
  3184     return page->nextId();
       
  3185 }
       
  3186 
       
  3187 /*!
       
  3188     \class QWizardPage
       
  3189     \since 4.3
       
  3190     \brief The QWizardPage class is the base class for wizard pages.
       
  3191 
       
  3192     QWizard represents a wizard. Each page is a QWizardPage. When
       
  3193     you create your own wizards, you can use QWizardPage directly,
       
  3194     or you can subclass it for more control.
       
  3195 
       
  3196     A page has the following attributes, which are rendered by
       
  3197     QWizard: a \l title, a \l subTitle, and a \l{setPixmap()}{set of
       
  3198     pixmaps}. See \l{Elements of a Wizard Page} for details. Once a
       
  3199     page is added to the wizard (using QWizard::addPage() or
       
  3200     QWizard::setPage()), wizard() returns a pointer to the
       
  3201     associated QWizard object.
       
  3202 
       
  3203     Page provides five virtual functions that can be reimplemented to
       
  3204     provide custom behavior:
       
  3205 
       
  3206     \list
       
  3207     \o initializePage() is called to initialize the page's contents
       
  3208        when the user clicks the wizard's \gui Next button. If you
       
  3209        want to derive the page's default from what the user entered
       
  3210        on previous pages, this is the function to reimplement.
       
  3211     \o cleanupPage() is called to reset the page's contents when the
       
  3212        user clicks the wizard's \gui Back button.
       
  3213     \o validatePage() validates the page when the user clicks \gui
       
  3214        Next or \gui Finish. It is often used to show an error message
       
  3215        if the user has entered incomplete or invalid information.
       
  3216     \o nextId() returns the ID of the next page. It is useful when
       
  3217        \l{creating non-linear wizards}, which allow different
       
  3218        traversal paths based on the information provided by the user.
       
  3219     \o isComplete() is called to determine whether the \gui Next
       
  3220        and/or \gui Finish button should be enabled or disabled. If
       
  3221        you reimplement isComplete(), also make sure that
       
  3222        completeChanged() is emitted whenever the complete state
       
  3223        changes.
       
  3224     \endlist
       
  3225 
       
  3226     Normally, the \gui Next button and the \gui Finish button of a
       
  3227     wizard are mutually exclusive. If isFinalPage() returns true, \gui
       
  3228     Finish is available; otherwise, \gui Next is available. By
       
  3229     default, isFinalPage() is true only when nextId() returns -1. If
       
  3230     you want to show \gui Next and \gui Final simultaneously for a
       
  3231     page (letting the user perform an "early finish"), call
       
  3232     setFinalPage(true) on that page. For wizards that support early
       
  3233     finishes, you might also want to set the
       
  3234     \l{QWizard::}{HaveNextButtonOnLastPage} and
       
  3235     \l{QWizard::}{HaveFinishButtonOnEarlyPages} options on the
       
  3236     wizard.
       
  3237 
       
  3238     In many wizards, the contents of a page may affect the default
       
  3239     values of the fields of a later page. To make it easy to
       
  3240     communicate between pages, QWizard supports a \l{Registering and
       
  3241     Using Fields}{"field" mechanism} that allows you to register a
       
  3242     field (e.g., a QLineEdit) on a page and to access its value from
       
  3243     any page. Fields are global to the entire wizard and make it easy
       
  3244     for any single page to access information stored by another page,
       
  3245     without having to put all the logic in QWizard or having the
       
  3246     pages know explicitly about each other. Fields are registered
       
  3247     using registerField() and can be accessed at any time using
       
  3248     field() and setField().
       
  3249 
       
  3250     \sa QWizard, {Class Wizard Example}, {License Wizard Example}
       
  3251 */
       
  3252 
       
  3253 /*!
       
  3254     Constructs a wizard page with the given \a parent.
       
  3255 
       
  3256     When the page is inserted into a wizard using QWizard::addPage()
       
  3257     or QWizard::setPage(), the parent is automatically set to be the
       
  3258     wizard.
       
  3259 
       
  3260     \sa wizard()
       
  3261 */
       
  3262 QWizardPage::QWizardPage(QWidget *parent)
       
  3263     : QWidget(*new QWizardPagePrivate, parent, 0)
       
  3264 {
       
  3265     connect(this, SIGNAL(completeChanged()), this, SLOT(_q_updateCachedCompleteState()));
       
  3266 }
       
  3267 
       
  3268 /*!
       
  3269     \property QWizardPage::title
       
  3270     \brief the title of the page
       
  3271 
       
  3272     The title is shown by the QWizard, above the actual page. All
       
  3273     pages should have a title.
       
  3274 
       
  3275     The title may be plain text or HTML, depending on the value of the
       
  3276     \l{QWizard::titleFormat} property.
       
  3277 
       
  3278     By default, this property contains an empty string.
       
  3279 
       
  3280     \sa subTitle, {Elements of a Wizard Page}
       
  3281 */
       
  3282 void QWizardPage::setTitle(const QString &title)
       
  3283 {
       
  3284     Q_D(QWizardPage);
       
  3285     d->title = title;
       
  3286     if (d->wizard && d->wizard->currentPage() == this)
       
  3287         d->wizard->d_func()->updateLayout();
       
  3288 }
       
  3289 
       
  3290 QString QWizardPage::title() const
       
  3291 {
       
  3292     Q_D(const QWizardPage);
       
  3293     return d->title;
       
  3294 }
       
  3295 
       
  3296 /*!
       
  3297     \property QWizardPage::subTitle
       
  3298     \brief the subtitle of the page
       
  3299 
       
  3300     The subtitle is shown by the QWizard, between the title and the
       
  3301     actual page. Subtitles are optional. In
       
  3302     \l{QWizard::ClassicStyle}{ClassicStyle} and
       
  3303     \l{QWizard::ModernStyle}{ModernStyle}, using subtitles is
       
  3304     necessary to make the header appear. In
       
  3305     \l{QWizard::MacStyle}{MacStyle}, the subtitle is shown as a text
       
  3306     label just above the actual page.
       
  3307 
       
  3308     The subtitle may be plain text or HTML, depending on the value of
       
  3309     the \l{QWizard::subTitleFormat} property.
       
  3310 
       
  3311     By default, this property contains an empty string.
       
  3312 
       
  3313     \sa title, QWizard::IgnoreSubTitles, {Elements of a Wizard Page}
       
  3314 */
       
  3315 void QWizardPage::setSubTitle(const QString &subTitle)
       
  3316 {
       
  3317     Q_D(QWizardPage);
       
  3318     d->subTitle = subTitle;
       
  3319     if (d->wizard && d->wizard->currentPage() == this)
       
  3320         d->wizard->d_func()->updateLayout();
       
  3321 }
       
  3322 
       
  3323 QString QWizardPage::subTitle() const
       
  3324 {
       
  3325     Q_D(const QWizardPage);
       
  3326     return d->subTitle;
       
  3327 }
       
  3328 
       
  3329 /*!
       
  3330     Sets the pixmap for role \a which to \a pixmap.
       
  3331 
       
  3332     The pixmaps are used by QWizard when displaying a page. Which
       
  3333     pixmaps are actually used depend on the \l{Wizard Look and
       
  3334     Feel}{wizard style}.
       
  3335 
       
  3336     Pixmaps can also be set for the entire wizard using
       
  3337     QWizard::setPixmap(), in which case they apply for all pages that
       
  3338     don't specify a pixmap.
       
  3339 
       
  3340     \sa QWizard::setPixmap(), {Elements of a Wizard Page}
       
  3341 */
       
  3342 void QWizardPage::setPixmap(QWizard::WizardPixmap which, const QPixmap &pixmap)
       
  3343 {
       
  3344     Q_D(QWizardPage);
       
  3345     Q_ASSERT(uint(which) < QWizard::NPixmaps);
       
  3346     d->pixmaps[which] = pixmap;
       
  3347     if (d->wizard && d->wizard->currentPage() == this)
       
  3348         d->wizard->d_func()->updatePixmap(which);
       
  3349 }
       
  3350 
       
  3351 /*!
       
  3352     Returns the pixmap set for role \a which.
       
  3353 
       
  3354     Pixmaps can also be set for the entire wizard using
       
  3355     QWizard::setPixmap(), in which case they apply for all pages that
       
  3356     don't specify a pixmap.
       
  3357 
       
  3358     \sa QWizard::pixmap(), {Elements of a Wizard Page}
       
  3359 */
       
  3360 QPixmap QWizardPage::pixmap(QWizard::WizardPixmap which) const
       
  3361 {
       
  3362     Q_D(const QWizardPage);
       
  3363     Q_ASSERT(uint(which) < QWizard::NPixmaps);
       
  3364 
       
  3365     const QPixmap &pixmap = d->pixmaps[which];
       
  3366     if (!pixmap.isNull())
       
  3367         return pixmap;
       
  3368 
       
  3369     if (wizard())
       
  3370         return wizard()->pixmap(which);
       
  3371 
       
  3372     return pixmap;
       
  3373 }
       
  3374 
       
  3375 /*!
       
  3376     This virtual function is called by QWizard::initializePage() to
       
  3377     prepare the page just before it is shown either as a result of QWizard::restart()
       
  3378     being called, or as a result of the user clicking \gui Next.
       
  3379     (However, if the \l QWizard::IndependentPages option is set, this function is only
       
  3380     called the first time the page is shown.)
       
  3381 
       
  3382     By reimplementing this function, you can ensure that the page's
       
  3383     fields are properly initialized based on fields from previous
       
  3384     pages. For example:
       
  3385 
       
  3386     \snippet examples/dialogs/classwizard/classwizard.cpp 17
       
  3387 
       
  3388     The default implementation does nothing.
       
  3389 
       
  3390     \sa QWizard::initializePage(), cleanupPage(), QWizard::IndependentPages
       
  3391 */
       
  3392 void QWizardPage::initializePage()
       
  3393 {
       
  3394 }
       
  3395 
       
  3396 /*!
       
  3397     This virtual function is called by QWizard::cleanupPage() when
       
  3398     the user leaves the page by clicking \gui Back (unless the \l QWizard::IndependentPages
       
  3399     option is set).
       
  3400 
       
  3401     The default implementation resets the page's fields to their
       
  3402     original values (the values they had before initializePage() was
       
  3403     called).
       
  3404 
       
  3405     \sa QWizard::cleanupPage(), initializePage(), QWizard::IndependentPages
       
  3406 */
       
  3407 void QWizardPage::cleanupPage()
       
  3408 {
       
  3409     Q_D(QWizardPage);
       
  3410     if (d->wizard) {
       
  3411         QVector<QWizardField> &fields = d->wizard->d_func()->fields;
       
  3412         for (int i = 0; i < fields.count(); ++i) {
       
  3413             const QWizardField &field = fields.at(i);
       
  3414             if (field.page == this)
       
  3415                 field.object->setProperty(field.property, field.initialValue);
       
  3416         }
       
  3417     }
       
  3418 }
       
  3419 
       
  3420 /*!
       
  3421     This virtual function is called by QWizard::validateCurrentPage()
       
  3422     when the user clicks \gui Next or \gui Finish to perform some
       
  3423     last-minute validation. If it returns true, the next page is shown
       
  3424     (or the wizard finishes); otherwise, the current page stays up.
       
  3425 
       
  3426     The default implementation returns true.
       
  3427 
       
  3428     When possible, it is usually better style to disable the \gui
       
  3429     Next or \gui Finish button (by specifying \l{mandatory fields} or
       
  3430     reimplementing isComplete()) than to reimplement validatePage().
       
  3431 
       
  3432     \sa QWizard::validateCurrentPage(), isComplete()
       
  3433 */
       
  3434 bool QWizardPage::validatePage()
       
  3435 {
       
  3436     return true;
       
  3437 }
       
  3438 
       
  3439 /*!
       
  3440     This virtual function is called by QWizard to determine whether
       
  3441     the \gui Next or \gui Finish button should be enabled or
       
  3442     disabled.
       
  3443 
       
  3444     The default implementation returns true if all \l{mandatory
       
  3445     fields} are filled; otherwise, it returns false.
       
  3446 
       
  3447     If you reimplement this function, make sure to emit completeChanged(),
       
  3448     from the rest of your implementation, whenever the value of isComplete()
       
  3449     changes. This ensures that QWizard updates the enabled or disabled state of
       
  3450     its buttons. An example of the reimplementation is
       
  3451     available \l{http://qt.nokia.com/doc/qq/qq22-qwizard.html#validatebeforeitstoolate}
       
  3452     {here}.
       
  3453 
       
  3454     \sa completeChanged(), isFinalPage()
       
  3455 */
       
  3456 bool QWizardPage::isComplete() const
       
  3457 {
       
  3458     Q_D(const QWizardPage);
       
  3459 
       
  3460     if (!d->wizard)
       
  3461         return true;
       
  3462 
       
  3463     const QVector<QWizardField> &wizardFields = d->wizard->d_func()->fields;
       
  3464     for (int i = wizardFields.count() - 1; i >= 0; --i) {
       
  3465         const QWizardField &field = wizardFields.at(i);
       
  3466         if (field.page == this && field.mandatory) {
       
  3467             QVariant value = field.object->property(field.property);
       
  3468             if (value == field.initialValue)
       
  3469                 return false;
       
  3470 
       
  3471 #ifndef QT_NO_LINEEDIT
       
  3472             if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(field.object)) {
       
  3473                 if (!lineEdit->hasAcceptableInput())
       
  3474                     return false;
       
  3475             }
       
  3476 #endif
       
  3477 #ifndef QT_NO_SPINBOX
       
  3478             if (QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(field.object)) {
       
  3479                 if (!spinBox->hasAcceptableInput())
       
  3480                     return false;
       
  3481             }
       
  3482 #endif
       
  3483         }
       
  3484     }
       
  3485     return true;
       
  3486 }
       
  3487 
       
  3488 /*!
       
  3489     Explicitly sets this page to be final if \a finalPage is true.
       
  3490 
       
  3491     After calling setFinalPage(true), isFinalPage() returns true and the \gui
       
  3492     Finish button is visible (and enabled if isComplete() returns
       
  3493     true).
       
  3494 
       
  3495     After calling setFinalPage(false), isFinalPage() returns true if
       
  3496     nextId() returns -1; otherwise, it returns false.
       
  3497 
       
  3498     \sa isComplete(), QWizard::HaveFinishButtonOnEarlyPages
       
  3499 */
       
  3500 void QWizardPage::setFinalPage(bool finalPage)
       
  3501 {
       
  3502     Q_D(QWizardPage);
       
  3503     d->explicitlyFinal = finalPage;
       
  3504     QWizard *wizard = this->wizard();
       
  3505     if (wizard && wizard->currentPage() == this)
       
  3506         wizard->d_func()->updateCurrentPage();
       
  3507 }
       
  3508 
       
  3509 /*!
       
  3510     This function is called by QWizard to determine whether the \gui
       
  3511     Finish button should be shown for this page or not.
       
  3512 
       
  3513     By default, it returns true if there is no next page
       
  3514     (i.e., nextId() returns -1); otherwise, it returns false.
       
  3515 
       
  3516     By explicitly calling setFinalPage(true), you can let the user perform an
       
  3517     "early finish".
       
  3518 
       
  3519     \sa isComplete(), QWizard::HaveFinishButtonOnEarlyPages
       
  3520 */
       
  3521 bool QWizardPage::isFinalPage() const
       
  3522 {
       
  3523     Q_D(const QWizardPage);
       
  3524     if (d->explicitlyFinal)
       
  3525         return true;
       
  3526 
       
  3527     QWizard *wizard = this->wizard();
       
  3528     if (wizard && wizard->currentPage() == this) {
       
  3529         // try to use the QWizard implementation if possible
       
  3530         return wizard->nextId() == -1;
       
  3531     } else {
       
  3532         return nextId() == -1;
       
  3533     }
       
  3534 }
       
  3535 
       
  3536 /*!
       
  3537     Sets this page to be a commit page if \a commitPage is true; otherwise,
       
  3538     sets it to be a normal page.
       
  3539 
       
  3540     A commit page is a page that represents an action which cannot be undone
       
  3541     by clicking \gui Back or \gui Cancel.
       
  3542 
       
  3543     A \gui Commit button replaces the \gui Next button on a commit page. Clicking this
       
  3544     button simply calls QWizard::next() just like clicking \gui Next does.
       
  3545 
       
  3546     A page entered directly from a commit page has its \gui Back button disabled.
       
  3547 
       
  3548     \sa isCommitPage()
       
  3549 */
       
  3550 void QWizardPage::setCommitPage(bool commitPage)
       
  3551 {
       
  3552     Q_D(QWizardPage);
       
  3553     d->commit = commitPage;
       
  3554     QWizard *wizard = this->wizard();
       
  3555     if (wizard && wizard->currentPage() == this)
       
  3556         wizard->d_func()->updateCurrentPage();
       
  3557 }
       
  3558 
       
  3559 /*!
       
  3560     Returns true if this page is a commit page; otherwise returns false.
       
  3561 
       
  3562     \sa setCommitPage()
       
  3563 */
       
  3564 bool QWizardPage::isCommitPage() const
       
  3565 {
       
  3566     Q_D(const QWizardPage);
       
  3567     return d->commit;
       
  3568 }
       
  3569 
       
  3570 /*!
       
  3571     Sets the text on button \a which to be \a text on this page.
       
  3572 
       
  3573     By default, the text on buttons depends on the QWizard::wizardStyle,
       
  3574     but may be redefined for the wizard as a whole using QWizard::setButtonText().
       
  3575 
       
  3576     \sa buttonText(), QWizard::setButtonText(), QWizard::buttonText()
       
  3577 */
       
  3578 void QWizardPage::setButtonText(QWizard::WizardButton which, const QString &text)
       
  3579 {
       
  3580     Q_D(QWizardPage);
       
  3581     d->buttonCustomTexts.insert(which, text);
       
  3582     if (wizard() && wizard()->currentPage() == this && wizard()->d_func()->btns[which])
       
  3583         wizard()->d_func()->btns[which]->setText(text);
       
  3584 }
       
  3585 
       
  3586 /*!
       
  3587     Returns the text on button \a which on this page.
       
  3588 
       
  3589     If a text has ben set using setButtonText(), this text is returned.
       
  3590     Otherwise, if a text has been set using QWizard::setButtonText(),
       
  3591     this text is returned.
       
  3592 
       
  3593     By default, the text on buttons depends on the QWizard::wizardStyle.
       
  3594     For example, on Mac OS X, the \gui Next button is called \gui
       
  3595     Continue.
       
  3596 
       
  3597     \sa setButtonText(), QWizard::buttonText(), QWizard::setButtonText()
       
  3598 */
       
  3599 QString QWizardPage::buttonText(QWizard::WizardButton which) const
       
  3600 {
       
  3601     Q_D(const QWizardPage);
       
  3602 
       
  3603     if (d->buttonCustomTexts.contains(which))
       
  3604         return d->buttonCustomTexts.value(which);
       
  3605 
       
  3606     if (wizard())
       
  3607         return wizard()->buttonText(which);
       
  3608 
       
  3609     return QString();
       
  3610 }
       
  3611 
       
  3612 /*!
       
  3613     This virtual function is called by QWizard::nextId() to find
       
  3614     out which page to show when the user clicks the \gui Next button.
       
  3615 
       
  3616     The return value is the ID of the next page, or -1 if no page follows.
       
  3617 
       
  3618     By default, this function returns the lowest ID greater than the ID
       
  3619     of the current page, or -1 if there is no such ID.
       
  3620 
       
  3621     By reimplementing this function, you can specify a dynamic page
       
  3622     order. For example:
       
  3623 
       
  3624     \snippet examples/dialogs/licensewizard/licensewizard.cpp 18
       
  3625 
       
  3626     \sa QWizard::nextId()
       
  3627 */
       
  3628 int QWizardPage::nextId() const
       
  3629 {
       
  3630     Q_D(const QWizardPage);
       
  3631 
       
  3632     if (!d->wizard)
       
  3633         return -1;
       
  3634 
       
  3635     bool foundCurrentPage = false;
       
  3636 
       
  3637     const QWizardPrivate::PageMap &pageMap = d->wizard->d_func()->pageMap;
       
  3638     QWizardPrivate::PageMap::const_iterator i = pageMap.constBegin();
       
  3639     QWizardPrivate::PageMap::const_iterator end = pageMap.constEnd();
       
  3640 
       
  3641     for (; i != end; ++i) {
       
  3642         if (i.value() == this) {
       
  3643             foundCurrentPage = true;
       
  3644         } else if (foundCurrentPage) {
       
  3645             return i.key();
       
  3646         }
       
  3647     }
       
  3648     return -1;
       
  3649 }
       
  3650 
       
  3651 /*!
       
  3652     \fn void QWizardPage::completeChanged()
       
  3653 
       
  3654     This signal is emitted whenever the complete state of the page
       
  3655     (i.e., the value of isComplete()) changes.
       
  3656 
       
  3657     If you reimplement isComplete(), make sure to emit
       
  3658     completeChanged() whenever the value of isComplete() changes, to
       
  3659     ensure that QWizard updates the enabled or disabled state of its
       
  3660     buttons.
       
  3661 
       
  3662     \sa isComplete()
       
  3663 */
       
  3664 
       
  3665 /*!
       
  3666     Sets the value of the field called \a name to \a value.
       
  3667 
       
  3668     This function can be used to set fields on any page of the wizard.
       
  3669     It is equivalent to calling
       
  3670     wizard()->\l{QWizard::setField()}{setField(\a name, \a value)}.
       
  3671 
       
  3672     \sa QWizard::setField(), field(), registerField()
       
  3673 */
       
  3674 void QWizardPage::setField(const QString &name, const QVariant &value)
       
  3675 {
       
  3676     Q_D(QWizardPage);
       
  3677     if (!d->wizard)
       
  3678         return;
       
  3679     d->wizard->setField(name, value);
       
  3680 }
       
  3681 
       
  3682 /*!
       
  3683     Returns the value of the field called \a name.
       
  3684 
       
  3685     This function can be used to access fields on any page of the
       
  3686     wizard. It is equivalent to calling
       
  3687     wizard()->\l{QWizard::field()}{field(\a name)}.
       
  3688 
       
  3689     Example:
       
  3690 
       
  3691     \snippet examples/dialogs/classwizard/classwizard.cpp 17
       
  3692 
       
  3693     \sa QWizard::field(), setField(), registerField()
       
  3694 */
       
  3695 QVariant QWizardPage::field(const QString &name) const
       
  3696 {
       
  3697     Q_D(const QWizardPage);
       
  3698     if (!d->wizard)
       
  3699         return QVariant();
       
  3700     return d->wizard->field(name);
       
  3701 }
       
  3702 
       
  3703 /*!
       
  3704     Creates a field called \a name associated with the given \a
       
  3705     property of the given \a widget. From then on, that property
       
  3706     becomes accessible using field() and setField().
       
  3707 
       
  3708     Fields are global to the entire wizard and make it easy for any
       
  3709     single page to access information stored by another page, without
       
  3710     having to put all the logic in QWizard or having the pages know
       
  3711     explicitly about each other.
       
  3712 
       
  3713     If \a name ends with an asterisk (\c *), the field is a mandatory
       
  3714     field. When a page has mandatory fields, the \gui Next and/or
       
  3715     \gui Finish buttons are enabled only when all mandatory fields
       
  3716     are filled. This requires a \a changedSignal to be specified, to
       
  3717     tell QWizard to recheck the value stored by the mandatory field.
       
  3718 
       
  3719     QWizard knows the most common Qt widgets. For these (or their
       
  3720     subclasses), you don't need to specify a \a property or a \a
       
  3721     changedSignal. The table below lists these widgets:
       
  3722 
       
  3723     \table
       
  3724     \header \o Widget          \o Property                            \o Change Notification Signal
       
  3725     \row    \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()}
       
  3726     \row    \o QAbstractSlider \o int \l{QAbstractSlider::}{value}    \o \l{QAbstractSlider::}{valueChanged()}
       
  3727     \row    \o QComboBox       \o int \l{QComboBox::}{currentIndex}   \o \l{QComboBox::}{currentIndexChanged()}
       
  3728     \row    \o QDateTimeEdit   \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()}
       
  3729     \row    \o QLineEdit       \o QString \l{QLineEdit::}{text}       \o \l{QLineEdit::}{textChanged()}
       
  3730     \row    \o QListWidget     \o int \l{QListWidget::}{currentRow}   \o \l{QListWidget::}{currentRowChanged()}
       
  3731     \row    \o QSpinBox        \o int \l{QSpinBox::}{value}           \o \l{QSpinBox::}{valueChanged()}
       
  3732     \endtable
       
  3733 
       
  3734     You can use QWizard::setDefaultProperty() to add entries to this
       
  3735     table or to override existing entries.
       
  3736 
       
  3737     To consider a field "filled", QWizard simply checks that their
       
  3738     current value doesn't equal their original value (the value they
       
  3739     had before initializePage() was called). For QLineEdit, it also
       
  3740     checks that
       
  3741     \l{QLineEdit::hasAcceptableInput()}{hasAcceptableInput()} returns
       
  3742     true, to honor any validator or mask.
       
  3743 
       
  3744     QWizard's mandatory field mechanism is provided for convenience.
       
  3745     It can be bypassed by reimplementing QWizardPage::isComplete().
       
  3746 
       
  3747     \sa field(), setField(), QWizard::setDefaultProperty()
       
  3748 */
       
  3749 void QWizardPage::registerField(const QString &name, QWidget *widget, const char *property,
       
  3750                                 const char *changedSignal)
       
  3751 {
       
  3752     Q_D(QWizardPage);
       
  3753     QWizardField field(this, name, widget, property, changedSignal);
       
  3754     if (d->wizard) {
       
  3755         d->wizard->d_func()->addField(field);
       
  3756     } else {
       
  3757         d->pendingFields += field;
       
  3758     }
       
  3759 }
       
  3760 
       
  3761 /*!
       
  3762     Returns the wizard associated with this page, or 0 if this page
       
  3763     hasn't been inserted into a QWizard yet.
       
  3764 
       
  3765     \sa QWizard::addPage(), QWizard::setPage()
       
  3766 */
       
  3767 QWizard *QWizardPage::wizard() const
       
  3768 {
       
  3769     Q_D(const QWizardPage);
       
  3770     return d->wizard;
       
  3771 }
       
  3772 
       
  3773 QT_END_NAMESPACE
       
  3774 
       
  3775 #include "moc_qwizard.cpp"
       
  3776 
       
  3777 #endif // QT_NO_WIZARD