Fix build of QWizard tests with QT_USE_QSTRINGBUILDER
[profile/ivi/qtbase.git] / tests / auto / widgets / dialogs / qwizard / tst_qwizard.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QFont>
44 #include <QtTest/QtTest>
45 #include <QCheckBox>
46 #include <QLabel>
47 #include <QLineEdit>
48 #include <QList>
49 #include <QPushButton>
50 #include <QToolButton>
51 #include <QVBoxLayout>
52 #include <QWizard>
53 #include <QStyle>
54 #include <QPlastiqueStyle>
55 #include <QTreeWidget>
56
57 static QImage grabWidget(QWidget *window)
58 {
59     return QPixmap::grabWidget(window).toImage();
60 }
61
62 class tst_QWizard : public QObject
63 {
64     Q_OBJECT
65
66 public:
67     tst_QWizard();
68
69 public slots:
70     void init();
71     void cleanup();
72
73 private slots:
74     void buttonText();
75     void setButtonLayout();
76     void setButton();
77     void setTitleFormatEtc();
78     void setPixmap();
79     void setDefaultProperty();
80     void addPage();
81     void setPage();
82     void setStartId();
83     void setOption_IndependentPages();
84     void setOption_IgnoreSubTitles();
85     void setOption_ExtendedWatermarkPixmap();
86     void setOption_NoDefaultButton();
87     void setOption_NoBackButtonOnStartPage();
88     void setOption_NoBackButtonOnLastPage();
89     void setOption_DisabledBackButtonOnLastPage();
90     void setOption_HaveNextButtonOnLastPage();
91     void setOption_HaveFinishButtonOnEarlyPages();
92     void setOption_NoCancelButton();
93     void setOption_CancelButtonOnLeft();
94     void setOption_HaveHelpButton();
95     void setOption_HelpButtonOnRight();
96     void setOption_HaveCustomButtonX();
97     void combinations_data();
98     void combinations();
99     void showCurrentPageOnly();
100     void setButtonText();
101     void setCommitPage();
102     void setWizardStyle();
103     void removePage();
104     void sideWidget();
105
106     // task-specific tests below me:
107     void task161660_buttonSpacing();
108     void task177716_disableCommitButton();
109     void task183550_stretchFactor();
110     void task161658_alignments();
111     void task177022_setFixedSize();
112     void task248107_backButton();
113     void task255350_fieldObjectDestroyed();
114
115     /*
116         Things that could be added:
117
118         1. Test virtual functions that are called, signals that are
119            emitted, etc.
120
121         2. Test QWizardPage more thorougly.
122
123         3. Test the look and field a bit more (especially the
124            different wizard styles, and how they interact with
125            pixmaps, titles, subtitles, etc.).
126
127         4. Test minimum sizes, sizes, maximum sizes, resizing, etc.
128
129         5. Try setting various options and wizard styles in various
130            orders and check that the results are the same every time,
131            no matter the order in which the properties were set.
132
133            -> Initial version done (tst_QWizard::combinations())
134
135         6. Test done() and restart().
136
137         7. Test default properties of built-in widgets.
138
139         8. Test mutual exclusiveness of Next and Commit buttons.
140     */
141 };
142
143 tst_QWizard::tst_QWizard()
144 {
145 }
146
147 void tst_QWizard::init()
148 {
149 #ifdef Q_OS_WINCE //disable magic for WindowsCE
150     qApp->setAutoMaximizeThreshold(-1);
151 #endif
152 }
153
154 void tst_QWizard::cleanup()
155 {
156 }
157
158 void tst_QWizard::buttonText()
159 {
160     QWizard wizard;
161     wizard.setWizardStyle(QWizard::ClassicStyle);
162
163     // Check the buttons' original text in Classic and Modern styles.
164     for (int pass = 0; pass < 2; ++pass) {
165         QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("< &Back"));
166         QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
167         QVERIFY(wizard.buttonText(QWizard::FinishButton).endsWith("Finish"));
168         QVERIFY(wizard.buttonText(QWizard::CancelButton).endsWith("Cancel"));
169         QVERIFY(wizard.buttonText(QWizard::HelpButton).endsWith("Help"));
170
171         QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
172         QVERIFY(wizard.buttonText(QWizard::CustomButton2).isEmpty());
173         QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
174
175         // robustness
176         QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
177         QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
178         QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
179         QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
180
181         wizard.setWizardStyle(QWizard::ModernStyle);
182     }
183
184     // Check the buttons' original text in Mac style.
185     wizard.setWizardStyle(QWizard::MacStyle);
186
187     QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("Go Back"));
188     QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("Continue"));
189     QCOMPARE(wizard.buttonText(QWizard::FinishButton), QString("Done"));
190     QCOMPARE(wizard.buttonText(QWizard::CancelButton), QString("Cancel"));
191     QCOMPARE(wizard.buttonText(QWizard::HelpButton), QString("Help"));
192
193     QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
194     QVERIFY(wizard.buttonText(QWizard::CustomButton2).isEmpty());
195     QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
196
197     // robustness
198     QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
199     QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
200     QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
201     QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
202
203     // Modify the buttons' text and see what happens.
204     wizard.setButtonText(QWizard::NextButton, "N&este");
205     wizard.setButtonText(QWizard::CustomButton2, "&Cucu");
206     wizard.setButtonText(QWizard::Stretch, "Stretch");
207
208     QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("Go Back"));
209     QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("N&este"));
210     QCOMPARE(wizard.buttonText(QWizard::FinishButton), QString("Done"));
211     QCOMPARE(wizard.buttonText(QWizard::CancelButton), QString("Cancel"));
212     QCOMPARE(wizard.buttonText(QWizard::HelpButton), QString("Help"));
213
214     QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
215     QCOMPARE(wizard.buttonText(QWizard::CustomButton2), QString("&Cucu"));
216     QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
217
218     // robustness
219     QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
220     QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
221     QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
222     QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
223
224     // Switch back to Classic style and see what happens.
225     wizard.setWizardStyle(QWizard::ClassicStyle);
226
227     for (int pass = 0; pass < 2; ++pass) {
228         QCOMPARE(wizard.buttonText(QWizard::BackButton), QString("< &Back"));
229         QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("N&este"));
230         QVERIFY(wizard.buttonText(QWizard::FinishButton).endsWith("Finish"));
231         QVERIFY(wizard.buttonText(QWizard::CancelButton).endsWith("Cancel"));
232         QVERIFY(wizard.buttonText(QWizard::HelpButton).endsWith("Help"));
233
234         QVERIFY(wizard.buttonText(QWizard::CustomButton1).isEmpty());
235         QCOMPARE(wizard.buttonText(QWizard::CustomButton2), QString("&Cucu"));
236         QVERIFY(wizard.buttonText(QWizard::CustomButton3).isEmpty());
237
238         // robustness
239         QVERIFY(wizard.buttonText(QWizard::Stretch).isEmpty());
240         QVERIFY(wizard.buttonText(QWizard::NoButton).isEmpty());
241         QVERIFY(wizard.buttonText(QWizard::NStandardButtons).isEmpty());
242         QVERIFY(wizard.buttonText(QWizard::NButtons).isEmpty());
243
244         wizard.setOptions(QWizard::NoDefaultButton
245                           | QWizard::NoBackButtonOnStartPage
246                           | QWizard::NoBackButtonOnLastPage
247                           | QWizard::DisabledBackButtonOnLastPage
248                           | QWizard::NoCancelButton
249                           | QWizard::CancelButtonOnLeft
250                           | QWizard::HaveHelpButton
251                           | QWizard::HelpButtonOnRight
252                           | QWizard::HaveCustomButton1
253                           | QWizard::HaveCustomButton2
254                           | QWizard::HaveCustomButton3);
255     }
256 }
257
258 void tst_QWizard::setButtonLayout()
259 {
260     QList<QWizard::WizardButton> layout;
261
262     QWizard wizard;
263     wizard.setWizardStyle(QWizard::ClassicStyle);
264     wizard.setOptions(0);
265     wizard.setButtonLayout(layout);
266     wizard.show();
267     qApp->processEvents();
268
269     // if these crash, this means there's a bug in QWizard
270     QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
271     QVERIFY(wizard.button(QWizard::BackButton)->text().contains("Back"));
272     QVERIFY(wizard.button(QWizard::FinishButton)->text().contains("Finish"));
273     QVERIFY(wizard.button(QWizard::CancelButton)->text().contains("Cancel"));
274     QVERIFY(wizard.button(QWizard::HelpButton)->text().contains("Help"));
275     QVERIFY(wizard.button(QWizard::CustomButton1)->text().isEmpty());
276     QVERIFY(wizard.button(QWizard::CustomButton2)->text().isEmpty());
277     QVERIFY(wizard.button(QWizard::CustomButton3)->text().isEmpty());
278     QVERIFY(!wizard.button(QWizard::Stretch));
279     QVERIFY(!wizard.button(QWizard::NoButton));
280
281     QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
282     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
283     QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
284
285     layout << QWizard::NextButton << QWizard::HelpButton;
286     wizard.setButtonLayout(layout);
287     qApp->processEvents();
288
289     QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
290     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
291     QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
292
293     wizard.addPage(new QWizardPage);
294     wizard.addPage(new QWizardPage);
295     qApp->processEvents();
296
297     QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
298     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
299     QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
300
301     wizard.restart();
302     qApp->processEvents();
303
304     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
305     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
306     QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
307
308     layout.clear();
309     layout << QWizard::NextButton << QWizard::HelpButton << QWizard::BackButton
310            << QWizard::FinishButton << QWizard::CancelButton << QWizard::Stretch
311            << QWizard::CustomButton2;
312
313     // Turn on all the button-related wizard options. Some of these
314     // should have no impact on a custom layout; others should.
315     wizard.setButtonLayout(layout);
316     wizard.setOptions(QWizard::NoDefaultButton
317                       | QWizard::NoBackButtonOnStartPage
318                       | QWizard::NoBackButtonOnLastPage
319                       | QWizard::DisabledBackButtonOnLastPage
320                       | QWizard::HaveNextButtonOnLastPage
321                       | QWizard::HaveFinishButtonOnEarlyPages
322                       | QWizard::NoCancelButton
323                       | QWizard::CancelButtonOnLeft
324                       | QWizard::HaveHelpButton
325                       | QWizard::HelpButtonOnRight
326                       | QWizard::HaveCustomButton1
327                       | QWizard::HaveCustomButton2
328                       | QWizard::HaveCustomButton3);
329     qApp->processEvents();
330
331     // we're on first page
332     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
333     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
334     QVERIFY(wizard.button(QWizard::CancelButton)->isVisible()); // NoCancelButton overridden
335     QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
336     QVERIFY(!wizard.button(QWizard::CustomButton1)->isVisible());
337     QVERIFY(wizard.button(QWizard::CustomButton2)->isVisible());    // HaveCustomButton2 overridden
338     QVERIFY(!wizard.button(QWizard::CustomButton3)->isVisible());
339
340     wizard.next();
341     qApp->processEvents();
342
343     // we're on last page
344     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
345     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
346     QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
347     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
348     QVERIFY(wizard.button(QWizard::FinishButton)->isEnabled());
349     QVERIFY(wizard.button(QWizard::CancelButton)->isVisible()); // NoCancelButton overridden
350     QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
351     QVERIFY(!wizard.button(QWizard::CustomButton1)->isVisible());
352     QVERIFY(wizard.button(QWizard::CustomButton2)->isVisible());    // HaveCustomButton2 overridden
353     QVERIFY(!wizard.button(QWizard::CustomButton3)->isVisible());
354
355     // Check that the buttons are in the right order on screen.
356     for (int pass = 0; pass < 2; ++pass) {
357         wizard.setLayoutDirection(pass == 0 ? Qt::LeftToRight : Qt::RightToLeft);
358         qApp->processEvents();
359
360         int sign = (pass == 0) ? +1 : -1;
361
362         int p[5];
363         p[0] = sign * wizard.button(QWizard::NextButton)->x();
364         p[1] = sign * wizard.button(QWizard::HelpButton)->x();
365         p[2] = sign * wizard.button(QWizard::FinishButton)->x();
366         p[3] = sign * wizard.button(QWizard::CancelButton)->x();
367         p[4] = sign * wizard.button(QWizard::CustomButton2)->x();
368
369         QVERIFY(p[0] < p[1]);
370         QVERIFY(p[1] < p[2]);
371         QVERIFY(p[2] < p[3]);
372         QVERIFY(p[3] < p[4]);
373     }
374
375     layout.clear();
376     wizard.setButtonLayout(layout);
377     qApp->processEvents();
378
379     for (int i = -1; i < 50; ++i) {
380         QAbstractButton *button = wizard.button(QWizard::WizardButton(i));
381         QVERIFY(!button || !button->isVisible());
382     }
383 }
384
385 void tst_QWizard::setButton()
386 {
387     QPointer<QToolButton> toolButton = new QToolButton;
388
389     QWizard wizard;
390     wizard.setWizardStyle(QWizard::ClassicStyle);
391     wizard.setButton(QWizard::NextButton, toolButton);
392     wizard.setButton(QWizard::CustomButton2, new QCheckBox("Kustom 2"));
393
394     QVERIFY(qobject_cast<QToolButton *>(wizard.button(QWizard::NextButton)));
395     QVERIFY(qobject_cast<QCheckBox *>(wizard.button(QWizard::CustomButton2)));
396     QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::CustomButton1)));
397
398     QVERIFY(toolButton != 0);
399
400     // resetting the same button does nothing
401     wizard.setButton(QWizard::NextButton, toolButton);
402     QVERIFY(toolButton != 0);
403
404     // revert to default button
405     wizard.setButton(QWizard::NextButton, 0);
406     QVERIFY(toolButton == 0);
407     QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton)));
408     QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
409 }
410
411 void tst_QWizard::setTitleFormatEtc()
412 {
413     QWizard wizard;
414     QVERIFY(wizard.titleFormat() == Qt::AutoText);
415     QVERIFY(wizard.subTitleFormat() == Qt::AutoText);
416
417     wizard.setTitleFormat(Qt::RichText);
418     QVERIFY(wizard.titleFormat() == Qt::RichText);
419     QVERIFY(wizard.subTitleFormat() == Qt::AutoText);
420
421     wizard.setSubTitleFormat(Qt::PlainText);
422     QVERIFY(wizard.titleFormat() == Qt::RichText);
423     QVERIFY(wizard.subTitleFormat() == Qt::PlainText);
424 }
425
426 void tst_QWizard::setPixmap()
427 {
428     QPixmap p1(1, 1);
429     QPixmap p2(2, 2);
430     QPixmap p3(3, 3);
431     QPixmap p4(4, 4);
432     QPixmap p5(5, 5);
433
434     QWizard wizard;
435     QWizardPage *page = new QWizardPage;
436     QWizardPage *page2 = new QWizardPage;
437
438     wizard.addPage(page);
439     wizard.addPage(page2);
440
441     QVERIFY(wizard.pixmap(QWizard::BannerPixmap).isNull());
442     QVERIFY(wizard.pixmap(QWizard::LogoPixmap).isNull());
443     QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).isNull());
444 #ifdef Q_OS_MAC
445     if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_3) {
446         QEXPECT_FAIL("", "QTBUG-23701", Continue);
447         QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull() == false);
448     } else {
449         // fall through since the image doesn't exist on a 10.3 system.
450         QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
451     }
452 #else
453     QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull());
454 #endif
455
456     QVERIFY(page->pixmap(QWizard::BannerPixmap).isNull());
457     QVERIFY(page->pixmap(QWizard::LogoPixmap).isNull());
458     QVERIFY(page->pixmap(QWizard::WatermarkPixmap).isNull());
459 #ifdef Q_OS_MAC
460     if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_3) {
461         QEXPECT_FAIL("", "QTBUG-23701", Continue);
462         QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull() == false);
463     } else {
464         // fall through since the image doesn't exist on a 10.3 system.
465         QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
466     }
467 #else
468     QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
469 #endif
470     wizard.setPixmap(QWizard::BannerPixmap, p1);
471     wizard.setPixmap(QWizard::LogoPixmap, p2);
472     wizard.setPixmap(QWizard::WatermarkPixmap, p3);
473     wizard.setPixmap(QWizard::BackgroundPixmap, p4);
474
475     page->setPixmap(QWizard::LogoPixmap, p5);
476
477     QVERIFY(wizard.pixmap(QWizard::BannerPixmap).size() == p1.size());
478     QVERIFY(wizard.pixmap(QWizard::LogoPixmap).size() == p2.size());
479     QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).size() == p3.size());
480     QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).size() == p4.size());
481
482     QVERIFY(page->pixmap(QWizard::BannerPixmap).size() == p1.size());
483     QVERIFY(page->pixmap(QWizard::LogoPixmap).size() == p5.size());
484     QVERIFY(page->pixmap(QWizard::WatermarkPixmap).size() == p3.size());
485     QVERIFY(page->pixmap(QWizard::BackgroundPixmap).size() == p4.size());
486
487     QVERIFY(page2->pixmap(QWizard::BannerPixmap).size() == p1.size());
488     QVERIFY(page2->pixmap(QWizard::LogoPixmap).size() == p2.size());
489     QVERIFY(page2->pixmap(QWizard::WatermarkPixmap).size() == p3.size());
490     QVERIFY(page2->pixmap(QWizard::BackgroundPixmap).size() == p4.size());
491 }
492
493 class MyPage1 : public QWizardPage
494 {
495 public:
496     MyPage1() {
497         edit1 = new QLineEdit("Bla 1", this);
498
499         edit2 = new QLineEdit("Bla 2", this);
500         edit2->setInputMask("Mask");
501
502         edit3 = new QLineEdit("Bla 3", this);
503         edit3->setMaxLength(25);
504
505         edit4 = new QLineEdit("Bla 4", this);
506     }
507
508     void registerField(const QString &name, QWidget *widget,
509                        const char *property = 0,
510                        const char *changedSignal = 0)
511         { QWizardPage::registerField(name, widget, property, changedSignal); }
512
513     QLineEdit *edit1;
514     QLineEdit *edit2;
515     QLineEdit *edit3;
516     QLineEdit *edit4;
517 };
518
519 void tst_QWizard::setDefaultProperty()
520 {
521     QWizard wizard;
522     MyPage1 *page = new MyPage1;
523     wizard.addPage(page);
524
525     page->registerField("edit1", page->edit1);
526
527     wizard.setDefaultProperty("QLineEdit", "inputMask", 0);
528     page->registerField("edit2", page->edit2);
529
530     wizard.setDefaultProperty("QLineEdit", "maxLength", 0);
531     page->registerField("edit3", page->edit3);
532
533     wizard.setDefaultProperty("QLineEdit", "text", SIGNAL(textChanged(QString)));
534     page->registerField("edit3bis", page->edit3);
535
536     wizard.setDefaultProperty("QWidget", "enabled", 0); // less specific, i.e. ignored
537     page->registerField("edit4", page->edit4);
538     QTest::ignoreMessage(QtWarningMsg,"QWizard::setField: Couldn't write to property 'customProperty'");
539     wizard.setDefaultProperty("QLineEdit", "customProperty", 0);
540     page->registerField("edit4bis", page->edit4);
541
542     QCOMPARE(wizard.field("edit1").toString(), QString("Bla 1"));
543     QCOMPARE(wizard.field("edit2").toString(), page->edit2->inputMask());
544     QCOMPARE(wizard.field("edit3").toInt(), 25);
545     QCOMPARE(wizard.field("edit3bis").toString(), QString("Bla 3"));
546     QCOMPARE(wizard.field("edit4").toString(), QString("Bla 4"));
547     QCOMPARE(wizard.field("edit4bis").toString(), QString());
548
549     wizard.setField("edit1", "Alpha");
550     wizard.setField("edit2", "Beta");
551     wizard.setField("edit3", 50);
552     wizard.setField("edit3bis", "Gamma");
553     wizard.setField("edit4", "Delta");
554     wizard.setField("edit4bis", "Epsilon");
555
556     QCOMPARE(wizard.field("edit1").toString(), QString("Alpha"));
557     QVERIFY(wizard.field("edit2").toString().contains("Beta"));
558     QCOMPARE(wizard.field("edit3").toInt(), 50);
559     QCOMPARE(wizard.field("edit3bis").toString(), QString("Gamma"));
560     QCOMPARE(wizard.field("edit4").toString(), QString("Delta"));
561     QCOMPARE(wizard.field("edit4bis").toString(), QString("Epsilon"));
562
563     // make sure the data structure is reasonable
564     for (int i = 0; i < 200000; ++i) {
565         wizard.setDefaultProperty("QLineEdit", QByteArray("x" + QByteArray::number(i)).constData(), 0);
566         wizard.setDefaultProperty("QLabel", QByteArray("y" + QByteArray::number(i)).constData(), 0);
567     }
568 }
569
570 void tst_QWizard::addPage()
571 {
572     QWidget *parent = new QWidget;
573     QWizard wizard;
574     const int N = 100;
575     QWizardPage *pages[N];
576     QSignalSpy spy(&wizard, SIGNAL(pageAdded(int)));
577
578     for (int i = 0; i < N; ++i) {
579         pages[i] = new QWizardPage(parent);
580         QCOMPARE(wizard.addPage(pages[i]), i);
581         QCOMPARE(pages[i]->window(), (QWidget *)&wizard);
582         QCOMPARE(wizard.startId(), 0);
583         QCOMPARE(spy.count(), 1);
584         QList<QVariant> arguments = spy.takeFirst();
585         QCOMPARE(arguments.at(0).toInt(), i);
586     }
587
588     for (int i = 0; i < N; ++i) {
589         QVERIFY(pages[i] == wizard.page(i));
590     }
591     QVERIFY(!wizard.page(-1));
592     QVERIFY(!wizard.page(N));
593     QVERIFY(!wizard.page(N + 1));
594
595     wizard.setPage(N + 50, new QWizardPage);
596     QCOMPARE(spy.count(), 1);
597     QList<QVariant> arguments = spy.takeFirst();
598     QCOMPARE(arguments.at(0).toInt(), N + 50);
599     wizard.setPage(-3000, new QWizardPage);
600     QCOMPARE(spy.count(), 1);
601     arguments = spy.takeFirst();
602     QCOMPARE(arguments.at(0).toInt(), -3000);
603
604     QWizardPage *pageX = new QWizardPage;
605     QCOMPARE(wizard.addPage(pageX), N + 51);
606     QCOMPARE(wizard.page(N + 51), pageX);
607     QCOMPARE(spy.count(), 1);
608     arguments = spy.takeFirst();
609     QCOMPARE(arguments.at(0).toInt(), N + 51);
610
611     QCOMPARE(wizard.addPage(new QWizardPage), N + 52);
612     QCOMPARE(spy.count(), 1);
613     arguments = spy.takeFirst();
614     QCOMPARE(arguments.at(0).toInt(), N + 52);
615
616     QTest::ignoreMessage(QtWarningMsg,"QWizard::setPage: Cannot insert null page");    
617     wizard.addPage(0); // generates a warning
618     QCOMPARE(spy.count(), 0);
619     delete parent;
620 }
621
622 #define CHECK_VISITED(wizard, list) \
623     do { \
624         QList<int> myList = list; \
625         QCOMPARE((wizard).visitedPages(), myList); \
626         Q_FOREACH(int id, myList) \
627             QVERIFY((wizard).hasVisitedPage(id)); \
628     } while (0)
629
630 void tst_QWizard::setPage()
631 {
632     QWidget *parent = new QWidget;
633     QWizard wizard;
634     QWizardPage *page;
635     QSignalSpy spy(&wizard, SIGNAL(pageAdded(int)));
636
637     QCOMPARE(wizard.startId(), -1);
638     QCOMPARE(wizard.currentId(), -1);
639     QVERIFY(!wizard.currentPage());
640     QCOMPARE(wizard.nextId(), -1);
641
642     page = new QWizardPage(parent);
643     QTest::ignoreMessage(QtWarningMsg,"QWizard::setPage: Cannot insert page with ID -1");    
644     wizard.setPage(-1, page);   // gives a warning and does nothing
645     QCOMPARE(spy.count(), 0);
646     QVERIFY(!wizard.page(-2));
647     QVERIFY(!wizard.page(-1));
648     QVERIFY(!wizard.page(0));
649     QCOMPARE(wizard.startId(), -1);
650     QCOMPARE(wizard.currentId(), -1);
651     QVERIFY(!wizard.currentPage());
652     QCOMPARE(wizard.nextId(), -1);
653     CHECK_VISITED(wizard, QList<int>());
654
655     page = new QWizardPage(parent);
656     wizard.setPage(0, page);
657     QCOMPARE(spy.count(), 1);
658     QList<QVariant> arguments = spy.takeFirst();
659     QCOMPARE(arguments.at(0).toInt(), 0);
660     QCOMPARE(page->window(), (QWidget *)&wizard);
661     QCOMPARE(wizard.page(0), page);
662     QCOMPARE(wizard.startId(), 0);
663     QCOMPARE(wizard.currentId(), -1);
664     QVERIFY(!wizard.currentPage());
665     QCOMPARE(wizard.nextId(), -1);
666     CHECK_VISITED(wizard, QList<int>());
667
668     page = new QWizardPage(parent);
669     wizard.setPage(-2, page);
670     QCOMPARE(spy.count(), 1);
671     arguments = spy.takeFirst();
672     QCOMPARE(arguments.at(0).toInt(), -2);
673     QCOMPARE(page->window(), (QWidget *)&wizard);
674     QCOMPARE(wizard.page(-2), page);
675     QCOMPARE(wizard.startId(), -2);
676     QCOMPARE(wizard.currentId(), -1);
677     QVERIFY(!wizard.currentPage());
678     QCOMPARE(wizard.nextId(), -1);
679     CHECK_VISITED(wizard, QList<int>());
680
681     wizard.restart();
682     QCOMPARE(wizard.page(-2), page);
683     QCOMPARE(wizard.startId(), -2);
684     QCOMPARE(wizard.currentId(), -2);
685     QVERIFY(wizard.currentPage() == page);
686     QCOMPARE(wizard.nextId(), 0);
687     CHECK_VISITED(wizard, QList<int>() << -2);
688
689     page = new QWizardPage(parent);
690     wizard.setPage(2, page);
691     QCOMPARE(spy.count(), 1);
692     arguments = spy.takeFirst();
693     QCOMPARE(arguments.at(0).toInt(), 2);
694     QCOMPARE(wizard.page(2), page);
695     QCOMPARE(wizard.startId(), -2);
696     QCOMPARE(wizard.currentId(), -2);
697     QVERIFY(wizard.currentPage() == wizard.page(-2));
698     QCOMPARE(wizard.nextId(), 0);
699     CHECK_VISITED(wizard, QList<int>() << -2);
700
701     wizard.restart();
702     QCOMPARE(wizard.startId(), -2);
703     QCOMPARE(wizard.currentId(), -2);
704     QVERIFY(wizard.currentPage() == wizard.page(-2));
705     QCOMPARE(wizard.nextId(), 0);
706     CHECK_VISITED(wizard, QList<int>() << -2);
707
708     page = new QWizardPage(parent);
709     wizard.setPage(-3, page);
710     QCOMPARE(spy.count(), 1);
711     arguments = spy.takeFirst();
712     QCOMPARE(arguments.at(0).toInt(), -3);
713     QCOMPARE(wizard.page(-3), page);
714     QCOMPARE(wizard.startId(), -3);
715     QCOMPARE(wizard.currentId(), -2);
716     QVERIFY(wizard.currentPage() == wizard.page(-2));
717     QCOMPARE(wizard.nextId(), 0);
718     CHECK_VISITED(wizard, QList<int>() << -2);
719
720     wizard.restart();
721     QCOMPARE(wizard.startId(), -3);
722     QCOMPARE(wizard.currentId(), -3);
723     QVERIFY(wizard.currentPage() == wizard.page(-3));
724     QCOMPARE(wizard.nextId(), -2);
725     CHECK_VISITED(wizard, QList<int>() << -3);
726
727     wizard.next();
728     QCOMPARE(wizard.startId(), -3);
729     QCOMPARE(wizard.currentId(), -2);
730     QVERIFY(wizard.currentPage() == wizard.page(-2));
731     QCOMPARE(wizard.nextId(), 0);
732     CHECK_VISITED(wizard, QList<int>() << -3 << -2);
733
734     wizard.next();
735     QCOMPARE(wizard.startId(), -3);
736     QCOMPARE(wizard.currentId(), 0);
737     QVERIFY(wizard.currentPage() == wizard.page(0));
738     QCOMPARE(wizard.nextId(), 2);
739     CHECK_VISITED(wizard, QList<int>() << -3 << -2 << 0);
740
741     for (int i = 0; i < 100; ++i) {
742         wizard.next();
743         QCOMPARE(wizard.startId(), -3);
744         QCOMPARE(wizard.currentId(), 2);
745         QVERIFY(wizard.currentPage() == wizard.page(2));
746         QCOMPARE(wizard.nextId(), -1);
747         CHECK_VISITED(wizard, QList<int>() << -3 << -2 << 0 << 2);
748     }
749
750     wizard.back();
751     QCOMPARE(wizard.startId(), -3);
752     QCOMPARE(wizard.currentId(), 0);
753     QVERIFY(wizard.currentPage() == wizard.page(0));
754     QCOMPARE(wizard.nextId(), 2);
755     CHECK_VISITED(wizard, QList<int>() << -3 << -2 << 0);
756
757     wizard.back();
758     QCOMPARE(wizard.startId(), -3);
759     QCOMPARE(wizard.currentId(), -2);
760     QVERIFY(wizard.currentPage() == wizard.page(-2));
761     QCOMPARE(wizard.nextId(), 0);
762     CHECK_VISITED(wizard, QList<int>() << -3 << -2);
763
764     for (int i = 0; i < 100; ++i) {
765         wizard.back();
766         QCOMPARE(wizard.startId(), -3);
767         QCOMPARE(wizard.currentId(), -3);
768         QVERIFY(wizard.currentPage() == wizard.page(-3));
769         QCOMPARE(wizard.nextId(), -2);
770         CHECK_VISITED(wizard, QList<int>() << -3);
771     }
772
773     for (int i = 0; i < 100; ++i) {
774         wizard.restart();
775         QCOMPARE(wizard.startId(), -3);
776         QCOMPARE(wizard.currentId(), -3);
777         QVERIFY(wizard.currentPage() == wizard.page(-3));
778         QCOMPARE(wizard.nextId(), -2);
779         CHECK_VISITED(wizard, QList<int>() << -3);
780     }
781     QCOMPARE(spy.count(), 0);
782     delete parent;
783 }
784
785 void tst_QWizard::setStartId()
786 {
787     QWizard wizard;
788     QCOMPARE(wizard.startId(), -1);
789
790     wizard.setPage(INT_MIN, new QWizardPage);
791     QCOMPARE(wizard.startId(), INT_MIN);
792
793     wizard.setPage(-2, new QWizardPage);
794     QCOMPARE(wizard.startId(), INT_MIN);
795
796     wizard.setPage(0, new QWizardPage);
797     QCOMPARE(wizard.startId(), INT_MIN);
798
799     wizard.setPage(1, new QWizardPage);
800     QCOMPARE(wizard.startId(), INT_MIN);
801
802     wizard.setPage(INT_MAX, new QWizardPage);
803     QCOMPARE(wizard.startId(), INT_MIN);
804
805     QTest::ignoreMessage(QtWarningMsg,"QWizard::setStartId: Invalid page ID 123");
806     wizard.setStartId(123);
807     QCOMPARE(wizard.startId(), INT_MIN);
808
809     wizard.setStartId(-1);
810     QCOMPARE(wizard.startId(), INT_MIN);
811
812     wizard.setStartId(-2);
813     QCOMPARE(wizard.startId(), -2);
814     QCOMPARE(wizard.nextId(), -1);
815
816     wizard.setStartId(-1);
817     QCOMPARE(wizard.startId(), INT_MIN);
818
819     wizard.setStartId(-2);
820     QCOMPARE(wizard.startId(), -2);
821     QCOMPARE(wizard.nextId(), -1);
822
823     wizard.restart();
824     QCOMPARE(wizard.startId(), -2);
825     QCOMPARE(wizard.currentId(), -2);
826     QVERIFY(wizard.currentPage() == wizard.page(-2));
827     QCOMPARE(wizard.nextId(), 0);
828
829     wizard.next();
830     QCOMPARE(wizard.startId(), -2);
831     QCOMPARE(wizard.currentId(), 0);
832     QVERIFY(wizard.currentPage() == wizard.page(0));
833     QCOMPARE(wizard.nextId(), 1);
834
835     wizard.setStartId(INT_MIN);
836     QCOMPARE(wizard.startId(), INT_MIN);
837     QCOMPARE(wizard.currentId(), 0);
838     QVERIFY(wizard.currentPage() == wizard.page(0));
839     QCOMPARE(wizard.nextId(), 1);
840
841     wizard.next();
842     QCOMPARE(wizard.startId(), INT_MIN);
843     QCOMPARE(wizard.currentId(), 1);
844     QVERIFY(wizard.currentPage() == wizard.page(1));
845     QCOMPARE(wizard.nextId(), INT_MAX);
846
847     wizard.next();
848     QCOMPARE(wizard.startId(), INT_MIN);
849     QCOMPARE(wizard.currentId(), INT_MAX);
850     QVERIFY(wizard.currentPage() == wizard.page(INT_MAX));
851     QCOMPARE(wizard.nextId(), -1);
852     CHECK_VISITED(wizard, QList<int>() << -2 << 0 << 1 << INT_MAX);
853 }
854
855 struct MyPage2 : public QWizardPage
856 {
857 public:
858     MyPage2() : init(0), cleanup(0), validate(0) {}
859
860     void initializePage() { ++init; QWizardPage::initializePage(); }
861     void cleanupPage() { ++cleanup; QWizardPage::cleanupPage(); }
862     bool validatePage() { ++validate; return QWizardPage::validatePage(); }
863
864     bool sanityCheck(int init, int cleanup)
865     {
866         return init == this->init
867             && cleanup == this->cleanup
868             && (this->init == this->cleanup || this->init - 1 == this->cleanup);
869     }
870
871     int init;
872     int cleanup;
873     int validate;
874 };
875
876 #define CHECK_PAGE_INIT(i0, c0, i1, c1, i2, c2) \
877     QVERIFY(page0->sanityCheck((i0), (c0))); \
878     QVERIFY(page1->sanityCheck((i1), (c1))); \
879     QVERIFY(page2->sanityCheck((i2), (c2)));
880
881 void tst_QWizard::setOption_IndependentPages()
882 {
883     MyPage2 *page0 = new MyPage2;
884     MyPage2 *page1 = new MyPage2;
885     MyPage2 *page2 = new MyPage2;
886
887     QWizard wizard;
888     wizard.addPage(page0);
889     wizard.addPage(page1);
890     wizard.addPage(page2);
891
892     QVERIFY(!wizard.testOption(QWizard::IndependentPages));
893
894     wizard.restart();
895
896     // Make sure initializePage() and cleanupPage() are called are
897     // they should when the
898     // wizard.testOption(QWizard::IndependentPages option is off.
899     for (int i = 0; i < 10; ++i) {
900         CHECK_PAGE_INIT(i + 1, i, i, i, i, i);
901
902         wizard.next();
903         CHECK_PAGE_INIT(i + 1, i, i + 1, i, i, i);
904
905         wizard.next();
906         CHECK_PAGE_INIT(i + 1, i, i + 1, i, i + 1, i);
907
908         wizard.next();
909         CHECK_PAGE_INIT(i + 1, i, i + 1, i, i + 1, i);
910
911         wizard.back();
912         CHECK_PAGE_INIT(i + 1, i, i + 1, i, i + 1, i + 1);
913
914         wizard.back();
915         CHECK_PAGE_INIT(i + 1, i, i + 1, i + 1, i + 1, i + 1);
916
917         wizard.back();
918         CHECK_PAGE_INIT(i + 1, i, i + 1, i + 1, i + 1, i + 1);
919
920         wizard.restart();
921     }
922
923     CHECK_PAGE_INIT(11, 10, 10, 10, 10, 10);
924
925     wizard.next();
926     CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
927
928     // Now, turn on the option and check that they're called at the
929     // appropriate times (which aren't the same).
930     wizard.setOption(QWizard::IndependentPages, true);
931     CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
932
933     wizard.back();
934     CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
935
936     wizard.next();
937     CHECK_PAGE_INIT(11, 10, 11, 10, 10, 10);
938
939     wizard.next();
940     CHECK_PAGE_INIT(11, 10, 11, 10, 11, 10);
941
942     wizard.next();
943     CHECK_PAGE_INIT(11, 10, 11, 10, 11, 10);
944
945     wizard.back();
946     CHECK_PAGE_INIT(11, 10, 11, 10, 11, 10);
947
948     wizard.setStartId(2);
949
950     wizard.restart();
951     CHECK_PAGE_INIT(11, 11, 11, 11, 12, 11);
952
953     wizard.back();
954     CHECK_PAGE_INIT(11, 11, 11, 11, 12, 11);
955
956     wizard.next();
957     CHECK_PAGE_INIT(11, 11, 11, 11, 12, 11);
958
959     wizard.setStartId(0);
960     wizard.restart();
961     CHECK_PAGE_INIT(12, 11, 11, 11, 12, 12);
962
963     wizard.next();
964     CHECK_PAGE_INIT(12, 11, 12, 11, 12, 12);
965
966     wizard.next();
967     CHECK_PAGE_INIT(12, 11, 12, 11, 13, 12);
968
969     wizard.back();
970     CHECK_PAGE_INIT(12, 11, 12, 11, 13, 12);
971
972     // Fun stuff here.
973
974     wizard.setOption(QWizard::IndependentPages, false);
975     CHECK_PAGE_INIT(12, 11, 12, 11, 13, 13);
976
977     wizard.setOption(QWizard::IndependentPages, true);
978     CHECK_PAGE_INIT(12, 11, 12, 11, 13, 13);
979
980     wizard.setOption(QWizard::IndependentPages, false);
981     CHECK_PAGE_INIT(12, 11, 12, 11, 13, 13);
982
983     wizard.back();
984     CHECK_PAGE_INIT(12, 11, 12, 12, 13, 13);
985
986     wizard.back();
987     CHECK_PAGE_INIT(12, 11, 12, 12, 13, 13);
988 }
989
990 void tst_QWizard::setOption_IgnoreSubTitles()
991 {
992 #if defined(Q_OS_WINCE)
993     QSKIP("Skipped because of limited resources and potential crash. (Task: 166824)");
994 #endif
995     QWizard wizard1;
996     wizard1.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
997     wizard1.resize(500, 500);
998     QVERIFY(!wizard1.testOption(QWizard::IgnoreSubTitles));
999     QWizardPage *page11 = new QWizardPage;
1000     page11->setTitle("Page X");
1001     page11->setSubTitle("Some subtitle");
1002
1003     QWizardPage *page12 = new QWizardPage;
1004     page12->setTitle("Page X");
1005
1006     wizard1.addPage(page11);
1007     wizard1.addPage(page12);
1008
1009     QWizard wizard2;
1010     wizard2.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
1011     wizard2.resize(500, 500);
1012     wizard2.setOption(QWizard::IgnoreSubTitles, true);
1013     QWizardPage *page21 = new QWizardPage;
1014     page21->setTitle("Page X");
1015     page21->setSubTitle("Some subtitle");
1016
1017     QWizardPage *page22 = new QWizardPage;
1018     page22->setTitle("Page X");
1019
1020     wizard2.addPage(page21);
1021     wizard2.addPage(page22);
1022
1023     wizard1.show();
1024     wizard2.show();
1025
1026     // Check that subtitles are shown when they should (i.e.,
1027     // they're set and IgnoreSubTitles is off).
1028
1029     qApp->setActiveWindow(0); // ensure no focus rectangle around cancel button
1030     QImage i11 = grabWidget(&wizard1);
1031     QImage i21 = grabWidget(&wizard2);
1032     QVERIFY(i11 != i21);
1033
1034     wizard1.next();
1035     wizard2.next();
1036
1037     QImage i12 = grabWidget(&wizard1);
1038     QImage i22 = grabWidget(&wizard2);
1039     QVERIFY(i12 == i22);
1040     QVERIFY(i21 == i22);
1041
1042     wizard1.back();
1043     wizard2.back();
1044
1045     QImage i13 = grabWidget(&wizard1);
1046     QImage i23 = grabWidget(&wizard2);
1047     QVERIFY(i13 == i11);
1048     QVERIFY(i23 == i21);
1049
1050     wizard1.setOption(QWizard::IgnoreSubTitles, true);
1051     wizard2.setOption(QWizard::IgnoreSubTitles, false);
1052
1053     QImage i14 = grabWidget(&wizard1);
1054     QImage i24 = grabWidget(&wizard2);
1055     QVERIFY(i14 == i21);
1056     QVERIFY(i24 == i11);
1057
1058     // Check the impact of subtitles on the rest of the layout, by
1059     // using a subtitle that looks empty (but that isn't). In
1060     // Classic and Modern styles, this should be enough to trigger a
1061     // "header"; in Mac style, this only creates a QLabel, with no
1062     // text, i.e. it doesn't affect the layout.
1063
1064     page11->setSubTitle("<b></b>");    // not quite empty, but looks empty
1065
1066     for (int i = 0; i < 3; ++i) {
1067         for (int j = 0; j < 2; ++j) {
1068             wizard1.setOption(QWizard::IgnoreSubTitles, j == 0);
1069
1070             wizard1.setWizardStyle(i == 0 ? QWizard::ClassicStyle
1071                                    : i == 1 ? QWizard::ModernStyle
1072                                             : QWizard::MacStyle);
1073             wizard1.restart();
1074             QImage i1 = grabWidget(&wizard1);
1075
1076             wizard1.next();
1077             QImage i2 = grabWidget(&wizard1);
1078
1079             if (j == 0 || wizard1.wizardStyle() == QWizard::MacStyle) {
1080                 QVERIFY(i1 == i2);
1081             } else {
1082                 QVERIFY(i1 != i2);
1083             }
1084         }
1085     }
1086 }
1087
1088 void tst_QWizard::setOption_ExtendedWatermarkPixmap()
1089 {
1090 #if defined(Q_OS_WINCE)
1091     QSKIP("Skipped because of limited resources and potential crash. (Task: 166824)");
1092 #endif
1093     QPixmap watermarkPixmap(200, 400);
1094     watermarkPixmap.fill(Qt::black);
1095
1096     QWizard wizard1;
1097     wizard1.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
1098     QVERIFY(!wizard1.testOption(QWizard::ExtendedWatermarkPixmap));
1099     QWizardPage *page11 = new QWizardPage;
1100     page11->setTitle("Page X");
1101     page11->setPixmap(QWizard::WatermarkPixmap, watermarkPixmap);
1102
1103     QWizardPage *page12 = new QWizardPage;
1104     page12->setTitle("Page X");
1105
1106     wizard1.addPage(page11);
1107     wizard1.addPage(page12);
1108
1109     QWizard wizard2;
1110     wizard2.setButtonLayout(QList<QWizard::WizardButton>() << QWizard::CancelButton);
1111     wizard2.setOption(QWizard::ExtendedWatermarkPixmap, true);
1112     QWizardPage *page21 = new QWizardPage;
1113     page21->setTitle("Page X");
1114     page21->setPixmap(QWizard::WatermarkPixmap, watermarkPixmap);
1115
1116     QWizardPage *page22 = new QWizardPage;
1117     page22->setTitle("Page X");
1118
1119     wizard2.addPage(page21);
1120     wizard2.addPage(page22);
1121
1122     wizard1.show();
1123     wizard2.show();
1124
1125     // Check the impact of watermark pixmaps on the rest of the layout.
1126
1127     for (int i = 0; i < 3; ++i) {
1128         QImage i1[2];
1129         QImage i2[2];
1130         for (int j = 0; j < 2; ++j) {
1131             wizard1.setOption(QWizard::ExtendedWatermarkPixmap, j == 0);
1132
1133             wizard1.setWizardStyle(i == 0 ? QWizard::ClassicStyle
1134                                    : i == 1 ? QWizard::ModernStyle
1135                                             : QWizard::MacStyle);
1136             wizard1.restart();
1137             wizard1.setMaximumSize(1000, 1000);
1138             wizard1.resize(600, 600);
1139             i1[j] = grabWidget(&wizard1);
1140
1141             wizard1.next();
1142             wizard1.setMaximumSize(1000, 1000);
1143             wizard1.resize(600, 600);
1144             i2[j] = grabWidget(&wizard1);
1145         }
1146
1147         if (wizard1.wizardStyle() == QWizard::MacStyle) {
1148             QVERIFY(i1[0] == i1[1]);
1149             QVERIFY(i2[0] == i2[1]);
1150             QVERIFY(i1[0] == i2[0]);
1151         } else {
1152             QVERIFY(i1[0] != i1[1]);
1153             QVERIFY(i2[0] == i2[1]);
1154             QVERIFY(i1[0] != i2[0]);
1155             QVERIFY(i1[1] != i2[1]);
1156         }
1157     }
1158 }
1159
1160 void tst_QWizard::setOption_NoDefaultButton()
1161 {
1162     QWizard wizard;
1163     wizard.setOption(QWizard::NoDefaultButton, false);
1164     wizard.setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
1165     wizard.addPage(new QWizardPage);
1166     wizard.page(0)->setFinalPage(true);
1167     wizard.addPage(new QWizardPage);
1168
1169     if (QPushButton *pb = qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton)))
1170         pb->setAutoDefault(false);
1171     if (QPushButton *pb = qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton)))
1172         pb->setAutoDefault(false);
1173
1174     wizard.show();
1175     qApp->processEvents();
1176     QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
1177     QVERIFY(wizard.button(QWizard::FinishButton)->isEnabled());
1178
1179     wizard.next();
1180     QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
1181
1182     wizard.back();
1183     QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
1184
1185     wizard.setOption(QWizard::NoDefaultButton, true);
1186     QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
1187     QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
1188
1189     wizard.next();
1190     QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
1191     QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
1192
1193     wizard.back();
1194     QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
1195     QVERIFY(!qobject_cast<QPushButton *>(wizard.button(QWizard::FinishButton))->isDefault());
1196
1197     wizard.setOption(QWizard::NoDefaultButton, false);
1198     QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::NextButton))->isDefault());
1199 }
1200
1201 void tst_QWizard::setOption_NoBackButtonOnStartPage()
1202 {
1203     QWizard wizard;
1204     wizard.setOption(QWizard::NoBackButtonOnStartPage, true);
1205     wizard.addPage(new QWizardPage);
1206     wizard.addPage(new QWizardPage);
1207     wizard.addPage(new QWizardPage);
1208
1209     wizard.setStartId(1);
1210     wizard.show();
1211     qApp->processEvents();
1212
1213     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
1214
1215     wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
1216     qApp->processEvents();
1217     QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1218
1219     wizard.setOption(QWizard::NoBackButtonOnStartPage, true);
1220     qApp->processEvents();
1221     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
1222
1223     wizard.next();
1224     qApp->processEvents();
1225     QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1226
1227     wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
1228     QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1229
1230     wizard.setOption(QWizard::NoBackButtonOnStartPage, true);
1231     QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1232
1233     wizard.back();
1234     qApp->processEvents();
1235     QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
1236 }
1237
1238 void tst_QWizard::setOption_NoBackButtonOnLastPage()
1239 {
1240     for (int i = 0; i < 2; ++i) {
1241         QWizard wizard;
1242         wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
1243         wizard.setOption(QWizard::NoBackButtonOnLastPage, true);
1244         wizard.setOption(QWizard::DisabledBackButtonOnLastPage, i == 0);    // changes nothing
1245         wizard.addPage(new QWizardPage);
1246         wizard.addPage(new QWizardPage);
1247         wizard.page(1)->setFinalPage(true);     // changes nothing (final != last in general)
1248         wizard.addPage(new QWizardPage);
1249
1250         wizard.setStartId(1);
1251         wizard.show();
1252         qApp->processEvents();
1253
1254         QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1255
1256         wizard.next();
1257         qApp->processEvents();
1258         QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
1259
1260         wizard.next();
1261         qApp->processEvents();
1262         QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
1263
1264         wizard.back();
1265         qApp->processEvents();
1266         QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1267
1268         wizard.next();
1269         qApp->processEvents();
1270         QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
1271
1272         wizard.setOption(QWizard::NoBackButtonOnLastPage, false);
1273         QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1274
1275         wizard.setOption(QWizard::NoBackButtonOnLastPage, true);
1276         QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());
1277
1278         wizard.addPage(new QWizardPage);
1279         QVERIFY(!wizard.button(QWizard::BackButton)->isVisible());  // this is maybe wrong
1280     }
1281 }
1282
1283 void tst_QWizard::setOption_DisabledBackButtonOnLastPage()
1284 {
1285     QWizard wizard;
1286     wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
1287     wizard.setOption(QWizard::DisabledBackButtonOnLastPage, true);
1288     wizard.addPage(new QWizardPage);
1289     wizard.addPage(new QWizardPage);
1290     wizard.page(1)->setFinalPage(true);     // changes nothing (final != last in general)
1291     wizard.addPage(new QWizardPage);
1292
1293     wizard.setStartId(1);
1294     wizard.show();
1295     qApp->processEvents();
1296
1297     QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1298     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
1299
1300     wizard.next();
1301     qApp->processEvents();
1302     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
1303
1304     wizard.next();
1305     qApp->processEvents();
1306     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
1307
1308     wizard.back();
1309     qApp->processEvents();
1310     QVERIFY(wizard.button(QWizard::BackButton)->isVisible());
1311     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
1312
1313     wizard.next();
1314     qApp->processEvents();
1315     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
1316
1317     wizard.setOption(QWizard::DisabledBackButtonOnLastPage, false);
1318     QVERIFY(wizard.button(QWizard::BackButton)->isEnabled());
1319
1320     wizard.setOption(QWizard::DisabledBackButtonOnLastPage, true);
1321     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
1322
1323     wizard.addPage(new QWizardPage);
1324     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());  // this is maybe wrong
1325 }
1326
1327 void tst_QWizard::setOption_HaveNextButtonOnLastPage()
1328 {
1329     QWizard wizard;
1330     wizard.setOption(QWizard::HaveNextButtonOnLastPage, false);
1331     wizard.addPage(new QWizardPage);
1332     wizard.addPage(new QWizardPage);
1333     wizard.page(1)->setFinalPage(true);     // changes nothing (final != last in general)
1334     wizard.addPage(new QWizardPage);
1335
1336     wizard.setStartId(1);
1337     wizard.show();
1338     qApp->processEvents();
1339
1340     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
1341     QVERIFY(wizard.button(QWizard::NextButton)->isEnabled());
1342
1343     wizard.next();
1344     QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
1345
1346     wizard.setOption(QWizard::HaveNextButtonOnLastPage, true);
1347     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
1348     QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
1349
1350     wizard.next();
1351     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
1352     QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
1353
1354     wizard.back();
1355     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
1356     QVERIFY(wizard.button(QWizard::NextButton)->isEnabled());
1357
1358     wizard.setOption(QWizard::HaveNextButtonOnLastPage, false);
1359     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
1360     QVERIFY(wizard.button(QWizard::NextButton)->isEnabled());
1361
1362     wizard.next();
1363     QVERIFY(!wizard.button(QWizard::NextButton)->isVisible());
1364
1365     wizard.setOption(QWizard::HaveNextButtonOnLastPage, true);
1366     QVERIFY(wizard.button(QWizard::NextButton)->isVisible());
1367     QVERIFY(!wizard.button(QWizard::NextButton)->isEnabled());
1368 }
1369
1370 void tst_QWizard::setOption_HaveFinishButtonOnEarlyPages()
1371 {
1372     QWizard wizard;
1373     QVERIFY(!wizard.testOption(QWizard::HaveFinishButtonOnEarlyPages));
1374     wizard.addPage(new QWizardPage);
1375     wizard.addPage(new QWizardPage);
1376     wizard.page(1)->setFinalPage(true);
1377     wizard.addPage(new QWizardPage);
1378
1379     wizard.show();
1380     qApp->processEvents();
1381
1382     QVERIFY(!wizard.button(QWizard::FinishButton)->isVisible());
1383
1384     wizard.next();
1385     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
1386
1387     wizard.next();
1388     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
1389
1390     wizard.back();
1391     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
1392
1393     wizard.back();
1394     QVERIFY(!wizard.button(QWizard::FinishButton)->isVisible());
1395
1396     wizard.setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
1397     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
1398
1399     wizard.next();
1400     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
1401
1402     wizard.setOption(QWizard::HaveFinishButtonOnEarlyPages, false);
1403     QVERIFY(wizard.button(QWizard::FinishButton)->isVisible());
1404
1405     wizard.back();
1406     QVERIFY(!wizard.button(QWizard::FinishButton)->isVisible());
1407 }
1408
1409 void tst_QWizard::setOption_NoCancelButton()
1410 {
1411     for (int i = 0; i < 2; ++i) {
1412         QWizard wizard;
1413         wizard.setOption(QWizard::NoCancelButton, true);
1414         wizard.setOption(QWizard::CancelButtonOnLeft, i == 0);
1415         wizard.addPage(new QWizardPage);
1416         wizard.addPage(new QWizardPage);
1417         wizard.show();
1418         qApp->processEvents();
1419
1420         QVERIFY(!wizard.button(QWizard::CancelButton)->isVisible());
1421
1422         wizard.next();
1423         QVERIFY(!wizard.button(QWizard::CancelButton)->isVisible());
1424
1425         wizard.setOption(QWizard::NoCancelButton, false);
1426         QVERIFY(wizard.button(QWizard::CancelButton)->isVisible());
1427
1428         wizard.back();
1429         QVERIFY(wizard.button(QWizard::CancelButton)->isVisible());
1430
1431         wizard.setOption(QWizard::NoCancelButton, true);
1432         QVERIFY(!wizard.button(QWizard::CancelButton)->isVisible());
1433     }
1434 }
1435
1436 void tst_QWizard::setOption_CancelButtonOnLeft()
1437 {
1438     for (int i = 0; i < 2; ++i) {
1439         int sign = (i == 0) ? +1 : -1;
1440
1441         QWizard wizard;
1442         wizard.setLayoutDirection(i == 0 ? Qt::LeftToRight : Qt::RightToLeft);
1443         wizard.setOption(QWizard::NoCancelButton, false);
1444         wizard.setOption(QWizard::CancelButtonOnLeft, true);
1445         wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
1446         wizard.addPage(new QWizardPage);
1447         wizard.addPage(new QWizardPage);
1448         wizard.show();
1449         qApp->processEvents();
1450
1451         const QAbstractButton *refButton = wizard.button((wizard.wizardStyle() == QWizard::AeroStyle)
1452             ? QWizard::NextButton : QWizard::BackButton);
1453         const QAbstractButton *refButton2 = wizard.button((wizard.wizardStyle() == QWizard::AeroStyle)
1454             ? QWizard::FinishButton : QWizard::BackButton);
1455
1456         QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() < sign * refButton->x());
1457
1458         wizard.next();
1459         qApp->processEvents();
1460         QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() < sign * refButton->x());
1461
1462         wizard.setOption(QWizard::CancelButtonOnLeft, false);
1463         qApp->processEvents();
1464         QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() > sign * refButton2->x());
1465
1466         wizard.back();
1467         qApp->processEvents();
1468         QVERIFY(sign * wizard.button(QWizard::CancelButton)->x() > sign * refButton->x());
1469     }
1470 }
1471
1472 void tst_QWizard::setOption_HaveHelpButton()
1473 {
1474     for (int i = 0; i < 2; ++i) {
1475         QWizard wizard;
1476         QVERIFY(!wizard.testOption(QWizard::HaveHelpButton));
1477         wizard.setOption(QWizard::HaveHelpButton, false);
1478         wizard.setOption(QWizard::HelpButtonOnRight, i == 0);
1479         wizard.addPage(new QWizardPage);
1480         wizard.addPage(new QWizardPage);
1481         wizard.show();
1482         qApp->processEvents();
1483
1484         QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
1485
1486         wizard.next();
1487         QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
1488
1489         wizard.setOption(QWizard::HaveHelpButton, true);
1490         QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
1491
1492         wizard.back();
1493         QVERIFY(wizard.button(QWizard::HelpButton)->isVisible());
1494
1495         wizard.setOption(QWizard::HaveHelpButton, false);
1496         QVERIFY(!wizard.button(QWizard::HelpButton)->isVisible());
1497     }
1498 }
1499
1500 void tst_QWizard::setOption_HelpButtonOnRight()
1501 {
1502     for (int i = 0; i < 2; ++i) {
1503         int sign = (i == 0) ? +1 : -1;
1504
1505         QWizard wizard;
1506         wizard.setLayoutDirection(i == 0 ? Qt::LeftToRight : Qt::RightToLeft);
1507         wizard.setOption(QWizard::HaveHelpButton, true);
1508         wizard.setOption(QWizard::HelpButtonOnRight, false);
1509         wizard.setOption(QWizard::NoBackButtonOnStartPage, false);
1510         wizard.addPage(new QWizardPage);
1511         wizard.addPage(new QWizardPage);
1512         wizard.show();
1513         qApp->processEvents();
1514
1515         const QAbstractButton *refButton = wizard.button((wizard.wizardStyle() == QWizard::AeroStyle)
1516             ? QWizard::NextButton : QWizard::BackButton);
1517
1518         QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() < sign * refButton->x());
1519
1520         wizard.next();
1521         qApp->processEvents();
1522         QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() < sign * refButton->x());
1523
1524         wizard.setOption(QWizard::HelpButtonOnRight, true);
1525         qApp->processEvents();
1526         QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() > sign * refButton->x());
1527
1528         wizard.back();
1529         qApp->processEvents();
1530         QVERIFY(sign * wizard.button(QWizard::HelpButton)->x() > sign * refButton->x());
1531     }
1532 }
1533
1534 void tst_QWizard::setOption_HaveCustomButtonX()
1535 {
1536     for (int i = 0; i < 2; ++i) {
1537         for (int j = 0; j < 2; ++j) {
1538             for (int k = 0; k < 2; ++k) {
1539                 QWizard wizard;
1540                 wizard.setLayoutDirection(Qt::LeftToRight);
1541                 wizard.addPage(new QWizardPage);
1542                 wizard.addPage(new QWizardPage);
1543                 wizard.show();
1544
1545                 wizard.setButtonText(QWizard::CustomButton1, "Foo");
1546                 wizard.setButton(QWizard::CustomButton2, new QCheckBox("Bar"));
1547                 wizard.button(QWizard::CustomButton3)->setText("Baz");
1548
1549                 wizard.setOption(QWizard::HaveCustomButton1, i == 0);
1550                 wizard.setOption(QWizard::HaveCustomButton2, j == 0);
1551                 wizard.setOption(QWizard::HaveCustomButton3, k == 0);
1552
1553                 QVERIFY(wizard.button(QWizard::CustomButton1)->isHidden() == (i != 0));
1554                 QVERIFY(wizard.button(QWizard::CustomButton2)->isHidden() == (j != 0));
1555                 QVERIFY(wizard.button(QWizard::CustomButton3)->isHidden() == (k != 0));
1556
1557                 if (i + j + k == 0) {
1558                     qApp->processEvents();
1559                     QVERIFY(wizard.button(QWizard::CustomButton1)->x()
1560                             < wizard.button(QWizard::CustomButton2)->x());
1561                     QVERIFY(wizard.button(QWizard::CustomButton2)->x()
1562                             < wizard.button(QWizard::CustomButton3)->x());
1563                 }
1564             }
1565         }
1566     }
1567 }
1568
1569 class Operation
1570 {
1571 public:
1572     virtual void apply(QWizard *) const = 0;
1573     virtual QString describe() const = 0;
1574 protected:
1575     virtual ~Operation() {}
1576 };
1577
1578 class SetPage : public Operation
1579 {
1580     void apply(QWizard *wizard) const
1581     {
1582         wizard->restart();
1583         for (int j = 0; j < page; ++j)
1584             wizard->next();
1585     }
1586     QString describe() const { return QString("set page %1").arg(page); }
1587     const int page;
1588 public:
1589     SetPage(int page) : page(page) {}
1590 };
1591
1592 class SetStyle : public Operation
1593 {
1594     void apply(QWizard *wizard) const { wizard->setWizardStyle(style); }
1595     QString describe() const { return QString("set style %1").arg(style); }
1596     const QWizard::WizardStyle style;
1597 public:
1598     SetStyle(QWizard::WizardStyle style) : style(style) {}
1599 };
1600
1601 class SetOption : public Operation
1602 {
1603     void apply(QWizard *wizard) const { wizard->setOption(option, on); }
1604     QString describe() const;
1605     const QWizard::WizardOption option;
1606     const bool on;
1607 public:
1608     SetOption(QWizard::WizardOption option, bool on) : option(option), on(on) {}
1609 };
1610
1611 class OptionInfo
1612 {
1613     OptionInfo()
1614     {
1615         tags[QWizard::IndependentPages]             = "0/IPP";
1616         tags[QWizard::IgnoreSubTitles]              = "1/IST";
1617         tags[QWizard::ExtendedWatermarkPixmap]      = "2/EWP";
1618         tags[QWizard::NoDefaultButton]              = "3/NDB";
1619         tags[QWizard::NoBackButtonOnStartPage]      = "4/BSP";
1620         tags[QWizard::NoBackButtonOnLastPage]       = "5/BLP";
1621         tags[QWizard::DisabledBackButtonOnLastPage] = "6/DLP";
1622         tags[QWizard::HaveNextButtonOnLastPage]     = "7/NLP";
1623         tags[QWizard::HaveFinishButtonOnEarlyPages] = "8/FEP";
1624         tags[QWizard::NoCancelButton]               = "9/NCB";
1625         tags[QWizard::CancelButtonOnLeft]           = "10/CBL";
1626         tags[QWizard::HaveHelpButton]               = "11/HHB";
1627         tags[QWizard::HelpButtonOnRight]            = "12/HBR";
1628         tags[QWizard::HaveCustomButton1]            = "13/CB1";
1629         tags[QWizard::HaveCustomButton2]            = "14/CB2";
1630         tags[QWizard::HaveCustomButton3]            = "15/CB3";
1631
1632         for (int i = 0; i < 2; ++i) {
1633             QMap<QWizard::WizardOption, Operation *> operations_;
1634             foreach (QWizard::WizardOption option, tags.keys())
1635                 operations_[option] = new SetOption(option, i == 1);
1636             operations << operations_;
1637         }
1638     }
1639     OptionInfo(OptionInfo const&);
1640     OptionInfo& operator=(OptionInfo const&);
1641     QMap<QWizard::WizardOption, QString> tags;
1642     QList<QMap<QWizard::WizardOption, Operation *> > operations;
1643 public:
1644     static OptionInfo &instance()
1645     {
1646         static OptionInfo optionInfo;
1647         return optionInfo;
1648     }
1649
1650     QString tag(QWizard::WizardOption option) const { return tags.value(option); }
1651     Operation * operation(QWizard::WizardOption option, bool on) const
1652     { return operations.at(on).value(option); }
1653     QList<QWizard::WizardOption> options() const { return tags.keys(); }
1654 };
1655
1656 QString SetOption::describe() const
1657 {
1658     return QString("set opt %1 %2").arg(OptionInfo::instance().tag(option)).arg(on);
1659 }
1660
1661 Q_DECLARE_METATYPE(Operation *)
1662 Q_DECLARE_METATYPE(SetPage *)
1663 Q_DECLARE_METATYPE(SetStyle *)
1664 Q_DECLARE_METATYPE(SetOption *)
1665 Q_DECLARE_METATYPE(QList<Operation *>)
1666
1667 class TestGroup
1668 {
1669 public:
1670     enum Type {Equality, NonEquality};
1671
1672     TestGroup(const QString &name = QString("no name"), Type type = Equality)
1673         : name(name), type(type), nRows_(0) {}
1674
1675     void reset(const QString &name, Type type = Equality)
1676     {
1677         this->name = name;
1678         this->type = type;
1679         combinations.clear();
1680     }
1681
1682     QList<Operation *> &add()
1683     { combinations << new QList<Operation *>; return *(combinations.last()); }
1684
1685     void createTestRows()
1686     {
1687         for (int i = 0; i < combinations.count(); ++i) {
1688             QTest::newRow((name + QString(", row %1").arg(i)).toLatin1().data())
1689                 << (i == 0) << (type == Equality) << *(combinations.at(i));
1690             ++nRows_;
1691         }
1692     }
1693
1694     int nRows() const { return nRows_; }
1695
1696 private:
1697     QString name;
1698     Type type;
1699     int nRows_;
1700     QList<QList<Operation *> *> combinations;
1701 };
1702
1703 class IntroPage : public QWizardPage
1704 {
1705     Q_OBJECT
1706 public:
1707     IntroPage()
1708     {
1709         setTitle(tr("Intro"));
1710         setSubTitle(tr("Intro Subtitle"));
1711         QVBoxLayout *layout = new QVBoxLayout;
1712         layout->addWidget(new QLabel(tr("Intro Label")));
1713         setLayout(layout);
1714     }
1715 };
1716
1717 class MiddlePage : public QWizardPage
1718 {
1719     Q_OBJECT
1720 public:
1721     MiddlePage()
1722     {
1723         setTitle(tr("Middle"));
1724         setSubTitle(tr("Middle Subtitle"));
1725         QVBoxLayout *layout = new QVBoxLayout;
1726         layout->addWidget(new QLabel(tr("Middle Label")));
1727         setLayout(layout);
1728     }
1729 };
1730
1731 class ConclusionPage : public QWizardPage
1732 {
1733     Q_OBJECT
1734 public:
1735     ConclusionPage()
1736     {
1737         setTitle(tr("Conclusion"));
1738         setSubTitle(tr("Conclusion Subtitle"));
1739         QVBoxLayout *layout = new QVBoxLayout;
1740         layout->addWidget(new QLabel(tr("Conclusion Label")));
1741         setLayout(layout);
1742     }
1743 };
1744
1745 class TestWizard : public QWizard
1746 {
1747     Q_OBJECT
1748     QList<int> pageIds;
1749     QString opsDescr;
1750 public:
1751     TestWizard()
1752     {
1753         setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png"));
1754         setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png"));
1755         setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark.png"));
1756         setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo.png"));
1757         setButtonText(QWizard::CustomButton1, "custom 1");
1758         setButtonText(QWizard::CustomButton2, "custom 2");
1759         setButtonText(QWizard::CustomButton3, "custom 3");
1760         pageIds << addPage(new IntroPage);
1761         pageIds << addPage(new MiddlePage);
1762         pageIds << addPage(new ConclusionPage);
1763
1764         // Disable antialiased font rendering since this may sometimes result in tiny
1765         // and (apparent) non-deterministic pixel variations between images expected to be
1766         // identical. This may only be a problem on X11.
1767         QFont f = font();
1768         f.setStyleStrategy(QFont::NoAntialias);
1769         setFont(f);
1770
1771         // ### Required to work with a deficiency(?) in QWizard:
1772 //        setFixedSize(800, 600);
1773     }
1774
1775     ~TestWizard()
1776     {
1777         foreach (int id, pageIds) {
1778             QWizardPage *page_to_delete = page(id);
1779             removePage(id);
1780             delete page_to_delete;
1781         }
1782     }
1783
1784     void applyOperations(const QList<Operation *> &operations)
1785     {
1786         foreach (Operation * op, operations) {
1787             if (op) {
1788                 op->apply(this);
1789                 opsDescr += QString("(%1) ").arg(op->describe());
1790             }
1791         }
1792     }
1793
1794     QImage createImage() const
1795     {
1796         return QPixmap::grabWidget(const_cast<TestWizard *>(this))
1797             .toImage().convertToFormat(QImage::Format_ARGB32);
1798     }
1799
1800     QString operationsDescription() const { return opsDescr; }
1801 };
1802
1803 class CombinationsTestData
1804 {
1805     TestGroup testGroup;
1806     QList<Operation *> pageOps;
1807     QList<Operation *> styleOps;
1808     QMap<bool, QList<Operation *> *> setAllOptions;
1809 public:
1810     CombinationsTestData()
1811     {
1812         QTest::addColumn<bool>("ref");
1813         QTest::addColumn<bool>("testEquality");
1814         QTest::addColumn<QList<Operation *> >("operations");
1815         pageOps << new SetPage(0) << new SetPage(1) << new SetPage(2);
1816         styleOps << new SetStyle(QWizard::ClassicStyle) << new SetStyle(QWizard::ModernStyle)
1817                  << new SetStyle(QWizard::MacStyle);
1818 #define SETPAGE(page) pageOps.at(page)
1819 #define SETSTYLE(style) styleOps.at(style)
1820 #define OPT(option, on) OptionInfo::instance().operation(option, on)
1821 #define CLROPT(option) OPT(option, false)
1822 #define SETOPT(option) OPT(option, true)
1823         setAllOptions[false] = new QList<Operation *>;
1824         setAllOptions[true]  = new QList<Operation *>;
1825         foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
1826             *setAllOptions.value(false) << CLROPT(option);
1827             *setAllOptions.value(true) << SETOPT(option);
1828         }
1829 #define CLRALLOPTS *setAllOptions.value(false)
1830 #define SETALLOPTS *setAllOptions.value(true)
1831     }
1832
1833     int nRows() const { return testGroup.nRows(); }
1834
1835     // Creates "all" possible test rows. (WARNING: This typically makes the test take too long!)
1836     void createAllTestRows()
1837     {
1838         testGroup.reset("testAll 1.1");
1839         testGroup.add(); // i.e. no operations applied!
1840         testGroup.add() << SETPAGE(0);
1841         testGroup.add() << SETSTYLE(0);
1842         testGroup.add() << SETPAGE(0) << SETSTYLE(0);
1843         testGroup.add() << SETSTYLE(0) << SETPAGE(0);
1844         testGroup.createTestRows();
1845
1846         testGroup.reset("testAll 2.1");
1847         testGroup.add();
1848         testGroup.add() << CLRALLOPTS;
1849         testGroup.createTestRows();
1850
1851         testGroup.reset("testAll 2.2");
1852         testGroup.add() << SETALLOPTS;
1853         testGroup.add() << SETALLOPTS << SETALLOPTS;
1854         testGroup.createTestRows();
1855
1856         testGroup.reset("testAll 2.3");
1857         testGroup.add() << CLRALLOPTS;
1858         testGroup.add() << CLRALLOPTS << CLRALLOPTS;
1859         testGroup.createTestRows();
1860
1861         testGroup.reset("testAll 2.4");
1862         testGroup.add() << CLRALLOPTS;
1863         testGroup.add() << SETALLOPTS << CLRALLOPTS;
1864         testGroup.createTestRows();
1865
1866         testGroup.reset("testAll 2.5");
1867         testGroup.add() << SETALLOPTS;
1868         testGroup.add() << CLRALLOPTS << SETALLOPTS;
1869         testGroup.createTestRows();
1870
1871         testGroup.reset("testAll 2.6");
1872         testGroup.add() << SETALLOPTS;
1873         testGroup.add() << SETALLOPTS << CLRALLOPTS << SETALLOPTS;
1874         testGroup.createTestRows();
1875
1876         testGroup.reset("testAll 2.7");
1877         testGroup.add() << CLRALLOPTS;
1878         testGroup.add() << CLRALLOPTS << SETALLOPTS << CLRALLOPTS;
1879         testGroup.createTestRows();
1880
1881         for (int i = 0; i < 2; ++i) {
1882             QList<Operation *> setOptions = *setAllOptions.value(i == 1);
1883
1884             testGroup.reset("testAll 3.1");
1885             testGroup.add() << setOptions;
1886             testGroup.add() << SETPAGE(0) << setOptions;
1887             testGroup.add() << setOptions << SETPAGE(0);
1888             testGroup.add() << SETSTYLE(0) << setOptions;
1889             testGroup.add() << setOptions << SETSTYLE(0);
1890             testGroup.add() << setOptions << SETPAGE(0) << SETSTYLE(0);
1891             testGroup.add() << SETPAGE(0) << setOptions << SETSTYLE(0);
1892             testGroup.add() << SETPAGE(0) << SETSTYLE(0) << setOptions;
1893             testGroup.add() << setOptions << SETSTYLE(0) << SETPAGE(0);
1894             testGroup.add() << SETSTYLE(0) << setOptions << SETPAGE(0);
1895             testGroup.add() << SETSTYLE(0) << SETPAGE(0) << setOptions;
1896             testGroup.createTestRows();
1897         }
1898
1899         foreach (Operation *pageOp, pageOps) {
1900             testGroup.reset("testAll 4.1");
1901             testGroup.add() << pageOp;
1902             testGroup.add() << pageOp << pageOp;
1903             testGroup.createTestRows();
1904
1905             for (int i = 0; i < 2; ++i) {
1906                 QList<Operation *> optionOps = *setAllOptions.value(i == 1);
1907                 testGroup.reset("testAll 4.2");
1908                 testGroup.add() << optionOps << pageOp;
1909                 testGroup.add() << pageOp << optionOps;
1910                 testGroup.createTestRows();
1911
1912                 foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
1913                     Operation *optionOp = OPT(option, i == 1);
1914                     testGroup.reset("testAll 4.3");
1915                     testGroup.add() << optionOp << pageOp;
1916                     testGroup.add() << pageOp << optionOp;
1917                     testGroup.createTestRows();
1918                 }
1919             }
1920         }
1921
1922         foreach (Operation *styleOp, styleOps) {
1923             testGroup.reset("testAll 5.1");
1924             testGroup.add() << styleOp;
1925             testGroup.add() << styleOp << styleOp;
1926             testGroup.createTestRows();
1927
1928             for (int i = 0; i < 2; ++i) {
1929                 QList<Operation *> optionOps = *setAllOptions.value(i == 1);
1930                 testGroup.reset("testAll 5.2");
1931                 testGroup.add() << optionOps << styleOp;
1932                 testGroup.add() << styleOp << optionOps;
1933                 testGroup.createTestRows();
1934
1935                 foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
1936                     Operation *optionOp = OPT(option, i == 1);
1937                     testGroup.reset("testAll 5.3");
1938                     testGroup.add() << optionOp << styleOp;
1939                     testGroup.add() << styleOp << optionOp;
1940                     testGroup.createTestRows();
1941                 }
1942             }
1943         }
1944
1945         foreach (Operation *pageOp, pageOps) {
1946             foreach (Operation *styleOp, styleOps) {
1947
1948                 testGroup.reset("testAll 6.1");
1949                 testGroup.add() << pageOp;
1950                 testGroup.add() << pageOp << pageOp;
1951                 testGroup.createTestRows();
1952
1953                 testGroup.reset("testAll 6.2");
1954                 testGroup.add() << styleOp;
1955                 testGroup.add() << styleOp << styleOp;
1956                 testGroup.createTestRows();
1957
1958                 testGroup.reset("testAll 6.3");
1959                 testGroup.add() << pageOp << styleOp;
1960                 testGroup.add() << styleOp << pageOp;
1961                 testGroup.createTestRows();
1962
1963                 for (int i = 0; i < 2; ++i) {
1964                     QList<Operation *> optionOps = *setAllOptions.value(i == 1);
1965                     testGroup.reset("testAll 6.4");
1966                     testGroup.add() << optionOps << pageOp << styleOp;
1967                     testGroup.add() << pageOp << optionOps << styleOp;
1968                     testGroup.add() << pageOp << styleOp << optionOps;
1969                     testGroup.add() << optionOps << styleOp << pageOp;
1970                     testGroup.add() << styleOp << optionOps << pageOp;
1971                     testGroup.add() << styleOp << pageOp << optionOps;
1972                     testGroup.createTestRows();
1973
1974                     foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
1975                         Operation *optionOp = OPT(option, i == 1);
1976                         testGroup.reset("testAll 6.5");
1977                         testGroup.add() << optionOp << pageOp << styleOp;
1978                         testGroup.add() << pageOp << optionOp << styleOp;
1979                         testGroup.add() << pageOp << styleOp << optionOp;
1980                         testGroup.add() << optionOp << styleOp << pageOp;
1981                         testGroup.add() << styleOp << optionOp << pageOp;
1982                         testGroup.add() << styleOp << pageOp << optionOp;
1983                         testGroup.createTestRows();
1984                     }
1985                 }
1986             }
1987         }
1988
1989         testGroup.reset("testAll 7.1", TestGroup::NonEquality);
1990         testGroup.add() << SETPAGE(0);
1991         testGroup.add() << SETPAGE(1);
1992         testGroup.add() << SETPAGE(2);
1993         testGroup.createTestRows();
1994
1995         testGroup.reset("testAll 7.2", TestGroup::NonEquality);
1996         testGroup.add() << SETSTYLE(0);
1997         testGroup.add() << SETSTYLE(1);
1998         testGroup.add() << SETSTYLE(2);
1999         testGroup.createTestRows();
2000
2001         // more to follow ...
2002     }
2003
2004     // Creates a "small" number of interesting test rows.
2005     void createTestRows1()
2006     {
2007         testGroup.reset("test1 1");
2008         testGroup.add() << SETPAGE(0) << SETOPT(QWizard::HaveCustomButton3);
2009         testGroup.add() << SETOPT(QWizard::HaveCustomButton3);
2010         testGroup.createTestRows();
2011
2012         testGroup.reset("test1 2");
2013         testGroup.add() << SETOPT(QWizard::HaveFinishButtonOnEarlyPages) << SETPAGE(0);
2014         testGroup.add() << SETPAGE(0) << SETOPT(QWizard::HaveFinishButtonOnEarlyPages);
2015         testGroup.createTestRows();
2016
2017         testGroup.reset("test1 3");
2018         testGroup.add() << SETPAGE(2) << SETOPT(QWizard::HaveNextButtonOnLastPage);
2019         testGroup.add() << SETOPT(QWizard::HaveNextButtonOnLastPage) << SETPAGE(2);
2020         testGroup.createTestRows();
2021     }
2022 };
2023
2024 void tst_QWizard::combinations_data()
2025 {
2026     CombinationsTestData combTestData;
2027 //    combTestData.createAllTestRows();
2028     combTestData.createTestRows1();
2029
2030 //    qDebug() << "test rows:" << combTestData.nRows();
2031 }
2032
2033 void tst_QWizard::combinations()
2034 {
2035 #ifdef Q_OS_WINCE
2036     QSKIP("Too much memory usage for testing on CE emulator");
2037 #endif
2038
2039     QFETCH(bool, ref);
2040     QFETCH(bool, testEquality);
2041     QFETCH(QList<Operation *>, operations);
2042
2043     TestWizard wizard;
2044 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
2045     if (wizard.wizardStyle() == QWizard::AeroStyle)
2046         return; // ### TODO: passes/fails in a unpredictable way, so disable for now
2047 #endif
2048     wizard.applyOperations(operations);
2049     wizard.show(); // ### TODO: Required, but why? Should wizard.createImage() care?
2050
2051     static QImage refImage;
2052     static QSize refMinSize;
2053     static QString refDescr;
2054
2055     if (ref) {
2056         refImage = wizard.createImage();
2057         refMinSize = wizard.minimumSizeHint();
2058         refDescr = wizard.operationsDescription();
2059         return;
2060     }
2061
2062     QImage image = wizard.createImage();
2063
2064     bool minSizeTest = wizard.minimumSizeHint() != refMinSize;
2065     bool imageTest = image != refImage;
2066     QLatin1String otor("!=");
2067     QLatin1String reason("differ");
2068
2069     if (!testEquality) {
2070         minSizeTest = false; // the image test is sufficient!
2071         imageTest = !imageTest;
2072         otor = QLatin1String("==");
2073         reason = QLatin1String("are equal");
2074     }
2075
2076     if (minSizeTest)
2077         qDebug() << "minimum sizes" << reason.latin1() << ";" << wizard.minimumSizeHint()
2078                  << otor.latin1() << refMinSize;
2079
2080     if (imageTest)
2081         qDebug() << "images" << reason.latin1();
2082
2083     if (minSizeTest || imageTest) {
2084         qDebug() << "\t      row 0 operations:" << refDescr.toLatin1();
2085         qDebug() << "\tcurrent row operations:" << wizard.operationsDescription().toLatin1();
2086         QVERIFY(false);
2087     }
2088 }
2089
2090 class WizardPage : public QWizardPage
2091 {
2092     Q_OBJECT
2093     bool shown_;
2094     void showEvent(QShowEvent *) { shown_ = true; }
2095     void hideEvent(QHideEvent *) { shown_ = false; }
2096 public:
2097     WizardPage() : shown_(false) {}
2098     bool shown() const { return shown_; }
2099 };
2100
2101 class WizardPages
2102 {
2103     QList<WizardPage *> pages;
2104 public:
2105     void add(WizardPage *page) { pages << page; }
2106     QList<WizardPage *> all() const { return pages; }
2107     QList<WizardPage *> shown() const
2108     {
2109         QList<WizardPage *> result;
2110         foreach (WizardPage *page, pages)
2111             if (page->shown())
2112                 result << page;
2113         return result;
2114     }
2115 };
2116
2117 void tst_QWizard::showCurrentPageOnly()
2118 {
2119     QWizard wizard;
2120     WizardPages pages;
2121     for (int i = 0; i < 5; ++i) {
2122         pages.add(new WizardPage);
2123         wizard.addPage(pages.all().last());
2124     }
2125
2126     wizard.show();
2127
2128     QCOMPARE(pages.shown().count(), 1);
2129     QCOMPARE(pages.shown().first(), pages.all().first());
2130
2131     const int steps = 2;
2132     for (int i = 0; i < steps; ++i)
2133         wizard.next();
2134
2135     QCOMPARE(pages.shown().count(), 1);
2136     QCOMPARE(pages.shown().first(), pages.all().at(steps));
2137
2138     wizard.restart();
2139
2140     QCOMPARE(pages.shown().count(), 1);
2141     QCOMPARE(pages.shown().first(), pages.all().first());
2142 }
2143
2144 void tst_QWizard::setButtonText()
2145 {
2146     QWizard wizard;
2147     wizard.setWizardStyle(QWizard::ClassicStyle);
2148     QWizardPage* page1 = new QWizardPage;
2149     QWizardPage* page2 = new QWizardPage;
2150     wizard.addPage(page1);
2151     wizard.addPage(page2);
2152
2153     wizard.show();
2154     qApp->processEvents();
2155     QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
2156     QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
2157     QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
2158     QVERIFY(page2->buttonText(QWizard::NextButton).contains("Next"));
2159
2160     page2->setButtonText(QWizard::NextButton, "Page2");
2161     QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
2162     QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
2163     QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
2164     QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
2165
2166     wizard.next();
2167     qApp->processEvents();
2168     QCOMPARE(wizard.button(QWizard::NextButton)->text(), QString("Page2"));
2169     QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
2170     QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
2171     QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
2172
2173     wizard.back();
2174     qApp->processEvents();
2175     QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Next"));
2176     QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Next"));
2177     QVERIFY(page1->buttonText(QWizard::NextButton).contains("Next"));
2178     QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
2179
2180     wizard.setButtonText(QWizard::NextButton, "Wizard");
2181     QVERIFY(wizard.button(QWizard::NextButton)->text().contains("Wizard"));
2182     QCOMPARE(wizard.buttonText(QWizard::NextButton), QString("Wizard"));
2183     QCOMPARE(page1->buttonText(QWizard::NextButton), QString("Wizard"));
2184     QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
2185
2186     wizard.next();
2187     qApp->processEvents();
2188     QCOMPARE(wizard.button(QWizard::NextButton)->text(), QString("Page2"));
2189     QVERIFY(wizard.buttonText(QWizard::NextButton).contains("Wizard"));
2190     QCOMPARE(page1->buttonText(QWizard::NextButton), QString("Wizard"));
2191     QCOMPARE(page2->buttonText(QWizard::NextButton), QString("Page2"));
2192 }
2193
2194 void tst_QWizard::setCommitPage()
2195 {
2196     QWizard wizard;
2197     QWizardPage* page1 = new QWizardPage;
2198     QWizardPage* page2 = new QWizardPage;
2199     wizard.addPage(page1);
2200     wizard.addPage(page2);
2201     wizard.show();
2202     qApp->processEvents();
2203
2204     QVERIFY(!page1->isCommitPage());
2205     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
2206
2207     wizard.next();
2208     QVERIFY(wizard.button(QWizard::BackButton)->isEnabled());
2209
2210     page1->setCommitPage(true);
2211     QVERIFY(page1->isCommitPage());
2212
2213     wizard.back();
2214     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
2215
2216     wizard.next();
2217     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
2218
2219     page1->setCommitPage(false);
2220     QVERIFY(!page1->isCommitPage());
2221
2222     wizard.back();
2223     QVERIFY(!wizard.button(QWizard::BackButton)->isEnabled());
2224
2225     wizard.next();
2226     QVERIFY(wizard.button(QWizard::BackButton)->isEnabled());
2227
2228     // ### test relabeling of the Cancel button to "Close" once this is implemented
2229 }
2230
2231 void tst_QWizard::setWizardStyle()
2232 {
2233     QWizard wizard;
2234     wizard.addPage(new QWizardPage);
2235     wizard.show();
2236     qApp->processEvents();
2237
2238     // defaults
2239     const bool styleHintMatch =
2240         wizard.wizardStyle() ==
2241         QWizard::WizardStyle(wizard.style()->styleHint(QStyle::SH_WizardStyle, 0, &wizard));
2242 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
2243     QVERIFY(styleHintMatch || wizard.wizardStyle() == QWizard::AeroStyle);
2244 #else
2245     QVERIFY(styleHintMatch);
2246 #endif
2247
2248     // set/get consistency
2249     for (int wstyle = 0; wstyle < QWizard::NStyles; ++wstyle) {
2250         wizard.setWizardStyle((QWizard::WizardStyle)wstyle);
2251         QCOMPARE((int)wizard.wizardStyle(), wstyle);
2252     }
2253 }
2254
2255 void tst_QWizard::removePage()
2256 {
2257     QWizard wizard;
2258     QWizardPage *page0 = new QWizardPage;
2259     QWizardPage *page1 = new QWizardPage;
2260     QWizardPage *page2 = new QWizardPage;
2261     QWizardPage *page3 = new QWizardPage;
2262     QSignalSpy spy(&wizard, SIGNAL(pageRemoved(int)));
2263
2264     wizard.setPage(0, page0);
2265     wizard.setPage(1, page1);
2266     wizard.setPage(2, page2);
2267     wizard.setPage(3, page3);
2268
2269     wizard.restart();
2270     QCOMPARE(wizard.pageIds().size(), 4);
2271     QCOMPARE(wizard.visitedPages().size(), 1);
2272     QCOMPARE(spy.count(), 0);
2273
2274     // Removing a non-existent page
2275     wizard.removePage(4);
2276     QCOMPARE(wizard.pageIds().size(), 4);
2277     QCOMPARE(spy.count(), 0);
2278
2279     // Removing and then reinserting a page
2280     QCOMPARE(wizard.pageIds().size(), 4);
2281     QVERIFY(wizard.pageIds().contains(2));
2282     wizard.removePage(2);
2283     QCOMPARE(spy.count(), 1);
2284     QList<QVariant> arguments = spy.takeFirst();
2285     QCOMPARE(arguments.at(0).toInt(), 2);
2286     QCOMPARE(wizard.pageIds().size(), 3);
2287     QVERIFY(!wizard.pageIds().contains(2));
2288     wizard.setPage(2, page2);
2289     QCOMPARE(spy.count(), 0);
2290     QCOMPARE(wizard.pageIds().size(), 4);
2291     QVERIFY(wizard.pageIds().contains(2));
2292
2293     // Removing the same page twice
2294     wizard.removePage(2); // restore
2295     QCOMPARE(spy.count(), 1);
2296     arguments = spy.takeFirst();
2297     QCOMPARE(arguments.at(0).toInt(), 2);
2298     QCOMPARE(wizard.pageIds().size(), 3);
2299     QVERIFY(!wizard.pageIds().contains(2));
2300     wizard.removePage(2);
2301     QCOMPARE(spy.count(), 0);
2302     QCOMPARE(wizard.pageIds().size(), 3);
2303     QVERIFY(!wizard.pageIds().contains(2));
2304
2305     // Removing a page not in the history
2306     wizard.setPage(2, page2); // restore
2307     wizard.restart();
2308     wizard.next();
2309     QCOMPARE(wizard.visitedPages().size(), 2);
2310     QCOMPARE(wizard.currentPage(), page1);
2311     QCOMPARE(spy.count(), 0);
2312     wizard.removePage(2);
2313     QCOMPARE(spy.count(), 1);
2314     arguments = spy.takeFirst();
2315     QCOMPARE(arguments.at(0).toInt(), 2);
2316     QCOMPARE(wizard.visitedPages().size(), 2);
2317     QVERIFY(!wizard.pageIds().contains(2));
2318     QCOMPARE(wizard.currentPage(), page1);
2319
2320     // Removing a page in the history before the current page
2321     wizard.setPage(2, page2); // restore
2322     wizard.restart();
2323     wizard.next();
2324     QCOMPARE(spy.count(), 0);
2325     QCOMPARE(wizard.visitedPages().size(), 2);
2326     QCOMPARE(wizard.currentPage(), page1);
2327     wizard.removePage(0);
2328     QCOMPARE(spy.count(), 1);
2329     arguments = spy.takeFirst();
2330     QCOMPARE(arguments.at(0).toInt(), 0);
2331     QCOMPARE(wizard.visitedPages().size(), 1);
2332     QVERIFY(!wizard.visitedPages().contains(0));
2333     QVERIFY(!wizard.pageIds().contains(0));
2334     QCOMPARE(wizard.currentPage(), page1);
2335
2336     // Remove the current page which is not the first one in the history
2337     wizard.setPage(0, page0); // restore
2338     wizard.restart();
2339     wizard.next();
2340     QCOMPARE(spy.count(), 0);
2341     QCOMPARE(wizard.visitedPages().size(), 2);
2342     QCOMPARE(wizard.currentPage(), page1);
2343     wizard.removePage(1);
2344     QCOMPARE(spy.count(), 1);
2345     arguments = spy.takeFirst();
2346     QCOMPARE(arguments.at(0).toInt(), 1);
2347     QCOMPARE(wizard.visitedPages().size(), 1);
2348     QVERIFY(!wizard.visitedPages().contains(1));
2349     QVERIFY(!wizard.pageIds().contains(1));
2350     QCOMPARE(wizard.currentPage(), page0);
2351
2352     // Remove the current page which is the first (and only) one in the history
2353     wizard.removePage(0);
2354     QCOMPARE(spy.count(), 1);
2355     arguments = spy.takeFirst();
2356     QCOMPARE(arguments.at(0).toInt(), 0);
2357     QCOMPARE(wizard.visitedPages().size(), 1);
2358     QVERIFY(!wizard.visitedPages().contains(0));
2359     QCOMPARE(wizard.pageIds().size(), 2);
2360     QVERIFY(!wizard.pageIds().contains(0));
2361     QCOMPARE(wizard.currentPage(), page2);
2362     //
2363     wizard.removePage(2);
2364     QCOMPARE(spy.count(), 1);
2365     arguments = spy.takeFirst();
2366     QCOMPARE(arguments.at(0).toInt(), 2);
2367     QCOMPARE(wizard.visitedPages().size(), 1);
2368     QVERIFY(!wizard.visitedPages().contains(2));
2369     QCOMPARE(wizard.pageIds().size(), 1);
2370     QVERIFY(!wizard.pageIds().contains(2));
2371     QCOMPARE(wizard.currentPage(), page3);
2372     //
2373     wizard.removePage(3);
2374     QCOMPARE(spy.count(), 1);
2375     arguments = spy.takeFirst();
2376     QCOMPARE(arguments.at(0).toInt(), 3);
2377     QVERIFY(wizard.visitedPages().empty());
2378     QVERIFY(wizard.pageIds().empty());
2379     QCOMPARE(wizard.currentPage(), static_cast<QWizardPage *>(0));
2380 }
2381
2382 void tst_QWizard::sideWidget()
2383 {
2384     QWizard wizard;
2385
2386     wizard.setSideWidget(0);
2387     QVERIFY(wizard.sideWidget() == 0);
2388     QWidget *w1 = new QWidget(&wizard);
2389     wizard.setSideWidget(w1);
2390     QVERIFY(wizard.sideWidget() == w1);
2391     QWidget *w2 = new QWidget(&wizard);
2392     wizard.setSideWidget(w2);
2393     QVERIFY(wizard.sideWidget() == w2);
2394     QVERIFY(w1->parent() != 0);
2395     QCOMPARE(w1->window(), static_cast<QWidget *>(&wizard));
2396     QCOMPARE(w2->window(), static_cast<QWidget *>(&wizard));
2397     w1->setParent(0);
2398     wizard.setSideWidget(0);
2399     QVERIFY(wizard.sideWidget() == 0);
2400 }
2401
2402 void tst_QWizard::task161660_buttonSpacing()
2403 {
2404 #ifndef QT_NO_STYLE_PLASTIQUE
2405     QString origStyle = QApplication::style()->objectName();
2406     QApplication::setStyle(new QPlastiqueStyle);
2407     QWizard wizard;
2408     wizard.addPage(new QWizardPage);
2409     wizard.show();
2410     const QAbstractButton *finishButton = wizard.button(QWizard::FinishButton);
2411     const QAbstractButton *cancelButton = wizard.button(QWizard::CancelButton);
2412     const int spacing = cancelButton->geometry().left() - finishButton->geometry().right() - 1;
2413     QCOMPARE(spacing, wizard.style()->layoutSpacing(
2414                  QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal));
2415     QApplication::setStyle(origStyle);
2416 #endif
2417 }
2418
2419 class task177716_CommitPage : public QWizardPage
2420 {
2421     Q_OBJECT
2422 public:
2423     task177716_CommitPage()
2424     {
2425         setCommitPage(true);
2426         QVBoxLayout *layout = new QVBoxLayout;
2427         ledit = new QLineEdit(this);
2428         registerField("foo*", ledit);
2429         layout->addWidget(ledit);
2430         setLayout(layout);
2431     }
2432     QLineEdit *ledit;
2433 };
2434
2435 void tst_QWizard::task177716_disableCommitButton()
2436 {
2437     QWizard wizard;
2438     task177716_CommitPage *commitPage = new task177716_CommitPage;
2439     wizard.addPage(commitPage);
2440     // the following page must be there to prevent the first page from replacing the Commit button
2441     // with the Finish button:
2442     wizard.addPage(new QWizardPage);
2443     wizard.show();
2444     QVERIFY(!wizard.button(QWizard::CommitButton)->isEnabled());
2445     commitPage->ledit->setText("some non-empty text");
2446     QVERIFY(wizard.button(QWizard::CommitButton)->isEnabled());
2447     commitPage->ledit->setText("");
2448     QVERIFY(!wizard.button(QWizard::CommitButton)->isEnabled());
2449 }
2450
2451 class WizardPage_task183550 : public QWizardPage
2452 {
2453 public:
2454     WizardPage_task183550(QWidget *parent = 0)
2455         : QWizardPage(parent)
2456         , treeWidget(new QTreeWidget)
2457         , verticalPolicy(QSizePolicy::MinimumExpanding) {}
2458     void enableVerticalExpansion() { verticalPolicy = QSizePolicy::MinimumExpanding; }
2459     void disableVerticalExpansion() { verticalPolicy = QSizePolicy::Preferred; }
2460     int treeWidgetHeight() const { return treeWidget->height(); }
2461     int treeWidgetSizeHintHeight() const { return treeWidget->sizeHint().height(); }
2462
2463 private:
2464     QTreeWidget *treeWidget;
2465     QSizePolicy::Policy verticalPolicy;
2466
2467     void initializePage()
2468     {
2469         if (layout())
2470             delete layout();
2471         if (treeWidget)
2472             delete treeWidget;
2473
2474         QLayout *layout_ = new QVBoxLayout(this);
2475         layout_->addWidget(treeWidget = new QTreeWidget);
2476  
2477         QSizePolicy policy = sizePolicy();
2478         policy.setVerticalPolicy(verticalPolicy);
2479         treeWidget->setSizePolicy(policy);
2480     }
2481 };
2482
2483 void tst_QWizard::task183550_stretchFactor()
2484 {
2485     QWizard wizard;
2486     WizardPage_task183550 *page1 = new WizardPage_task183550;
2487     WizardPage_task183550 *page2 = new WizardPage_task183550;
2488     wizard.addPage(page1);
2489     wizard.addPage(page2);
2490     wizard.resize(500, 2 * page2->treeWidgetSizeHintHeight());
2491     wizard.show();
2492
2493     QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page1));
2494
2495     // ----
2496     page2->disableVerticalExpansion();
2497     wizard.next();
2498     QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page2));
2499     QVERIFY(page2->treeWidgetHeight() == page2->treeWidgetSizeHintHeight());
2500
2501     wizard.back();
2502     QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page1));
2503
2504     // ----
2505     page2->enableVerticalExpansion();
2506     wizard.next();
2507     QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page2));
2508     QVERIFY(page2->treeWidgetHeight() > page2->treeWidgetSizeHintHeight());
2509
2510     wizard.back();
2511     QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page1));
2512
2513     // ----
2514     page2->disableVerticalExpansion();
2515     wizard.next();
2516     QCOMPARE(wizard.currentPage(), static_cast<QWizardPage*>(page2));
2517     QVERIFY(page2->treeWidgetHeight() == page2->treeWidgetSizeHintHeight());
2518 }
2519
2520 void tst_QWizard::task161658_alignments()
2521 {
2522     QWizard wizard;
2523     wizard.setWizardStyle(QWizard::MacStyle);
2524
2525     QWizardPage page;
2526     page.setTitle("Title");
2527     page.setSubTitle("SUBTITLE#:  The subtitle bust be aligned with the rest of the widget");
2528
2529     QLabel label1("Field:");
2530     QLineEdit lineEdit1;
2531     QGridLayout *layout = new QGridLayout;
2532     layout->addWidget(&label1, 0, 0);
2533     layout->addWidget(&lineEdit1, 0, 1);
2534     page.setLayout(layout);
2535
2536     int idx = wizard.addPage(&page);
2537     wizard.setStartId(idx);
2538     wizard.show();
2539     QTest::qWait(100);
2540
2541     foreach (QLabel *subtitleLabel, qFindChildren<QLabel *>(&wizard)) {
2542         if (subtitleLabel->text().startsWith("SUBTITLE#")) {
2543             QCOMPARE(lineEdit1.mapToGlobal(lineEdit1.contentsRect().bottomRight()).x(),
2544                      subtitleLabel->mapToGlobal(subtitleLabel->contentsRect().bottomRight()).x());
2545             return;
2546         }
2547     }
2548     QFAIL("Subtitle label not found");
2549 }
2550
2551 void tst_QWizard::task177022_setFixedSize()
2552 {
2553     int width = 300;
2554     int height = 200;
2555     QWizard wiz;
2556     QWizardPage page1;
2557     QWizardPage page2;
2558     int page1_id = wiz.addPage(&page1);
2559     int page2_id = wiz.addPage(&page2);
2560     wiz.setFixedSize(width, height);
2561     if (wiz.wizardStyle() == QWizard::AeroStyle)
2562         QEXPECT_FAIL("", "this probably relates to non-client area hack for AeroStyle titlebar "
2563                      "effect; not sure if it qualifies as a bug or not", Continue);
2564     QCOMPARE(wiz.size(), QSize(width, height));
2565     QCOMPARE(wiz.minimumWidth(), width);
2566     QCOMPARE(wiz.minimumHeight(), height);
2567     QCOMPARE(wiz.maximumWidth(), width);
2568     QCOMPARE(wiz.maximumHeight(), height);
2569
2570     wiz.show();
2571     QTest::qWait(100);
2572     QCOMPARE(wiz.size(), QSize(width, height));
2573     QCOMPARE(wiz.minimumWidth(), width);
2574     QCOMPARE(wiz.minimumHeight(), height);
2575     QCOMPARE(wiz.maximumWidth(), width);
2576     QCOMPARE(wiz.maximumHeight(), height);
2577
2578     wiz.next();
2579     QTest::qWait(100);
2580     QCOMPARE(wiz.size(), QSize(width, height));
2581     QCOMPARE(wiz.minimumWidth(), width);
2582     QCOMPARE(wiz.minimumHeight(), height);
2583     QCOMPARE(wiz.maximumWidth(), width);
2584     QCOMPARE(wiz.maximumHeight(), height);
2585
2586     wiz.removePage(page1_id);
2587     wiz.removePage(page2_id);
2588 }
2589
2590 void tst_QWizard::task248107_backButton()
2591 {
2592     QWizard wizard;
2593     QWizardPage page1;
2594     QWizardPage page2;
2595     QWizardPage page3;
2596     QWizardPage page4;
2597     wizard.addPage(&page1);
2598     wizard.addPage(&page2);
2599     wizard.addPage(&page3);
2600     wizard.addPage(&page4);
2601
2602     wizard.show();
2603     QTest::qWait(100);
2604     QCOMPARE(wizard.currentPage(), &page1);
2605
2606     QTest::mouseClick(wizard.button(QWizard::NextButton), Qt::LeftButton);
2607     QCOMPARE(wizard.currentPage(), &page2);
2608
2609     QTest::mouseClick(wizard.button(QWizard::NextButton), Qt::LeftButton);
2610     QCOMPARE(wizard.currentPage(), &page3);
2611
2612     QTest::mouseClick(wizard.button(QWizard::NextButton), Qt::LeftButton);
2613     QCOMPARE(wizard.currentPage(), &page4);
2614
2615     QTest::mouseClick(wizard.button(QWizard::BackButton), Qt::LeftButton);
2616     QCOMPARE(wizard.currentPage(), &page3);
2617
2618     QTest::mouseClick(wizard.button(QWizard::BackButton), Qt::LeftButton);
2619     QCOMPARE(wizard.currentPage(), &page2);
2620
2621     QTest::mouseClick(wizard.button(QWizard::BackButton), Qt::LeftButton);
2622     QCOMPARE(wizard.currentPage(), &page1);
2623 }
2624
2625 class WizardPage_task255350 : public QWizardPage
2626 {
2627 public:
2628     QLineEdit *lineEdit;
2629     WizardPage_task255350()
2630         : lineEdit(new QLineEdit)
2631     {
2632         registerField("dummy*", lineEdit);
2633     }
2634 };
2635
2636 void tst_QWizard::task255350_fieldObjectDestroyed()
2637 {
2638     QWizard wizard;
2639     WizardPage_task255350 *page = new WizardPage_task255350;
2640     int id = wizard.addPage(page);
2641     delete page->lineEdit;
2642     wizard.removePage(id); // don't crash!
2643     delete page;
2644 }
2645
2646 QTEST_MAIN(tst_QWizard)
2647 #include "tst_qwizard.moc"