• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kleopatra

  • sources
  • kde-4.12
  • kdepim
  • kleopatra
  • utils
qwizard.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qwizard.h"
43 
44 #include "qabstractspinbox.h"
45 #include "qalgorithms.h"
46 #include "qapplication.h"
47 #include "qboxlayout.h"
48 #include "qlayoutitem.h"
49 #include "qdesktopwidget.h"
50 #include "qevent.h"
51 #include "qframe.h"
52 #include "qlabel.h"
53 #include "qlineedit.h"
54 #include "qpainter.h"
55 #include "qpushbutton.h"
56 #include "qset.h"
57 #include "qstyle.h"
58 #include "qvarlengtharray.h"
59 #if defined(Q_WS_MAC)
60 #include "private/qt_mac_p.h"
61 #include "qlibrary.h"
62 #elif !defined(QT_NO_STYLE_WINDOWSVISTA)
63 #include "qwizard_win_p.h"
64 #include "qtimer.h"
65 #endif
66 
67 #include "private/qdialog_p.h"
68 #include <qdebug.h>
69 
70 #include <string.h> // for memset()
71 
72 #ifdef QT_SOFTKEYS_ENABLED
73 #include "qaction.h"
74 #endif
75 
76 // These fudge terms were needed a few places to obtain pixel-perfect results
77 const int GapBetweenLogoAndRightEdge = 5;
78 const int ModernHeaderTopMargin = 2;
79 const int ClassicHMargin = 4;
80 const int MacButtonTopMargin = 13;
81 const int MacLayoutLeftMargin = 20;
82 //const int MacLayoutTopMargin = 14; // Unused. Save some space and avoid warning.
83 const int MacLayoutRightMargin = 20;
84 const int MacLayoutBottomMargin = 17;
85 
86 static void changeSpacerSize(QLayout *layout, int index, int width, int height)
87 {
88  QSpacerItem *spacer = layout->itemAt(index)->spacerItem();
89  if (!spacer)
90  return;
91  spacer->changeSize(width, height);
92 }
93 
94 static QWidget *iWantTheFocus(QWidget *ancestor)
95 {
96  const int MaxIterations = 100;
97 
98  QWidget *candidate = ancestor;
99  for (int i = 0; i < MaxIterations; ++i) {
100  candidate = candidate->nextInFocusChain();
101  if (!candidate)
102  break;
103 
104  if (candidate->focusPolicy() & Qt::TabFocus) {
105  if (candidate != ancestor && ancestor->isAncestorOf(candidate))
106  return candidate;
107  }
108  }
109  return 0;
110 }
111 
112 static bool objectInheritsXAndXIsCloserThanY(const QObject *object, const QByteArray &classX,
113  const QByteArray &classY)
114 {
115  const QMetaObject *metaObject = object->metaObject();
116  while (metaObject) {
117  if (metaObject->className() == classX)
118  return true;
119  if (metaObject->className() == classY)
120  return false;
121  metaObject = metaObject->superClass();
122  }
123  return false;
124 }
125 
126 const int NFallbackDefaultProperties = 7;
127 
128 const struct {
129  const char *className;
130  const char *property;
131  const char *changedSignal;
132 } fallbackProperties[NFallbackDefaultProperties] = {
133  // If you modify this list, make sure to update the documentation (and the auto test)
134  { "QAbstractButton", "checked", SIGNAL(toggled(bool)) },
135  { "QAbstractSlider", "value", SIGNAL(valueChanged(int)) },
136  { "QComboBox", "currentIndex", SIGNAL(currentIndexChanged(int)) },
137  { "QDateTimeEdit", "dateTime", SIGNAL(dateTimeChanged(QDateTime)) },
138  { "QLineEdit", "text", SIGNAL(textChanged(QString)) },
139  { "QListWidget", "currentRow", SIGNAL(currentRowChanged(int)) },
140  { "QSpinBox", "value", SIGNAL(valueChanged(int)) }
141 };
142 
143 class QWizardDefaultProperty
144 {
145 public:
146  QByteArray className;
147  QByteArray property;
148  QByteArray changedSignal;
149 
150  inline QWizardDefaultProperty() {}
151  inline QWizardDefaultProperty(const char *className, const char *property,
152  const char *changedSignal)
153  : className(className), property(property), changedSignal(changedSignal) {}
154 };
155 
156 class QWizardField
157 {
158 public:
159  inline QWizardField() {}
160  QWizardField(QWizardPage *page, const QString &spec, QObject *object, const char *property,
161  const char *changedSignal);
162 
163  void resolve(const QVector<QWizardDefaultProperty> &defaultPropertyTable);
164  void findProperty(const QWizardDefaultProperty *properties, int propertyCount);
165 
166  QWizardPage *page;
167  QString name;
168  bool mandatory;
169  QObject *object;
170  QByteArray property;
171  QByteArray changedSignal;
172  QVariant initialValue;
173 };
174 
175 QWizardField::QWizardField(QWizardPage *page, const QString &spec, QObject *object,
176  const char *property, const char *changedSignal)
177  : page(page), name(spec), mandatory(false), object(object), property(property),
178  changedSignal(changedSignal)
179 {
180  if (name.endsWith(QLatin1Char('*'))) {
181  name.chop(1);
182  mandatory = true;
183  }
184 }
185 
186 void QWizardField::resolve(const QVector<QWizardDefaultProperty> &defaultPropertyTable)
187 {
188  if (property.isEmpty())
189  findProperty(defaultPropertyTable.constData(), defaultPropertyTable.count());
190  initialValue = object->property(property);
191 }
192 
193 void QWizardField::findProperty(const QWizardDefaultProperty *properties, int propertyCount)
194 {
195  QByteArray className;
196 
197  for (int i = 0; i < propertyCount; ++i) {
198  if (objectInheritsXAndXIsCloserThanY(object, properties[i].className, className)) {
199  className = properties[i].className;
200  property = properties[i].property;
201  changedSignal = properties[i].changedSignal;
202  }
203  }
204 }
205 
206 class QWizardLayoutInfo
207 {
208 public:
209  inline QWizardLayoutInfo()
210  : topLevelMarginLeft(-1), topLevelMarginRight(-1), topLevelMarginTop(-1),
211  topLevelMarginBottom(-1), childMarginLeft(-1), childMarginRight(-1),
212  childMarginTop(-1), childMarginBottom(-1), hspacing(-1), vspacing(-1),
213  wizStyle(QWizard::ClassicStyle), header(false), watermark(false), title(false),
214  subTitle(false), extension(false), sideWidget(false) {}
215 
216  int topLevelMarginLeft;
217  int topLevelMarginRight;
218  int topLevelMarginTop;
219  int topLevelMarginBottom;
220  int childMarginLeft;
221  int childMarginRight;
222  int childMarginTop;
223  int childMarginBottom;
224  int hspacing;
225  int vspacing;
226  int buttonSpacing;
227  QWizard::WizardStyle wizStyle;
228  bool header;
229  bool watermark;
230  bool title;
231  bool subTitle;
232  bool extension;
233  bool sideWidget;
234 
235  bool operator==(const QWizardLayoutInfo &other);
236  inline bool operator!=(const QWizardLayoutInfo &other) { return !operator==(other); }
237 };
238 
239 bool QWizardLayoutInfo::operator==(const QWizardLayoutInfo &other)
240 {
241  return topLevelMarginLeft == other.topLevelMarginLeft
242  && topLevelMarginRight == other.topLevelMarginRight
243  && topLevelMarginTop == other.topLevelMarginTop
244  && topLevelMarginBottom == other.topLevelMarginBottom
245  && childMarginLeft == other.childMarginLeft
246  && childMarginRight == other.childMarginRight
247  && childMarginTop == other.childMarginTop
248  && childMarginBottom == other.childMarginBottom
249  && hspacing == other.hspacing
250  && vspacing == other.vspacing
251  && buttonSpacing == other.buttonSpacing
252  && wizStyle == other.wizStyle
253  && header == other.header
254  && watermark == other.watermark
255  && title == other.title
256  && subTitle == other.subTitle
257  && extension == other.extension
258  && sideWidget == other.sideWidget;
259 }
260 
261 class QWizardHeader : public QWidget
262 {
263 public:
264  enum RulerType { Ruler };
265 
266  inline QWizardHeader(RulerType /* ruler */, QWidget *parent = 0)
267  : QWidget(parent) { setFixedHeight(2); }
268  QWizardHeader(QWidget *parent = 0);
269 
270  void setup(const QWizardLayoutInfo &info, const QString &title,
271  const QString &subTitle, const QPixmap &logo, const QPixmap &banner,
272  Qt::TextFormat titleFormat, Qt::TextFormat subTitleFormat);
273 
274 protected:
275  void paintEvent(QPaintEvent *event);
276 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
277 private:
278  bool vistaDisabled() const;
279 #endif
280 private:
281  QLabel *titleLabel;
282  QLabel *subTitleLabel;
283  QLabel *logoLabel;
284  QGridLayout *layout;
285  QPixmap bannerPixmap;
286 };
287 
288 QWizardHeader::QWizardHeader(QWidget *parent)
289  : QWidget(parent)
290 {
291  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
292  setBackgroundRole(QPalette::Base);
293 
294  titleLabel = new QLabel(this);
295  titleLabel->setBackgroundRole(QPalette::Base);
296 
297  subTitleLabel = new QLabel(this);
298  subTitleLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
299  subTitleLabel->setWordWrap(true);
300 
301  logoLabel = new QLabel(this);
302 
303  QFont font = titleLabel->font();
304  font.setBold(true);
305  titleLabel->setFont(font);
306 
307  layout = new QGridLayout(this);
308  layout->setMargin(0);
309  layout->setSpacing(0);
310 
311  layout->setRowMinimumHeight(3, 1);
312  layout->setRowStretch(4, 1);
313 
314  layout->setColumnStretch(2, 1);
315  layout->setColumnMinimumWidth(4, 2 * GapBetweenLogoAndRightEdge);
316  layout->setColumnMinimumWidth(6, GapBetweenLogoAndRightEdge);
317 
318  layout->addWidget(titleLabel, 2, 1, 1, 2);
319  layout->addWidget(subTitleLabel, 4, 2);
320  layout->addWidget(logoLabel, 1, 5, 5, 1);
321 }
322 
323 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
324 bool QWizardHeader::vistaDisabled() const
325 {
326  bool styleDisabled = false;
327  QWizard *wiz = parentWidget() ? qobject_cast <QWizard *>(parentWidget()->parentWidget()) : 0;
328  if (wiz) {
329  // Designer dosen't support the Vista style for Wizards. This property is used to turn
330  // off the Vista style.
331  const QVariant v = wiz->property("_q_wizard_vista_off");
332  styleDisabled = v.isValid() && v.toBool();
333  }
334  return styleDisabled;
335 }
336 #endif
337 
338 void QWizardHeader::setup(const QWizardLayoutInfo &info, const QString &title,
339  const QString &subTitle, const QPixmap &logo, const QPixmap &banner,
340  Qt::TextFormat titleFormat, Qt::TextFormat subTitleFormat)
341 {
342  bool modern = ((info.wizStyle == QWizard::ModernStyle)
343 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
344  || ((info.wizStyle == QWizard::AeroStyle
345  && QVistaHelper::vistaState() == QVistaHelper::Classic) || vistaDisabled())
346 #endif
347  );
348 
349  layout->setRowMinimumHeight(0, modern ? ModernHeaderTopMargin : 0);
350  layout->setRowMinimumHeight(1, modern ? info.topLevelMarginTop - ModernHeaderTopMargin - 1 : 0);
351  layout->setRowMinimumHeight(6, (modern ? 3 : GapBetweenLogoAndRightEdge) + 2);
352 
353  int minColumnWidth0 = modern ? info.topLevelMarginLeft + info.topLevelMarginRight : 0;
354  int minColumnWidth1 = modern ? info.topLevelMarginLeft + info.topLevelMarginRight + 1
355  : info.topLevelMarginLeft + ClassicHMargin;
356  layout->setColumnMinimumWidth(0, minColumnWidth0);
357  layout->setColumnMinimumWidth(1, minColumnWidth1);
358 
359  titleLabel->setTextFormat(titleFormat);
360  titleLabel->setText(title);
361  logoLabel->setPixmap(logo);
362 
363  subTitleLabel->setTextFormat(subTitleFormat);
364  subTitleLabel->setText(QLatin1String("Pq\nPq"));
365  int desiredSubTitleHeight = subTitleLabel->sizeHint().height();
366  subTitleLabel->setText(subTitle);
367 
368  if (modern) {
369  bannerPixmap = banner;
370  } else {
371  bannerPixmap = QPixmap();
372  }
373 
374  if (bannerPixmap.isNull()) {
375  /*
376  There is no widthForHeight() function, so we simulate it with a loop.
377  */
378  int candidateSubTitleWidth = qMin(512, 2 * QApplication::desktop()->width() / 3);
379  int delta = candidateSubTitleWidth >> 1;
380  while (delta > 0) {
381  if (subTitleLabel->heightForWidth(candidateSubTitleWidth - delta)
382  <= desiredSubTitleHeight)
383  candidateSubTitleWidth -= delta;
384  delta >>= 1;
385  }
386 
387  subTitleLabel->setMinimumSize(candidateSubTitleWidth, desiredSubTitleHeight);
388 
389  QSize size = layout->totalMinimumSize();
390  setMinimumSize(size);
391  setMaximumSize(QWIDGETSIZE_MAX, size.height());
392  } else {
393  subTitleLabel->setMinimumSize(0, 0);
394  setFixedSize(banner.size() + QSize(0, 2));
395  }
396  updateGeometry();
397 }
398 
399 void QWizardHeader::paintEvent(QPaintEvent * /* event */)
400 {
401  QPainter painter(this);
402  painter.drawPixmap(0, 0, bannerPixmap);
403 
404  int x = width() - 2;
405  int y = height() - 2;
406  const QPalette &pal = palette();
407  painter.setPen(pal.mid().color());
408  painter.drawLine(0, y, x, y);
409  painter.setPen(pal.base().color());
410  painter.drawPoint(x + 1, y);
411  painter.drawLine(0, y + 1, x + 1, y + 1);
412 }
413 
414 // We save one vtable by basing QWizardRuler on QWizardHeader
415 class QWizardRuler : public QWizardHeader
416 {
417 public:
418  inline QWizardRuler(QWidget *parent = 0)
419  : QWizardHeader(Ruler, parent) {}
420 };
421 
422 class QWatermarkLabel : public QLabel
423 {
424 public:
425  QWatermarkLabel(QWidget *parent, QWidget *sideWidget) : QLabel(parent), m_sideWidget(sideWidget) {
426  m_layout = new QVBoxLayout(this);
427  if (m_sideWidget)
428  m_layout->addWidget(m_sideWidget);
429  }
430 
431  QSize minimumSizeHint() const {
432  if (!pixmap() && !pixmap()->isNull())
433  return pixmap()->size();
434  return QFrame::minimumSizeHint();
435  }
436 
437  void setSideWidget(QWidget *widget) {
438  if (m_sideWidget == widget)
439  return;
440  if (m_sideWidget) {
441  m_layout->removeWidget(m_sideWidget);
442  m_sideWidget->hide();
443  }
444  m_sideWidget = widget;
445  if (m_sideWidget)
446  m_layout->addWidget(m_sideWidget);
447  }
448  QWidget *sideWidget() const {
449  return m_sideWidget;
450  }
451 private:
452  QVBoxLayout *m_layout;
453  QWidget *m_sideWidget;
454 };
455 
456 class QWizardPagePrivate : public QWidgetPrivate
457 {
458  Q_DECLARE_PUBLIC(QWizardPage)
459 
460 public:
461  enum TriState { Tri_Unknown = -1, Tri_False, Tri_True };
462 
463  inline QWizardPagePrivate()
464  : wizard(0), completeState(Tri_Unknown), explicitlyFinal(false), commit(false) {}
465 
466  bool cachedIsComplete() const;
467  void _q_maybeEmitCompleteChanged();
468  void _q_updateCachedCompleteState();
469 
470  QWizard *wizard;
471  QString title;
472  QString subTitle;
473  QPixmap pixmaps[QWizard::NPixmaps];
474  QVector<QWizardField> pendingFields;
475  mutable TriState completeState;
476  bool explicitlyFinal;
477  bool commit;
478  QMap<int, QString> buttonCustomTexts;
479 };
480 
481 bool QWizardPagePrivate::cachedIsComplete() const
482 {
483  Q_Q(const QWizardPage);
484  if (completeState == Tri_Unknown)
485  completeState = q->isComplete() ? Tri_True : Tri_False;
486  return completeState == Tri_True;
487 }
488 
489 void QWizardPagePrivate::_q_maybeEmitCompleteChanged()
490 {
491  Q_Q(QWizardPage);
492  TriState newState = q->isComplete() ? Tri_True : Tri_False;
493  if (newState != completeState)
494  emit q->completeChanged();
495 }
496 
497 void QWizardPagePrivate::_q_updateCachedCompleteState()
498 {
499  Q_Q(QWizardPage);
500  completeState = q->isComplete() ? Tri_True : Tri_False;
501 }
502 
503 class QWizardAntiFlickerWidget : public QWidget
504 {
505  QWizard *wizard;
506  QWizardPrivate *wizardPrivate;
507 public:
508  QWizardAntiFlickerWidget(QWidget *parent, QWizard *wizard, QWizardPrivate *wizardPrivate)
509  : QWidget(parent)
510  , wizard(wizard)
511  , wizardPrivate(wizardPrivate) {}
512 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
513 protected:
514  void paintEvent(QPaintEvent *);
515 #endif
516 };
517 
518 class QWizardPrivate : public QDialogPrivate
519 {
520  Q_DECLARE_PUBLIC(QWizard)
521 
522 public:
523  typedef QMap<int, QWizardPage *> PageMap;
524 
525  enum Direction {
526  Backward,
527  Forward
528  };
529 
530  inline QWizardPrivate()
531  : start(-1)
532  , startSetByUser(false)
533  , current(-1)
534  , canContinue(false)
535  , canFinish(false)
536  , disableUpdatesCount(0)
537  , opts(0)
538  , buttonsHaveCustomLayout(false)
539  , titleFmt(Qt::AutoText)
540  , subTitleFmt(Qt::AutoText)
541  , placeholderWidget1(0)
542  , placeholderWidget2(0)
543  , headerWidget(0)
544  , watermarkLabel(0)
545  , sideWidget(0)
546  , titleLabel(0)
547  , subTitleLabel(0)
548  , bottomRuler(0)
549 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
550  , vistaInitPending(false)
551  , vistaState(QVistaHelper::Dirty)
552  , vistaStateChanged(false)
553  , inHandleAeroStyleChange(false)
554 #endif
555  , minimumWidth(0)
556  , minimumHeight(0)
557  , maximumWidth(QWIDGETSIZE_MAX)
558  , maximumHeight(QWIDGETSIZE_MAX)
559  {
560  for (int i = 0; i < QWizard::NButtons; ++i) {
561  btns[i] = 0;
562 #ifdef QT_SOFTKEYS_ENABLED
563  softKeys[i] = 0;
564 #endif
565  }
566 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
567  if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
568  && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
569  vistaInitPending = true;
570 #endif
571  }
572 
573  void init();
574  void reset();
575  void cleanupPagesNotInHistory();
576  void addField(const QWizardField &field);
577  void removeFieldAt(int index);
578  void switchToPage(int newId, Direction direction);
579  QWizardLayoutInfo layoutInfoForCurrentPage();
580  void recreateLayout(const QWizardLayoutInfo &info);
581  void updateLayout();
582  void updateMinMaxSizes(const QWizardLayoutInfo &info);
583  void updateCurrentPage();
584  bool ensureButton(QWizard::WizardButton which) const;
585  void connectButton(QWizard::WizardButton which) const;
586  void updateButtonTexts();
587  void updateButtonLayout();
588  void setButtonLayout(const QWizard::WizardButton *array, int size);
589  bool buttonLayoutContains(QWizard::WizardButton which);
590  void updatePixmap(QWizard::WizardPixmap which);
591 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
592  bool vistaDisabled() const;
593  bool isVistaThemeEnabled(QVistaHelper::VistaState state) const;
594  void handleAeroStyleChange();
595 #endif
596  bool isVistaThemeEnabled() const;
597  void disableUpdates();
598  void enableUpdates();
599  void _q_emitCustomButtonClicked();
600  void _q_updateButtonStates();
601  void _q_handleFieldObjectDestroyed(QObject *);
602  void setStyle(QStyle *style);
603 #ifdef Q_WS_MAC
604  static QPixmap findDefaultBackgroundPixmap();
605 #endif
606 
607  PageMap pageMap;
608  QVector<QWizardField> fields;
609  QMap<QString, int> fieldIndexMap;
610  QVector<QWizardDefaultProperty> defaultPropertyTable;
611  QList<int> history;
612  QSet<int> initialized; // ### remove and move bit to QWizardPage?
613  int start;
614  bool startSetByUser;
615  int current;
616  bool canContinue;
617  bool canFinish;
618  QWizardLayoutInfo layoutInfo;
619  int disableUpdatesCount;
620 
621  QWizard::WizardStyle wizStyle;
622  QWizard::WizardOptions opts;
623  QMap<int, QString> buttonCustomTexts;
624  bool buttonsHaveCustomLayout;
625  QList<QWizard::WizardButton> buttonsCustomLayout;
626  Qt::TextFormat titleFmt;
627  Qt::TextFormat subTitleFmt;
628  mutable QPixmap defaultPixmaps[QWizard::NPixmaps];
629 
630  union {
631  // keep in sync with QWizard::WizardButton
632  mutable struct {
633  QAbstractButton *back;
634  QAbstractButton *next;
635  QAbstractButton *commit;
636  QAbstractButton *finish;
637  QAbstractButton *cancel;
638  QAbstractButton *help;
639  } btn;
640  mutable QAbstractButton *btns[QWizard::NButtons];
641  };
642  QWidget *topWidget;
643  QWizardAntiFlickerWidget *antiFlickerWidget;
644  QWidget *placeholderWidget1;
645  QWidget *placeholderWidget2;
646  QWizardHeader *headerWidget;
647  QWatermarkLabel *watermarkLabel;
648  QWidget *sideWidget;
649  QFrame *pageFrame;
650  QLabel *titleLabel;
651  QLabel *subTitleLabel;
652  QWizardRuler *bottomRuler;
653 #ifdef QT_SOFTKEYS_ENABLED
654  mutable QAction *softKeys[QWizard::NButtons];
655 #endif
656 
657  QVBoxLayout *pageVBoxLayout;
658  QHBoxLayout *buttonLayout;
659  QGridLayout *mainLayout;
660 
661 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
662  QVistaHelper *vistaHelper;
663  bool vistaInitPending;
664  QVistaHelper::VistaState vistaState;
665  bool vistaStateChanged;
666  bool inHandleAeroStyleChange;
667 #endif
668  int minimumWidth;
669  int minimumHeight;
670  int maximumWidth;
671  int maximumHeight;
672 };
673 
674 static QString buttonDefaultText(int wstyle, int which, const QWizardPrivate *wizardPrivate)
675 {
676 #if defined(QT_NO_STYLE_WINDOWSVISTA)
677  Q_UNUSED(wizardPrivate);
678 #endif
679  const bool macStyle = (wstyle == QWizard::MacStyle);
680  switch (which) {
681  case QWizard::BackButton:
682  return macStyle ? QWizard::tr("Go Back") : QWizard::tr("< &Back");
683  case QWizard::NextButton:
684  if (macStyle)
685  return QWizard::tr("Continue");
686  else
687  return wizardPrivate->isVistaThemeEnabled()
688  ? QWizard::tr("&Next") : QWizard::tr("&Next >");
689  case QWizard::CommitButton:
690  return QWizard::tr("Commit");
691  case QWizard::FinishButton:
692  return macStyle ? QWizard::tr("Done") : QWizard::tr("&Finish");
693  case QWizard::CancelButton:
694  return QWizard::tr("Cancel");
695  case QWizard::HelpButton:
696  return macStyle ? QWizard::tr("Help") : QWizard::tr("&Help");
697  default:
698  return QString();
699  }
700 }
701 
702 void QWizardPrivate::init()
703 {
704  Q_Q(QWizard);
705 
706  QScrollArea *scrollArea = new QScrollArea(q);
707  antiFlickerWidget = new QWizardAntiFlickerWidget(scrollArea, q, this);
708  scrollArea->setWidget(antiFlickerWidget);
709  scrollArea->setWidgetResizable(true);
710  scrollArea->setFrameStyle(QFrame::NoFrame);
711  topWidget = scrollArea;
712 
713  wizStyle = QWizard::WizardStyle(q->style()->styleHint(QStyle::SH_WizardStyle, 0, q));
714  if (wizStyle == QWizard::MacStyle) {
715  opts = (QWizard::NoDefaultButton | QWizard::NoCancelButton);
716  } else if (wizStyle == QWizard::ModernStyle) {
717  opts = QWizard::HelpButtonOnRight;
718  }
719 
720 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
721  vistaHelper = new QVistaHelper(q);
722 #endif
723 
724  // create these buttons right away; create the other buttons as necessary
725  ensureButton(QWizard::BackButton);
726  ensureButton(QWizard::NextButton);
727  ensureButton(QWizard::CommitButton);
728  ensureButton(QWizard::FinishButton);
729 
730  pageFrame = new QFrame(antiFlickerWidget);
731  pageFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
732 
733  pageVBoxLayout = new QVBoxLayout(pageFrame);
734  pageVBoxLayout->setSpacing(0);
735  pageVBoxLayout->addSpacing(0);
736  QSpacerItem *spacerItem = new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
737  pageVBoxLayout->addItem(spacerItem);
738 
739  buttonLayout = new QHBoxLayout;
740  mainLayout = new QGridLayout(antiFlickerWidget);
741  mainLayout->setSizeConstraint(QLayout::SetNoConstraint);
742 
743  updateButtonLayout();
744 
745  for (int i = 0; i < NFallbackDefaultProperties; ++i)
746  defaultPropertyTable.append(QWizardDefaultProperty(fallbackProperties[i].className,
747  fallbackProperties[i].property,
748  fallbackProperties[i].changedSignal));
749 }
750 
751 void QWizardPrivate::reset()
752 {
753  Q_Q(QWizard);
754  if (current != -1) {
755  q->currentPage()->hide();
756  cleanupPagesNotInHistory();
757  for (int i = history.count() - 1; i >= 0; --i)
758  q->cleanupPage(history.at(i));
759  history.clear();
760  initialized.clear();
761 
762  current = -1;
763  emit q->currentIdChanged(-1);
764  }
765 }
766 
767 void QWizardPrivate::cleanupPagesNotInHistory()
768 {
769  Q_Q(QWizard);
770 
771  const QSet<int> original = initialized;
772  QSet<int>::const_iterator i = original.constBegin();
773  QSet<int>::const_iterator end = original.constEnd();
774 
775  for (; i != end; ++i) {
776  if (!history.contains(*i)) {
777  q->cleanupPage(*i);
778  initialized.remove(*i);
779  }
780  }
781 }
782 
783 void QWizardPrivate::addField(const QWizardField &field)
784 {
785  Q_Q(QWizard);
786 
787  QWizardField myField = field;
788  myField.resolve(defaultPropertyTable);
789 
790  if (fieldIndexMap.contains(myField.name)) {
791  kWarning() << "Duplicate field '" << qPrintable(myField.name) << "'";
792  return;
793  }
794 
795  fieldIndexMap.insert(myField.name, fields.count());
796  fields += myField;
797  if (myField.mandatory && !myField.changedSignal.isEmpty())
798  QObject::connect(myField.object, myField.changedSignal,
799  myField.page, SLOT(_q_maybeEmitCompleteChanged()));
800  QObject::connect(
801  myField.object, SIGNAL(destroyed(QObject*)), q,
802  SLOT(_q_handleFieldObjectDestroyed(QObject*)));
803 }
804 
805 void QWizardPrivate::removeFieldAt(int index)
806 {
807  Q_Q(QWizard);
808 
809  const QWizardField &field = fields.at(index);
810  fieldIndexMap.remove(field.name);
811  if (field.mandatory && !field.changedSignal.isEmpty())
812  QObject::disconnect(field.object, field.changedSignal,
813  field.page, SLOT(_q_maybeEmitCompleteChanged()));
814  QObject::disconnect(
815  field.object, SIGNAL(destroyed(QObject*)), q,
816  SLOT(_q_handleFieldObjectDestroyed(QObject*)));
817  fields.remove(index);
818 }
819 
820 void QWizardPrivate::switchToPage(int newId, Direction direction)
821 {
822  Q_Q(QWizard);
823 
824  disableUpdates();
825 
826  int oldId = current;
827  if (QWizardPage *oldPage = q->currentPage()) {
828  oldPage->hide();
829 
830  if (direction == Backward) {
831  if (!(opts & QWizard::IndependentPages)) {
832  q->cleanupPage(oldId);
833  initialized.remove(oldId);
834  }
835  Q_ASSERT(history.last() == oldId);
836  history.removeLast();
837  Q_ASSERT(history.last() == newId);
838  }
839  }
840 
841  current = newId;
842 
843  QWizardPage *newPage = q->currentPage();
844  if (newPage) {
845  if (direction == Forward) {
846  if (!initialized.contains(current)) {
847  initialized.insert(current);
848  q->initializePage(current);
849  }
850  history.append(current);
851  }
852  newPage->show();
853  }
854 
855  canContinue = (q->nextId() != -1);
856  canFinish = (newPage && newPage->isFinalPage());
857 
858  _q_updateButtonStates();
859  updateButtonTexts();
860 
861  const QWizard::WizardButton nextOrCommit =
862  newPage && newPage->isCommitPage() ? QWizard::CommitButton : QWizard::NextButton;
863  QAbstractButton *nextOrFinishButton =
864  btns[canContinue ? nextOrCommit : QWizard::FinishButton];
865  QWidget *candidate = 0;
866 
867  /*
868  If there is no default button and the Next or Finish button
869  is enabled, give focus directly to it as a convenience to the
870  user. This is the normal case on Mac OS X.
871 
872  Otherwise, give the focus to the new page's first child that
873  can handle it. If there is no such child, give the focus to
874  Next or Finish.
875  */
876  if ((opts & QWizard::NoDefaultButton) && nextOrFinishButton->isEnabled()) {
877  candidate = nextOrFinishButton;
878  } else if (newPage) {
879  candidate = iWantTheFocus(newPage);
880  }
881  if (!candidate)
882  candidate = nextOrFinishButton;
883  candidate->setFocus();
884 
885  if (wizStyle == QWizard::MacStyle)
886  q->updateGeometry();
887 
888  enableUpdates();
889  updateLayout();
890 
891  emit q->currentIdChanged(current);
892 }
893 
894 // keep in sync with QWizard::WizardButton
895 static const char * const buttonSlots[QWizard::NStandardButtons] = {
896  SLOT(back()), SLOT(next()), SLOT(next()), SLOT(accept()), SLOT(reject()),
897  SIGNAL(helpRequested())
898 };
899 
900 QWizardLayoutInfo QWizardPrivate::layoutInfoForCurrentPage()
901 {
902  Q_Q(QWizard);
903  QStyle *style = q->style();
904 
905  QWizardLayoutInfo info;
906 
907  const int layoutHorizontalSpacing = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
908  info.topLevelMarginLeft = style->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, q);
909  info.topLevelMarginRight = style->pixelMetric(QStyle::PM_LayoutRightMargin, 0, q);
910  info.topLevelMarginTop = style->pixelMetric(QStyle::PM_LayoutTopMargin, 0, q);
911  info.topLevelMarginBottom = style->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, q);
912  info.childMarginLeft = style->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, titleLabel);
913  info.childMarginRight = style->pixelMetric(QStyle::PM_LayoutRightMargin, 0, titleLabel);
914  info.childMarginTop = style->pixelMetric(QStyle::PM_LayoutTopMargin, 0, titleLabel);
915  info.childMarginBottom = style->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, titleLabel);
916  info.hspacing = (layoutHorizontalSpacing == -1)
917  ? style->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Horizontal)
918  : layoutHorizontalSpacing;
919  info.vspacing = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
920  info.buttonSpacing = (layoutHorizontalSpacing == -1)
921  ? style->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal)
922  : layoutHorizontalSpacing;
923 
924  if (wizStyle == QWizard::MacStyle)
925  info.buttonSpacing = 12;
926 
927  info.wizStyle = wizStyle;
928  if ((info.wizStyle == QWizard::AeroStyle)
929 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
930  && (QVistaHelper::vistaState() == QVistaHelper::Classic || vistaDisabled())
931 #endif
932  )
933  info.wizStyle = QWizard::ModernStyle;
934 
935  QString titleText;
936  QString subTitleText;
937  QPixmap backgroundPixmap;
938  QPixmap watermarkPixmap;
939 
940  if (QWizardPage *page = q->currentPage()) {
941  titleText = page->title();
942  subTitleText = page->subTitle();
943  backgroundPixmap = page->pixmap(QWizard::BackgroundPixmap);
944  watermarkPixmap = page->pixmap(QWizard::WatermarkPixmap);
945  }
946 
947  info.header = (info.wizStyle == QWizard::ClassicStyle || info.wizStyle == QWizard::ModernStyle)
948  && !(opts & QWizard::IgnoreSubTitles) && !subTitleText.isEmpty();
949  info.sideWidget = sideWidget;
950  info.watermark = (info.wizStyle != QWizard::MacStyle) && (info.wizStyle != QWizard::AeroStyle)
951  && !watermarkPixmap.isNull();
952  info.title = !info.header && !titleText.isEmpty();
953  info.subTitle = !(opts & QWizard::IgnoreSubTitles) && !info.header && !subTitleText.isEmpty();
954  info.extension = (info.watermark || info.sideWidget) && (opts & QWizard::ExtendedWatermarkPixmap);
955 
956  return info;
957 }
958 
959 void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
960 {
961  Q_Q(QWizard);
962 
963  /*
964  Start by undoing the main layout.
965  */
966  for (int i = mainLayout->count() - 1; i >= 0; --i) {
967  QLayoutItem *item = mainLayout->takeAt(i);
968  if (item->layout()) {
969  item->layout()->setParent(0);
970  } else {
971  delete item;
972  }
973  }
974  for (int i = mainLayout->columnCount() - 1; i >= 0; --i)
975  mainLayout->setColumnMinimumWidth(i, 0);
976  for (int i = mainLayout->rowCount() - 1; i >= 0; --i)
977  mainLayout->setRowMinimumHeight(i, 0);
978 
979  /*
980  Now, recreate it.
981  */
982 
983  bool mac = (info.wizStyle == QWizard::MacStyle);
984  bool classic = (info.wizStyle == QWizard::ClassicStyle);
985  bool modern = (info.wizStyle == QWizard::ModernStyle);
986  bool aero = (info.wizStyle == QWizard::AeroStyle);
987  int deltaMarginLeft = info.topLevelMarginLeft - info.childMarginLeft;
988  int deltaMarginRight = info.topLevelMarginRight - info.childMarginRight;
989  int deltaMarginTop = info.topLevelMarginTop - info.childMarginTop;
990  int deltaMarginBottom = info.topLevelMarginBottom - info.childMarginBottom;
991  int deltaVSpacing = info.topLevelMarginBottom - info.vspacing;
992 
993  int row = 0;
994  int numColumns;
995  if (mac) {
996  numColumns = 3;
997  } else if (info.watermark || info.sideWidget) {
998  numColumns = 2;
999  } else {
1000  numColumns = 1;
1001  }
1002  int pageColumn = qMin(1, numColumns - 1);
1003 
1004  if (mac) {
1005  mainLayout->setMargin(0);
1006  mainLayout->setSpacing(0);
1007  buttonLayout->setContentsMargins(MacLayoutLeftMargin, MacButtonTopMargin, MacLayoutRightMargin, MacLayoutBottomMargin);
1008  pageVBoxLayout->setMargin(7);
1009  } else {
1010  if (modern) {
1011  mainLayout->setMargin(0);
1012  mainLayout->setSpacing(0);
1013  pageVBoxLayout->setContentsMargins(deltaMarginLeft, deltaMarginTop,
1014  deltaMarginRight, deltaMarginBottom);
1015  buttonLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop,
1016  info.topLevelMarginRight, info.topLevelMarginBottom);
1017  } else {
1018  mainLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop,
1019  info.topLevelMarginRight, info.topLevelMarginBottom);
1020  mainLayout->setHorizontalSpacing(info.hspacing);
1021  mainLayout->setVerticalSpacing(info.vspacing);
1022  pageVBoxLayout->setContentsMargins(0, 0, 0, 0);
1023  buttonLayout->setContentsMargins(0, 0, 0, 0);
1024  }
1025  }
1026  buttonLayout->setSpacing(info.buttonSpacing);
1027 
1028  if (info.header) {
1029  if (!headerWidget)
1030  headerWidget = new QWizardHeader(antiFlickerWidget);
1031  headerWidget->setAutoFillBackground(modern);
1032  mainLayout->addWidget(headerWidget, row++, 0, 1, numColumns);
1033  }
1034  if (headerWidget)
1035  headerWidget->setVisible(info.header);
1036 
1037  int watermarkStartRow = row;
1038 
1039  if (mac)
1040  mainLayout->setRowMinimumHeight(row++, 10);
1041 
1042  if (info.title) {
1043  if (!titleLabel) {
1044  titleLabel = new QLabel(antiFlickerWidget);
1045  titleLabel->setBackgroundRole(QPalette::Base);
1046  titleLabel->setWordWrap(true);
1047  }
1048 
1049  QFont titleFont = q->font();
1050  titleFont.setPointSize(titleFont.pointSize() + (mac ? 3 : 4));
1051  titleFont.setBold(true);
1052  titleLabel->setPalette(QPalette());
1053 
1054  if (aero) {
1055  // ### hardcoded for now:
1056  titleFont = QFont(QLatin1String("Segoe UI"), 12);
1057  QPalette pal(titleLabel->palette());
1058  pal.setColor(QPalette::Text, "#003399");
1059  titleLabel->setPalette(pal);
1060  }
1061 
1062  titleLabel->setFont(titleFont);
1063  const int aeroTitleIndent = 25; // ### hardcoded for now - should be calculated somehow
1064  if (aero)
1065  titleLabel->setIndent(aeroTitleIndent);
1066  else if (mac)
1067  titleLabel->setIndent(2);
1068  else if (classic)
1069  titleLabel->setIndent(info.childMarginLeft);
1070  else
1071  titleLabel->setIndent(info.topLevelMarginLeft);
1072  if (modern) {
1073  if (!placeholderWidget1) {
1074  placeholderWidget1 = new QWidget(antiFlickerWidget);
1075  placeholderWidget1->setBackgroundRole(QPalette::Base);
1076  }
1077  placeholderWidget1->setFixedHeight(info.topLevelMarginLeft + 2);
1078  mainLayout->addWidget(placeholderWidget1, row++, pageColumn);
1079  }
1080  mainLayout->addWidget(titleLabel, row++, pageColumn);
1081  if (modern) {
1082  if (!placeholderWidget2) {
1083  placeholderWidget2 = new QWidget(antiFlickerWidget);
1084  placeholderWidget2->setBackgroundRole(QPalette::Base);
1085  }
1086  placeholderWidget2->setFixedHeight(5);
1087  mainLayout->addWidget(placeholderWidget2, row++, pageColumn);
1088  }
1089  if (mac)
1090  mainLayout->setRowMinimumHeight(row++, 7);
1091  }
1092  if (placeholderWidget1)
1093  placeholderWidget1->setVisible(info.title && modern);
1094  if (placeholderWidget2)
1095  placeholderWidget2->setVisible(info.title && modern);
1096 
1097  if (info.subTitle) {
1098  if (!subTitleLabel) {
1099  subTitleLabel = new QLabel(pageFrame);
1100  subTitleLabel->setWordWrap(true);
1101 
1102  subTitleLabel->setContentsMargins(info.childMarginLeft , 0,
1103  info.childMarginRight , 0);
1104 
1105  pageVBoxLayout->insertWidget(1, subTitleLabel);
1106  }
1107  }
1108 
1109  // ### try to replace with margin.
1110  changeSpacerSize(pageVBoxLayout, 0, 0, info.subTitle ? info.childMarginLeft : 0);
1111 
1112  int hMargin = mac ? 1 : 0;
1113  int vMargin = hMargin;
1114 
1115  pageFrame->setFrameStyle(mac ? (QFrame::Box | QFrame::Raised) : QFrame::NoFrame);
1116  pageFrame->setLineWidth(0);
1117  pageFrame->setMidLineWidth(hMargin);
1118 
1119  if (info.header) {
1120  if (modern) {
1121  hMargin = info.topLevelMarginLeft;
1122  vMargin = deltaMarginBottom;
1123  } else if (classic) {
1124  hMargin = deltaMarginLeft + ClassicHMargin;
1125  vMargin = 0;
1126  }
1127  }
1128 
1129  if (aero) {
1130  int leftMargin = 18; // ### hardcoded for now - should be calculated somehow
1131  int topMargin = vMargin;
1132  int rightMargin = hMargin; // ### for now
1133  int bottomMargin = vMargin;
1134  pageFrame->setContentsMargins(leftMargin, topMargin, rightMargin, bottomMargin);
1135  } else {
1136  pageFrame->setContentsMargins(hMargin, vMargin, hMargin, vMargin);
1137  }
1138 
1139  if ((info.watermark || info.sideWidget) && !watermarkLabel) {
1140  watermarkLabel = new QWatermarkLabel(antiFlickerWidget, sideWidget);
1141  watermarkLabel->setBackgroundRole(QPalette::Base);
1142  watermarkLabel->setMinimumHeight(1);
1143  watermarkLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
1144  watermarkLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
1145  }
1146 
1147  //bool wasSemiTransparent = pageFrame->testAttribute(Qt::WA_SetPalette);
1148  const bool wasSemiTransparent =
1149  pageFrame->palette().brush(QPalette::Window).color().alpha() < 255
1150  || pageFrame->palette().brush(QPalette::Base).color().alpha() < 255;
1151  if (mac) {
1152  if (!wasSemiTransparent) {
1153  QPalette pal = pageFrame->palette();
1154  pal.setBrush(QPalette::Window, QColor(255, 255, 255, 153));
1155  // ### The next line is required to ensure visual semitransparency when
1156  // ### switching from ModernStyle to MacStyle. See TAG1 below.
1157  pal.setBrush(QPalette::Base, QColor(255, 255, 255, 153));
1158  pageFrame->setPalette(pal);
1159  pageFrame->setAutoFillBackground(true);
1160  antiFlickerWidget->setAutoFillBackground(false);
1161  }
1162  } else {
1163  if (wasSemiTransparent)
1164  pageFrame->setPalette(QPalette());
1165 
1166  bool baseBackground = (modern && !info.header); // ### TAG1
1167  pageFrame->setBackgroundRole(baseBackground ? QPalette::Base : QPalette::Window);
1168 
1169  if (titleLabel)
1170  titleLabel->setAutoFillBackground(baseBackground);
1171  pageFrame->setAutoFillBackground(baseBackground);
1172  if (watermarkLabel)
1173  watermarkLabel->setAutoFillBackground(baseBackground);
1174  if (placeholderWidget1)
1175  placeholderWidget1->setAutoFillBackground(baseBackground);
1176  if (placeholderWidget2)
1177  placeholderWidget2->setAutoFillBackground(baseBackground);
1178 
1179  if (aero) {
1180  QPalette pal = pageFrame->palette();
1181  pal.setBrush(QPalette::Window, QColor(255, 255, 255));
1182  pageFrame->setPalette(pal);
1183  pageFrame->setAutoFillBackground(true);
1184  pal = antiFlickerWidget->palette();
1185  pal.setBrush(QPalette::Window, QColor(255, 255, 255));
1186  antiFlickerWidget->setPalette(pal);
1187  antiFlickerWidget->setAutoFillBackground(true);
1188  }
1189  }
1190 
1191  mainLayout->addWidget(pageFrame, row++, pageColumn);
1192 
1193  int watermarkEndRow = row;
1194  if (classic)
1195  mainLayout->setRowMinimumHeight(row++, deltaVSpacing);
1196 
1197  if (aero) {
1198  buttonLayout->setContentsMargins(9, 9, 9, 9);
1199  mainLayout->setContentsMargins(0, 11, 0, 0);
1200  }
1201 
1202  int buttonStartColumn = info.extension ? 1 : 0;
1203  int buttonNumColumns = info.extension ? 1 : numColumns;
1204 
1205  if (classic || modern) {
1206  if (!bottomRuler)
1207  bottomRuler = new QWizardRuler(antiFlickerWidget);
1208  mainLayout->addWidget(bottomRuler, row++, buttonStartColumn, 1, buttonNumColumns);
1209  }
1210 
1211  if (classic)
1212  mainLayout->setRowMinimumHeight(row++, deltaVSpacing);
1213 
1214  mainLayout->addLayout(buttonLayout, row++, buttonStartColumn, 1, buttonNumColumns);
1215 
1216  if (info.watermark || info.sideWidget) {
1217  if (info.extension)
1218  watermarkEndRow = row;
1219  mainLayout->addWidget(watermarkLabel, watermarkStartRow, 0,
1220  watermarkEndRow - watermarkStartRow, 1);
1221  }
1222 
1223  mainLayout->setColumnMinimumWidth(0, mac && !info.watermark ? 181 : 0);
1224  if (mac)
1225  mainLayout->setColumnMinimumWidth(2, 21);
1226 
1227  if (headerWidget)
1228  headerWidget->setVisible(info.header);
1229  if (titleLabel)
1230  titleLabel->setVisible(info.title);
1231  if (subTitleLabel)
1232  subTitleLabel->setVisible(info.subTitle);
1233  if (bottomRuler)
1234  bottomRuler->setVisible(classic || modern);
1235  if (watermarkLabel)
1236  watermarkLabel->setVisible(info.watermark || info.sideWidget);
1237 
1238  layoutInfo = info;
1239 }
1240 
1241 void QWizardPrivate::updateLayout()
1242 {
1243  Q_Q(QWizard);
1244 
1245  disableUpdates();
1246 
1247  QWizardLayoutInfo info = layoutInfoForCurrentPage();
1248  if (layoutInfo != info)
1249  recreateLayout(info);
1250  QWizardPage *page = q->currentPage();
1251 
1252  // If the page can expand vertically, let it stretch "infinitely" more
1253  // than the QSpacerItem at the bottom. Otherwise, let the QSpacerItem
1254  // stretch "infinitely" more than the page. Change the bottom item's
1255  // policy accordingly. The case that the page has no layout is basically
1256  // for Designer, only.
1257  if (page) {
1258  bool expandPage = !page->layout();
1259  if (!expandPage) {
1260  const QLayoutItem *pageItem = pageVBoxLayout->itemAt(pageVBoxLayout->indexOf(page));
1261  expandPage = pageItem->expandingDirections() & Qt::Vertical;
1262  }
1263  QSpacerItem *bottomSpacer = pageVBoxLayout->itemAt(pageVBoxLayout->count() - 1)->spacerItem();
1264  Q_ASSERT(bottomSpacer);
1265  bottomSpacer->changeSize(0, 0, QSizePolicy::Ignored, expandPage ? QSizePolicy::Ignored : QSizePolicy::MinimumExpanding);
1266  pageVBoxLayout->invalidate();
1267  }
1268 
1269  if (info.header) {
1270  Q_ASSERT(page);
1271  headerWidget->setup(info, page->title(), page->subTitle(),
1272  page->pixmap(QWizard::LogoPixmap), page->pixmap(QWizard::BannerPixmap),
1273  titleFmt, subTitleFmt);
1274  }
1275 
1276  if (info.watermark || info.sideWidget) {
1277  QPixmap pix;
1278  if (info.watermark) {
1279  if (page)
1280  pix = page->pixmap(QWizard::WatermarkPixmap);
1281  else
1282  pix = q->pixmap(QWizard::WatermarkPixmap);
1283  }
1284  watermarkLabel->setPixmap(pix); // in case there is no watermark and we show the side widget we need to clear the watermark
1285  }
1286 
1287  if (info.title) {
1288  Q_ASSERT(page);
1289  titleLabel->setTextFormat(titleFmt);
1290  titleLabel->setText(page->title());
1291  }
1292  if (info.subTitle) {
1293  Q_ASSERT(page);
1294  subTitleLabel->setTextFormat(subTitleFmt);
1295  subTitleLabel->setText(page->subTitle());
1296  }
1297 
1298  enableUpdates();
1299  updateMinMaxSizes(info);
1300 }
1301 
1302 void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
1303 {
1304  Q_Q(QWizard);
1305 
1306  int extraHeight = 0;
1307 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
1308  if (isVistaThemeEnabled())
1309  extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset();
1310 #endif
1311  QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight);
1312  QSize maximumSize = mainLayout->totalMaximumSize();
1313  if (info.header && headerWidget->maximumWidth() != QWIDGETSIZE_MAX) {
1314  minimumSize.setWidth(headerWidget->maximumWidth());
1315  maximumSize.setWidth(headerWidget->maximumWidth());
1316  }
1317  if (info.watermark && !info.sideWidget) {
1318  minimumSize.setHeight(mainLayout->totalSizeHint().height());
1319  maximumSize.setHeight(mainLayout->totalSizeHint().height());
1320  }
1321  if (q->minimumWidth() == minimumWidth) {
1322  minimumWidth = minimumSize.width();
1323  q->setMinimumWidth(minimumWidth);
1324  }
1325  if (q->minimumHeight() == minimumHeight) {
1326  minimumHeight = minimumSize.height();
1327  q->setMinimumHeight(minimumHeight);
1328  }
1329  if (q->maximumWidth() == maximumWidth) {
1330  maximumWidth = maximumSize.width();
1331  q->setMaximumWidth(maximumWidth);
1332  }
1333  if (q->maximumHeight() == maximumHeight) {
1334  maximumHeight = maximumSize.height();
1335  q->setMaximumHeight(maximumHeight);
1336  }
1337 
1338  q->setFixedSize( QApplication::desktop()->screenGeometry().size() );
1339 }
1340 
1341 void QWizardPrivate::updateCurrentPage()
1342 {
1343  Q_Q(QWizard);
1344  if (q->currentPage()) {
1345  canContinue = (q->nextId() != -1);
1346  canFinish = q->currentPage()->isFinalPage();
1347  } else {
1348  canContinue = false;
1349  canFinish = false;
1350  }
1351  _q_updateButtonStates();
1352  updateButtonTexts();
1353 }
1354 
1355 bool QWizardPrivate::ensureButton(QWizard::WizardButton which) const
1356 {
1357  Q_Q(const QWizard);
1358  if (uint(which) >= QWizard::NButtons)
1359  return false;
1360 
1361  if (!btns[which]) {
1362  QPushButton *pushButton = new QPushButton(antiFlickerWidget);
1363  QStyle *style = q->style();
1364  if (style != QApplication::style()) // Propagate style
1365  pushButton->setStyle(style);
1366  // Make navigation buttons detectable as passive interactor in designer
1367  switch (which) {
1368  case QWizard::CommitButton:
1369  case QWizard::FinishButton:
1370  case QWizard::CancelButton:
1371  break;
1372  default: {
1373  QString objectName = QLatin1String("__qt__passive_wizardbutton");
1374  objectName += QString::number(which);
1375  pushButton->setObjectName(objectName);
1376  }
1377  break;
1378  }
1379 #ifdef Q_WS_MAC
1380  pushButton->setAutoDefault(false);
1381 #endif
1382  pushButton->hide();
1383 #ifdef Q_CC_HPACC
1384  const_cast<QWizardPrivate *>(this)->btns[which] = pushButton;
1385 #else
1386  btns[which] = pushButton;
1387 #endif
1388  if (which < QWizard::NStandardButtons)
1389  pushButton->setText(buttonDefaultText(wizStyle, which, this));
1390 
1391 #ifdef QT_SOFTKEYS_ENABLED
1392  QAction *softKey = new QAction(pushButton->text(), pushButton);
1393  QAction::SoftKeyRole softKeyRole;
1394  switch(which) {
1395  case QWizard::NextButton:
1396  case QWizard::FinishButton:
1397  case QWizard::CancelButton:
1398  softKeyRole = QAction::NegativeSoftKey;
1399  break;
1400  case QWizard::BackButton:
1401  case QWizard::CommitButton:
1402  case QWizard::HelpButton:
1403  case QWizard::CustomButton1:
1404  case QWizard::CustomButton2:
1405  case QWizard::CustomButton3:
1406  default:
1407  softKeyRole = QAction::PositiveSoftKey;
1408  break;
1409  }
1410  softKey->setSoftKeyRole(softKeyRole);
1411  softKeys[which] = softKey;
1412 #endif
1413  connectButton(which);
1414  }
1415  return true;
1416 }
1417 
1418 void QWizardPrivate::connectButton(QWizard::WizardButton which) const
1419 {
1420  Q_Q(const QWizard);
1421  if (which < QWizard::NStandardButtons) {
1422  QObject::connect(btns[which], SIGNAL(clicked()), q, buttonSlots[which]);
1423  } else {
1424  QObject::connect(btns[which], SIGNAL(clicked()), q, SLOT(_q_emitCustomButtonClicked()));
1425  }
1426 
1427 #ifdef QT_SOFTKEYS_ENABLED
1428  QObject::connect(softKeys[which], SIGNAL(triggered()), btns[which], SIGNAL(clicked()));
1429 #endif
1430 }
1431 
1432 void QWizardPrivate::updateButtonTexts()
1433 {
1434  Q_Q(QWizard);
1435  for (int i = 0; i < QWizard::NButtons; ++i) {
1436  if (btns[i]) {
1437  if (q->currentPage() && (q->currentPage()->d_func()->buttonCustomTexts.contains(i)))
1438  btns[i]->setText(q->currentPage()->d_func()->buttonCustomTexts.value(i));
1439  else if (buttonCustomTexts.contains(i))
1440  btns[i]->setText(buttonCustomTexts.value(i));
1441  else if (i < QWizard::NStandardButtons)
1442  btns[i]->setText(buttonDefaultText(wizStyle, i, this));
1443 #ifdef QT_SOFTKEYS_ENABLED
1444  softKeys[i]->setText(btns[i]->text());
1445 #endif
1446  }
1447  }
1448 }
1449 
1450 void QWizardPrivate::updateButtonLayout()
1451 {
1452  if (buttonsHaveCustomLayout) {
1453  QVarLengthArray<QWizard::WizardButton> array(buttonsCustomLayout.count());
1454  for (int i = 0; i < buttonsCustomLayout.count(); ++i)
1455  array[i] = buttonsCustomLayout.at(i);
1456  setButtonLayout(array.constData(), array.count());
1457  } else {
1458  // Positions:
1459  // Help Stretch Custom1 Custom2 Custom3 Cancel Back Next Commit Finish Cancel Help
1460 
1461  const int ArraySize = 12;
1462  QWizard::WizardButton array[ArraySize];
1463  memset(array, -1, sizeof(array));
1464  Q_ASSERT(array[0] == QWizard::NoButton);
1465 
1466  if (opts & QWizard::HaveHelpButton) {
1467  int i = (opts & QWizard::HelpButtonOnRight) ? 11 : 0;
1468  array[i] = QWizard::HelpButton;
1469  }
1470  array[1] = QWizard::Stretch;
1471  if (opts & QWizard::HaveCustomButton1)
1472  array[2] = QWizard::CustomButton1;
1473  if (opts & QWizard::HaveCustomButton2)
1474  array[3] = QWizard::CustomButton2;
1475  if (opts & QWizard::HaveCustomButton3)
1476  array[4] = QWizard::CustomButton3;
1477 
1478  if (!(opts & QWizard::NoCancelButton)) {
1479  int i = (opts & QWizard::CancelButtonOnLeft) ? 5 : 10;
1480  array[i] = QWizard::CancelButton;
1481  }
1482  array[6] = QWizard::BackButton;
1483  array[7] = QWizard::NextButton;
1484  array[8] = QWizard::CommitButton;
1485  array[9] = QWizard::FinishButton;
1486 
1487  setButtonLayout(array, ArraySize);
1488  }
1489 }
1490 
1491 void QWizardPrivate::setButtonLayout(const QWizard::WizardButton *array, int size)
1492 {
1493  QWidget *prev = pageFrame;
1494 
1495  for (int i = buttonLayout->count() - 1; i >= 0; --i) {
1496  QLayoutItem *item = buttonLayout->takeAt(i);
1497  if (QWidget *widget = item->widget())
1498  widget->hide();
1499  delete item;
1500  }
1501 
1502  for (int i = 0; i < size; ++i) {
1503  QWizard::WizardButton which = array[i];
1504  if (which == QWizard::Stretch) {
1505  buttonLayout->addStretch(1);
1506  } else if (which != QWizard::NoButton) {
1507  ensureButton(which);
1508  buttonLayout->addWidget(btns[which]);
1509 
1510  // Back, Next, Commit, and Finish are handled in _q_updateButtonStates()
1511  if (which != QWizard::BackButton && which != QWizard::NextButton
1512  && which != QWizard::CommitButton && which != QWizard::FinishButton)
1513  btns[which]->show();
1514 
1515  if (prev)
1516  QWidget::setTabOrder(prev, btns[which]);
1517  prev = btns[which];
1518  }
1519  }
1520 
1521  _q_updateButtonStates();
1522 }
1523 
1524 bool QWizardPrivate::buttonLayoutContains(QWizard::WizardButton which)
1525 {
1526  return !buttonsHaveCustomLayout || buttonsCustomLayout.contains(which);
1527 }
1528 
1529 void QWizardPrivate::updatePixmap(QWizard::WizardPixmap which)
1530 {
1531  Q_Q(QWizard);
1532  if (which == QWizard::BackgroundPixmap) {
1533  if (wizStyle == QWizard::MacStyle) {
1534  q->update();
1535  q->updateGeometry();
1536  }
1537  } else {
1538  updateLayout();
1539  }
1540 }
1541 
1542 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
1543 bool QWizardPrivate::vistaDisabled() const
1544 {
1545  Q_Q(const QWizard);
1546  const QVariant v = q->property("_q_wizard_vista_off");
1547  return v.isValid() && v.toBool();
1548 }
1549 
1550 bool QWizardPrivate::isVistaThemeEnabled(QVistaHelper::VistaState state) const
1551 {
1552  return wizStyle == QWizard::AeroStyle
1553  && QVistaHelper::vistaState() == state
1554  && !vistaDisabled();
1555 }
1556 
1557 void QWizardPrivate::handleAeroStyleChange()
1558 {
1559  Q_Q(QWizard);
1560 
1561  if (inHandleAeroStyleChange)
1562  return; // prevent recursion
1563  inHandleAeroStyleChange = true;
1564 
1565  vistaHelper->disconnectBackButton();
1566  q->removeEventFilter(vistaHelper);
1567 
1568  if (isVistaThemeEnabled()) {
1569  if (isVistaThemeEnabled(QVistaHelper::VistaAero)) {
1570  vistaHelper->setDWMTitleBar(QVistaHelper::ExtendedTitleBar);
1571  q->installEventFilter(vistaHelper);
1572  q->setMouseTracking(true);
1573  topWidget->move(0, vistaHelper->titleBarSize() + vistaHelper->topOffset());
1574  vistaHelper->backButton()->move(
1575  0, vistaHelper->topOffset() // ### should ideally work without the '+ 1'
1576  - qMin(vistaHelper->topOffset(), vistaHelper->topPadding() + 1));
1577  } else {
1578  vistaHelper->setDWMTitleBar(QVistaHelper::NormalTitleBar);
1579  q->setMouseTracking(true);
1580  topWidget->move(0, vistaHelper->topOffset());
1581  vistaHelper->backButton()->move(0, -1); // ### should ideally work with (0, 0)
1582  }
1583  vistaHelper->setTitleBarIconAndCaptionVisible(false);
1584  QObject::connect(
1585  vistaHelper->backButton(), SIGNAL(clicked()), q, buttonSlots[QWizard::BackButton]);
1586  vistaHelper->backButton()->show();
1587  } else {
1588  q->setMouseTracking(true); // ### original value possibly different
1589 #ifndef QT_NO_CURSOR
1590  q->unsetCursor(); // ### ditto
1591 #endif
1592  topWidget->move(0, 0);
1593  vistaHelper->hideBackButton();
1594  vistaHelper->setTitleBarIconAndCaptionVisible(true);
1595  }
1596 
1597  _q_updateButtonStates();
1598 
1599  if (q->isVisible())
1600  vistaHelper->setWindowPosHack();
1601 
1602  inHandleAeroStyleChange = false;
1603 }
1604 #endif
1605 
1606 bool QWizardPrivate::isVistaThemeEnabled() const
1607 {
1608 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
1609  return isVistaThemeEnabled(QVistaHelper::VistaAero)
1610  || isVistaThemeEnabled(QVistaHelper::VistaBasic);
1611 #else
1612  return false;
1613 #endif
1614 }
1615 
1616 void QWizardPrivate::disableUpdates()
1617 {
1618  Q_Q(QWizard);
1619  if (disableUpdatesCount++ == 0) {
1620  q->setUpdatesEnabled(false);
1621  topWidget->hide();
1622  }
1623 }
1624 
1625 void QWizardPrivate::enableUpdates()
1626 {
1627  Q_Q(QWizard);
1628  if (--disableUpdatesCount == 0) {
1629  topWidget->show();
1630  q->setUpdatesEnabled(true);
1631  }
1632 }
1633 
1634 void QWizardPrivate::_q_emitCustomButtonClicked()
1635 {
1636  Q_Q(QWizard);
1637  QObject *button = q->sender();
1638  for (int i = QWizard::NStandardButtons; i < QWizard::NButtons; ++i) {
1639  if (btns[i] == button) {
1640  emit q->customButtonClicked(QWizard::WizardButton(i));
1641  break;
1642  }
1643  }
1644 }
1645 
1646 void QWizardPrivate::_q_updateButtonStates()
1647 {
1648  Q_Q(QWizard);
1649 
1650  disableUpdates();
1651 
1652  const QWizardPage *page = q->currentPage();
1653  bool complete = page && page->isComplete();
1654 
1655  btn.back->setEnabled(history.count() > 1
1656  && !q->page(history.at(history.count() - 2))->isCommitPage()
1657  && (!canFinish || !(opts & QWizard::DisabledBackButtonOnLastPage)));
1658  btn.next->setEnabled(canContinue && complete);
1659  btn.commit->setEnabled(canContinue && complete);
1660  btn.finish->setEnabled(canFinish && complete);
1661 
1662  const bool backButtonVisible = buttonLayoutContains(QWizard::BackButton)
1663  && (history.count() > 1 || !(opts & QWizard::NoBackButtonOnStartPage))
1664  && (canContinue || !(opts & QWizard::NoBackButtonOnLastPage));
1665  bool commitPage = page && page->isCommitPage();
1666  btn.back->setVisible(backButtonVisible);
1667  btn.next->setVisible(buttonLayoutContains(QWizard::NextButton) && !commitPage
1668  && (canContinue || (opts & QWizard::HaveNextButtonOnLastPage)));
1669  btn.commit->setVisible(buttonLayoutContains(QWizard::CommitButton) && commitPage
1670  && canContinue);
1671  btn.finish->setVisible(buttonLayoutContains(QWizard::FinishButton)
1672  && (canFinish || (opts & QWizard::HaveFinishButtonOnEarlyPages)));
1673 
1674  bool useDefault = !(opts & QWizard::NoDefaultButton);
1675  if (QPushButton *nextPush = qobject_cast<QPushButton *>(btn.next))
1676  nextPush->setDefault(canContinue && useDefault && !commitPage);
1677  if (QPushButton *commitPush = qobject_cast<QPushButton *>(btn.commit))
1678  commitPush->setDefault(canContinue && useDefault && commitPage);
1679  if (QPushButton *finishPush = qobject_cast<QPushButton *>(btn.finish))
1680  finishPush->setDefault(!canContinue && useDefault);
1681 
1682 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
1683  if (isVistaThemeEnabled()) {
1684  vistaHelper->backButton()->setEnabled(btn.back->isEnabled());
1685  vistaHelper->backButton()->setVisible(backButtonVisible);
1686  btn.back->setVisible(false);
1687  }
1688 #endif
1689 
1690 #ifdef QT_SOFTKEYS_ENABLED
1691  QAbstractButton *wizardButton;
1692  for (int i = 0; i < QWizard::NButtons; ++i) {
1693  wizardButton = btns[i];
1694  if (wizardButton && !wizardButton->testAttribute(Qt::WA_WState_Hidden)) {
1695  wizardButton->hide();
1696  q->addAction(softKeys[i]);
1697  } else {
1698  q->removeAction(softKeys[i]);
1699  }
1700  }
1701 #endif
1702 
1703  enableUpdates();
1704 }
1705 
1706 void QWizardPrivate::_q_handleFieldObjectDestroyed(QObject *object)
1707 {
1708  QVector<QWizardField>::iterator it = fields.begin();
1709  while (it != fields.end()) {
1710  const QWizardField &field = *it;
1711  if (field.object == object) {
1712  fieldIndexMap.remove(field.name);
1713  it = fields.erase(it);
1714  } else {
1715  ++it;
1716  }
1717  }
1718 }
1719 
1720 void QWizardPrivate::setStyle(QStyle *style)
1721 {
1722  for (int i = 0; i < QWizard::NButtons; i++)
1723  if (btns[i])
1724  btns[i]->setStyle(style);
1725  const PageMap::const_iterator pcend = pageMap.constEnd();
1726  for (PageMap::const_iterator it = pageMap.constBegin(); it != pcend; ++it)
1727  it.value()->setStyle(style);
1728 }
1729 
1730 #ifdef Q_WS_MAC
1731 
1732 QPixmap QWizardPrivate::findDefaultBackgroundPixmap()
1733 {
1734  QCFType<CFURLRef> url;
1735  const int ExpectedImageWidth = 242;
1736  const int ExpectedImageHeight = 414;
1737  if (LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.KeyboardSetupAssistant"),
1738  0, 0, &url) == noErr) {
1739  QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, url);
1740  if (bundle) {
1741  url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("tif"), 0);
1742  if (url) {
1743  QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0);
1744  QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
1745  if (image) {
1746  int width = CGImageGetWidth(image);
1747  int height = CGImageGetHeight(image);
1748  if (width == ExpectedImageWidth && height == ExpectedImageHeight)
1749  return QPixmap::fromMacCGImageRef(image);
1750  }
1751  }
1752  }
1753  }
1754  return QPixmap();
1755 
1756 }
1757 
1758 #endif
1759 
1760 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
1761 void QWizardAntiFlickerWidget::paintEvent(QPaintEvent *)
1762 {
1763  if (wizardPrivate->isVistaThemeEnabled()) {
1764  int leftMargin, topMargin, rightMargin, bottomMargin;
1765  wizardPrivate->buttonLayout->getContentsMargins(
1766  &leftMargin, &topMargin, &rightMargin, &bottomMargin);
1767  const int buttonLayoutTop = wizardPrivate->buttonLayout->contentsRect().top() - topMargin;
1768  QPainter painter(this);
1769  const QBrush brush(QColor(240, 240, 240)); // ### hardcoded for now
1770  painter.fillRect(0, buttonLayoutTop, width(), height() - buttonLayoutTop, brush);
1771  painter.setPen(QPen(QBrush(QColor(223, 223, 223)), 0)); // ### hardcoded for now
1772  painter.drawLine(0, buttonLayoutTop, width(), buttonLayoutTop);
1773  if (wizardPrivate->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
1774  if (window()->isActiveWindow())
1775  painter.setPen(QPen(QBrush(QColor(169, 191, 214)), 0)); // ### hardcoded for now
1776  else
1777  painter.setPen(QPen(QBrush(QColor(182, 193, 204)), 0)); // ### hardcoded for now
1778  painter.drawLine(0, 0, width(), 0);
1779  }
1780  }
1781 }
1782 #endif
1783 
2175 QWizard::QWizard(QWidget *parent, Qt::WindowFlags flags)
2176  : QDialog(*new QWizardPrivate, parent, flags)
2177 {
2178  Q_D(QWizard);
2179  d->init();
2180 }
2181 
2185 QWizard::~QWizard()
2186 {
2187  Q_D(QWizard);
2188  delete d->buttonLayout;
2189 }
2190 
2199 int QWizard::addPage(QWizardPage *page)
2200 {
2201  Q_D(QWizard);
2202  int theid = 0;
2203  if (!d->pageMap.isEmpty())
2204  theid = (d->pageMap.constEnd() - 1).key() + 1;
2205  setPage(theid, page);
2206  return theid;
2207 }
2208 
2219 void QWizard::setPage(int theid, QWizardPage *page)
2220 {
2221  Q_D(QWizard);
2222 
2223  if (!page) {
2224  kWarning() << "Cannot insert null page";
2225  return;
2226  }
2227 
2228  if (theid == -1) {
2229  kWarning() << "Cannot insert page with ID -1";
2230  return;
2231  }
2232 
2233  if (d->pageMap.contains(theid)) {
2234  kWarning() << "Page with duplicate ID " << theid << " ignored";
2235  return;
2236  }
2237 
2238  page->setParent(d->pageFrame);
2239 
2240  QVector<QWizardField> &pendingFields = page->d_func()->pendingFields;
2241  for (int i = 0; i < pendingFields.count(); ++i)
2242  d->addField(pendingFields.at(i));
2243  pendingFields.clear();
2244 
2245  connect(page, SIGNAL(completeChanged()), this, SLOT(_q_updateButtonStates()));
2246 
2247  d->pageMap.insert(theid, page);
2248  page->d_func()->wizard = this;
2249 
2250  int n = d->pageVBoxLayout->count();
2251 
2252  // disable layout to prevent layout updates while adding
2253  bool pageVBoxLayoutEnabled = d->pageVBoxLayout->isEnabled();
2254  d->pageVBoxLayout->setEnabled(false);
2255 
2256  d->pageVBoxLayout->insertWidget(n - 1, page);
2257 
2258  // hide new page and reset layout to old status
2259  page->hide();
2260  d->pageVBoxLayout->setEnabled(pageVBoxLayoutEnabled);
2261 
2262  if (!d->startSetByUser && d->pageMap.constBegin().key() == theid)
2263  d->start = theid;
2264  emit pageAdded(theid);
2265 }
2266 
2275 void QWizard::removePage(int id)
2276 {
2277  Q_D(QWizard);
2278 
2279  QWizardPage *removedPage = 0;
2280 
2281  // update startItem accordingly
2282  if (d->pageMap.count() > 0) { // only if we have any pages
2283  if (d->start == id) {
2284  const int firstId = d->pageMap.constBegin().key();
2285  if (firstId == id) {
2286  if (d->pageMap.count() > 1)
2287  d->start = (++d->pageMap.constBegin()).key(); // secondId
2288  else
2289  d->start = -1; // removing the last page
2290  } else { // startSetByUser has to be "true" here
2291  d->start = firstId;
2292  }
2293  d->startSetByUser = false;
2294  }
2295  }
2296 
2297  if (d->pageMap.contains(id))
2298  emit pageRemoved(id);
2299 
2300  if (!d->history.contains(id)) {
2301  // Case 1: removing a page not in the history
2302  removedPage = d->pageMap.take(id);
2303  d->updateCurrentPage();
2304  } else if (id != d->current) {
2305  // Case 2: removing a page in the history before the current page
2306  removedPage = d->pageMap.take(id);
2307  d->history.removeOne(id);
2308  d->_q_updateButtonStates();
2309  } else if (d->history.count() == 1) {
2310  // Case 3: removing the current page which is the first (and only) one in the history
2311  d->reset();
2312  removedPage = d->pageMap.take(id);
2313  if (d->pageMap.isEmpty())
2314  d->updateCurrentPage();
2315  else
2316  restart();
2317  } else {
2318  // Case 4: removing the current page which is not the first one in the history
2319  back();
2320  removedPage = d->pageMap.take(id);
2321  d->updateCurrentPage();
2322  }
2323 
2324  if (removedPage) {
2325  if (d->initialized.contains(id)) {
2326  cleanupPage(id);
2327  d->initialized.remove(id);
2328  }
2329 
2330  d->pageVBoxLayout->removeWidget(removedPage);
2331 
2332  for (int i = d->fields.count() - 1; i >= 0; --i) {
2333  if (d->fields.at(i).page == removedPage) {
2334  removedPage->d_func()->pendingFields += d->fields.at(i);
2335  d->removeFieldAt(i);
2336  }
2337  }
2338  }
2339 }
2340 
2349 QWizardPage *QWizard::page(int theid) const
2350 {
2351  Q_D(const QWizard);
2352  return d->pageMap.value(theid);
2353 }
2354 
2365 bool QWizard::hasVisitedPage(int theid) const
2366 {
2367  Q_D(const QWizard);
2368  return d->history.contains(theid);
2369 }
2370 
2379 QList<int> QWizard::visitedPages() const
2380 {
2381  Q_D(const QWizard);
2382  return d->history;
2383 }
2384 
2389 QList<int> QWizard::pageIds() const
2390 {
2391  Q_D(const QWizard);
2392  return d->pageMap.keys();
2393 }
2394 
2405 void QWizard::setStartId(int theid)
2406 {
2407  Q_D(QWizard);
2408  int newStart = theid;
2409  if (theid == -1)
2410  newStart = d->pageMap.count() ? d->pageMap.constBegin().key() : -1;
2411 
2412  if (d->start == newStart) {
2413  d->startSetByUser = theid != -1;
2414  return;
2415  }
2416 
2417  if (!d->pageMap.contains(newStart)) {
2418  kWarning() << "Invalid page ID " << newStart;
2419  return;
2420  }
2421  d->start = newStart;
2422  d->startSetByUser = theid != -1;
2423 }
2424 
2425 int QWizard::startId() const
2426 {
2427  Q_D(const QWizard);
2428  return d->start;
2429 }
2430 
2439 QWizardPage *QWizard::currentPage() const
2440 {
2441  Q_D(const QWizard);
2442  return page(d->current);
2443 }
2444 
2457 int QWizard::currentId() const
2458 {
2459  Q_D(const QWizard);
2460  return d->current;
2461 }
2462 
2470 void QWizard::setField(const QString &name, const QVariant &value)
2471 {
2472  Q_D(QWizard);
2473 
2474  int index = d->fieldIndexMap.value(name, -1);
2475  if (index != -1) {
2476  const QWizardField &field = d->fields.at(index);
2477  if (!field.object->setProperty(field.property, value))
2478  kWarning() << "Couldn't write to property '"
2479  << field.property.constData() << "'";
2480  return;
2481  }
2482 
2483  kWarning() << "No such field '" << qPrintable(name) << "'";
2484 }
2485 
2493 QVariant QWizard::field(const QString &name) const
2494 {
2495  Q_D(const QWizard);
2496 
2497  int index = d->fieldIndexMap.value(name, -1);
2498  if (index != -1) {
2499  const QWizardField &field = d->fields.at(index);
2500  return field.object->property(field.property);
2501  }
2502 
2503  kWarning() << "No such field '" << qPrintable(name) << "'";
2504  return QVariant();
2505 }
2506 
2519 void QWizard::setWizardStyle(WizardStyle style)
2520 {
2521  Q_D(QWizard);
2522 
2523  const bool styleChange = style != d->wizStyle;
2524 
2525 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
2526  const bool aeroStyleChange =
2527  d->vistaInitPending || d->vistaStateChanged || (styleChange && (style == AeroStyle || d->wizStyle == AeroStyle));
2528  d->vistaStateChanged = false;
2529  d->vistaInitPending = false;
2530 #endif
2531 
2532  if (styleChange
2533 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
2534  || aeroStyleChange
2535 #endif
2536  ) {
2537  d->disableUpdates();
2538  d->wizStyle = style;
2539  d->updateButtonTexts();
2540  d->updateLayout();
2541  updateGeometry();
2542  d->enableUpdates();
2543 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
2544  if (aeroStyleChange)
2545  d->handleAeroStyleChange();
2546 #endif
2547  }
2548 }
2549 
2550 QWizard::WizardStyle QWizard::wizardStyle() const
2551 {
2552  Q_D(const QWizard);
2553  return d->wizStyle;
2554 }
2555 
2562 void QWizard::setOption(WizardOption option, bool on)
2563 {
2564  Q_D(QWizard);
2565  if (!(d->opts & option) != !on)
2566  setOptions(d->opts ^ option);
2567 }
2568 
2575 bool QWizard::testOption(WizardOption option) const
2576 {
2577  Q_D(const QWizard);
2578  return (d->opts & option) != 0;
2579 }
2580 
2595 void QWizard::setOptions(WizardOptions options)
2596 {
2597  Q_D(QWizard);
2598 
2599  WizardOptions changed = (options ^ d->opts);
2600  if (!changed)
2601  return;
2602 
2603  d->disableUpdates();
2604 
2605  d->opts = options;
2606  if ((changed & IndependentPages) && !(d->opts & IndependentPages))
2607  d->cleanupPagesNotInHistory();
2608 
2609  if (changed & (NoDefaultButton | HaveHelpButton | HelpButtonOnRight | NoCancelButton
2610  | CancelButtonOnLeft | HaveCustomButton1 | HaveCustomButton2
2611  | HaveCustomButton3)) {
2612  d->updateButtonLayout();
2613  } else if (changed & (NoBackButtonOnStartPage | NoBackButtonOnLastPage
2614  | HaveNextButtonOnLastPage | HaveFinishButtonOnEarlyPages
2615  | DisabledBackButtonOnLastPage)) {
2616  d->_q_updateButtonStates();
2617  }
2618 
2619  d->enableUpdates();
2620  d->updateLayout();
2621 }
2622 
2623 QWizard::WizardOptions QWizard::options() const
2624 {
2625  Q_D(const QWizard);
2626  return d->opts;
2627 }
2628 
2646 void QWizard::setButtonText(WizardButton which, const QString &text)
2647 {
2648  Q_D(QWizard);
2649 
2650  if (!d->ensureButton(which))
2651  return;
2652 
2653  d->buttonCustomTexts.insert(which, text);
2654 
2655  if (!currentPage() || !currentPage()->d_func()->buttonCustomTexts.contains(which))
2656  d->btns[which]->setText(text);
2657 }
2658 
2671 QString QWizard::buttonText(WizardButton which) const
2672 {
2673  Q_D(const QWizard);
2674 
2675  if (!d->ensureButton(which))
2676  return QString();
2677 
2678  if (d->buttonCustomTexts.contains(which))
2679  return d->buttonCustomTexts.value(which);
2680 
2681  const QString defText = buttonDefaultText(d->wizStyle, which, d);
2682  if(!defText.isNull())
2683  return defText;
2684 
2685  return d->btns[which]->text();
2686 }
2687 
2706 void QWizard::setButtonLayout(const QList<WizardButton> &layout)
2707 {
2708  Q_D(QWizard);
2709 
2710  for (int i = 0; i < layout.count(); ++i) {
2711  WizardButton button1 = layout.at(i);
2712 
2713  if (button1 == NoButton || button1 == Stretch)
2714  continue;
2715  if (!d->ensureButton(button1))
2716  return;
2717 
2718  // O(n^2), but n is very small
2719  for (int j = 0; j < i; ++j) {
2720  WizardButton button2 = layout.at(j);
2721  if (button2 == button1) {
2722  kWarning() << "Duplicate button in layout");
2723  return;
2724  }
2725  }
2726  }
2727 
2728  d->buttonsHaveCustomLayout = true;
2729  d->buttonsCustomLayout = layout;
2730  d->updateButtonLayout();
2731 }
2732 
2743 void QWizard::setButton(WizardButton which, QAbstractButton *button)
2744 {
2745  Q_D(QWizard);
2746 
2747  if (uint(which) >= NButtons || d->btns[which] == button)
2748  return;
2749 
2750  if (QAbstractButton *oldButton = d->btns[which]) {
2751  d->buttonLayout->removeWidget(oldButton);
2752  delete oldButton;
2753  }
2754 
2755  d->btns[which] = button;
2756  if (button) {
2757  button->setParent(d->antiFlickerWidget);
2758  d->buttonCustomTexts.insert(which, button->text());
2759  d->connectButton(which);
2760  } else {
2761  d->buttonCustomTexts.remove(which); // ### what about page-specific texts set for 'which'
2762  d->ensureButton(which); // (QWizardPage::setButtonText())? Clear them as well?
2763  }
2764 
2765  d->updateButtonLayout();
2766 }
2767 
2773 QAbstractButton *QWizard::button(WizardButton which) const
2774 {
2775  Q_D(const QWizard);
2776 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
2777  if (d->wizStyle == AeroStyle && which == BackButton)
2778  return d->vistaHelper->backButton();
2779 #endif
2780  if (!d->ensureButton(which))
2781  return 0;
2782  return d->btns[which];
2783 }
2784 
2793 void QWizard::setTitleFormat(Qt::TextFormat format)
2794 {
2795  Q_D(QWizard);
2796  d->titleFmt = format;
2797  d->updateLayout();
2798 }
2799 
2800 Qt::TextFormat QWizard::titleFormat() const
2801 {
2802  Q_D(const QWizard);
2803  return d->titleFmt;
2804 }
2805 
2814 void QWizard::setSubTitleFormat(Qt::TextFormat format)
2815 {
2816  Q_D(QWizard);
2817  d->subTitleFmt = format;
2818  d->updateLayout();
2819 }
2820 
2821 Qt::TextFormat QWizard::subTitleFormat() const
2822 {
2823  Q_D(const QWizard);
2824  return d->subTitleFmt;
2825 }
2826 
2839 void QWizard::setPixmap(WizardPixmap which, const QPixmap &pixmap)
2840 {
2841  Q_D(QWizard);
2842  Q_ASSERT(uint(which) < NPixmaps);
2843  d->defaultPixmaps[which] = pixmap;
2844  d->updatePixmap(which);
2845 }
2846 
2855 QPixmap QWizard::pixmap(WizardPixmap which) const
2856 {
2857  Q_D(const QWizard);
2858  Q_ASSERT(uint(which) < NPixmaps);
2859 #ifdef Q_WS_MAC
2860  if (which == BackgroundPixmap && d->defaultPixmaps[BackgroundPixmap].isNull())
2861  d->defaultPixmaps[BackgroundPixmap] = d->findDefaultBackgroundPixmap();
2862 #endif
2863  return d->defaultPixmaps[which];
2864 }
2865 
2891 void QWizard::setDefaultProperty(const char *className, const char *property,
2892  const char *changedSignal)
2893 {
2894  Q_D(QWizard);
2895  for (int i = d->defaultPropertyTable.count() - 1; i >= 0; --i) {
2896  if (qstrcmp(d->defaultPropertyTable.at(i).className, className) == 0) {
2897  d->defaultPropertyTable.remove(i);
2898  break;
2899  }
2900  }
2901  d->defaultPropertyTable.append(QWizardDefaultProperty(className, property, changedSignal));
2902 }
2903 
2928 void QWizard::setSideWidget(QWidget *widget)
2929 {
2930  Q_D(QWizard);
2931 
2932  d->sideWidget = widget;
2933  if (d->watermarkLabel) {
2934  d->watermarkLabel->setSideWidget(widget);
2935  d->updateLayout();
2936  }
2937 }
2938 
2946 QWidget *QWizard::sideWidget() const
2947 {
2948  Q_D(const QWizard);
2949 
2950  return d->sideWidget;
2951 }
2952 
2956 void QWizard::setVisible(bool visible)
2957 {
2958  Q_D(QWizard);
2959  if (visible) {
2960  if (d->current == -1)
2961  restart();
2962  }
2963  QDialog::setVisible(visible);
2964 }
2965 
2969 QSize QWizard::sizeHint() const
2970 {
2971  Q_D(const QWizard);
2972  QSize result = d->mainLayout->totalSizeHint();
2973 #ifdef Q_WS_S60
2974  QSize extra(QApplication::desktop()->availableGeometry(QCursor::pos()).size());
2975 #else
2976  QSize extra(500, 360);
2977 #endif
2978  if (d->wizStyle == MacStyle && d->current != -1) {
2979  QSize pixmap(currentPage()->pixmap(BackgroundPixmap).size());
2980  extra.setWidth(616);
2981  if (!pixmap.isNull()) {
2982  extra.setHeight(pixmap.height());
2983 
2984  /*
2985  The width isn't always reliable as a size hint, as
2986  some wizard backgrounds just cover the leftmost area.
2987  Use a rule of thumb to determine if the width is
2988  reliable or not.
2989  */
2990  if (pixmap.width() >= pixmap.height())
2991  extra.setWidth(pixmap.width());
2992  }
2993  }
2994  return result.expandedTo(extra);
2995 }
2996 
3076 void QWizard::back()
3077 {
3078  Q_D(QWizard);
3079  int n = d->history.count() - 2;
3080  if (n < 0)
3081  return;
3082  d->switchToPage(d->history.at(n), QWizardPrivate::Backward);
3083 }
3084 
3092 void QWizard::next()
3093 {
3094  Q_D(QWizard);
3095 
3096  if (d->current == -1)
3097  return;
3098 
3099  if (validateCurrentPage()) {
3100  int next = nextId();
3101  if (next != -1) {
3102  if (d->history.contains(next)) {
3103  kWarning() << "Page " << next << " already met";
3104  return;
3105  }
3106  if (!d->pageMap.contains(next)) {
3107  kWarning() << "No such page " << next;
3108  return;
3109  }
3110  d->switchToPage(next, QWizardPrivate::Forward);
3111  }
3112  }
3113 }
3114 
3121 void QWizard::restart()
3122 {
3123  Q_D(QWizard);
3124  d->disableUpdates();
3125  d->reset();
3126  d->switchToPage(startId(), QWizardPrivate::Forward);
3127  d->enableUpdates();
3128 }
3129 
3133 bool QWizard::event(QEvent *event)
3134 {
3135  Q_D(QWizard);
3136  if (event->type() == QEvent::StyleChange) { // Propagate style
3137  d->setStyle(style());
3138  d->updateLayout();
3139  }
3140 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
3141  else if (event->type() == QEvent::Show && d->vistaInitPending) {
3142  d->vistaInitPending = false;
3143  d->wizStyle = AeroStyle;
3144  d->handleAeroStyleChange();
3145  }
3146  else if (d->isVistaThemeEnabled()) {
3147  d->vistaHelper->mouseEvent(event);
3148  }
3149 #endif
3150  return QDialog::event(event);
3151 }
3152 
3156 void QWizard::resizeEvent(QResizeEvent *event)
3157 {
3158  Q_D(QWizard);
3159  int heightOffset = 0;
3160 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
3161  if (d->isVistaThemeEnabled()) {
3162  heightOffset = d->vistaHelper->topOffset();
3163  if (d->isVistaThemeEnabled(QVistaHelper::VistaAero))
3164  heightOffset += d->vistaHelper->titleBarSize();
3165  }
3166 #endif
3167  d->topWidget->resize(event->size().width(), event->size().height() - heightOffset);
3168 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
3169  if (d->isVistaThemeEnabled())
3170  d->vistaHelper->resizeEvent(event);
3171 #endif
3172  QDialog::resizeEvent(event);
3173 }
3174 
3178 void QWizard::paintEvent(QPaintEvent * event)
3179 {
3180  Q_D(QWizard);
3181  if (d->wizStyle == MacStyle && currentPage()) {
3182  QPixmap backgroundPixmap = currentPage()->pixmap(BackgroundPixmap);
3183  if (backgroundPixmap.isNull())
3184  return;
3185 
3186  QPainter painter(this);
3187  painter.drawPixmap(0, (height() - backgroundPixmap.height()) / 2, backgroundPixmap);
3188  }
3189 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
3190  else if (d->isVistaThemeEnabled()) {
3191  if (d->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
3192  QPainter painter(this);
3193  QColor color = d->vistaHelper->basicWindowFrameColor();
3194  painter.fillRect(0, 0, width(), QVistaHelper::topOffset(), color);
3195  }
3196  d->vistaHelper->paintEvent(event);
3197  }
3198 #else
3199  Q_UNUSED(event);
3200 #endif
3201 }
3202 
3203 #if defined(Q_WS_WIN)
3204 
3207 bool QWizard::winEvent(MSG *message, long *result)
3208 {
3209 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
3210  Q_D(QWizard);
3211  if (d->isVistaThemeEnabled()) {
3212  const bool winEventResult = d->vistaHelper->handleWinEvent(message, result);
3213  if (QVistaHelper::vistaState() != d->vistaState) {
3214  d->vistaState = QVistaHelper::vistaState();
3215  d->vistaStateChanged = true;
3216  setWizardStyle(AeroStyle);
3217  }
3218  return winEventResult;
3219  } else {
3220  return QDialog::winEvent(message, result);
3221  }
3222 #else
3223  return QDialog::winEvent(message, result);
3224 #endif
3225 }
3226 #endif
3227 
3231 void QWizard::done(int result)
3232 {
3233  Q_D(QWizard);
3234  // canceling leaves the wizard in a known state
3235  if (result == Rejected) {
3236  d->reset();
3237  } else {
3238  if (!validateCurrentPage())
3239  return;
3240  }
3241  QDialog::done(result);
3242 }
3243 
3262 void QWizard::initializePage(int theid)
3263 {
3264  QWizardPage *page = this->page(theid);
3265  if (page)
3266  page->initializePage();
3267 }
3268 
3280 void QWizard::cleanupPage(int theid)
3281 {
3282  QWizardPage *page = this->page(theid);
3283  if (page)
3284  page->cleanupPage();
3285 }
3286 
3303 bool QWizard::validateCurrentPage()
3304 {
3305  QWizardPage *page = currentPage();
3306  if (!page)
3307  return true;
3308 
3309  return page->validatePage();
3310 }
3311 
3326 int QWizard::nextId() const
3327 {
3328  const QWizardPage *page = currentPage();
3329  if (!page)
3330  return -1;
3331 
3332  return page->nextId();
3333 }
3334 
3410 QWizardPage::QWizardPage(QWidget *parent)
3411  : QWidget(*new QWizardPagePrivate, parent, 0)
3412 {
3413  connect(this, SIGNAL(completeChanged()), this, SLOT(_q_updateCachedCompleteState()));
3414 }
3415 
3430 void QWizardPage::setTitle(const QString &title)
3431 {
3432  Q_D(QWizardPage);
3433  d->title = title;
3434  if (d->wizard && d->wizard->currentPage() == this)
3435  d->wizard->d_func()->updateLayout();
3436 }
3437 
3438 QString QWizardPage::title() const
3439 {
3440  Q_D(const QWizardPage);
3441  return d->title;
3442 }
3443 
3463 void QWizardPage::setSubTitle(const QString &subTitle)
3464 {
3465  Q_D(QWizardPage);
3466  d->subTitle = subTitle;
3467  if (d->wizard && d->wizard->currentPage() == this)
3468  d->wizard->d_func()->updateLayout();
3469 }
3470 
3471 QString QWizardPage::subTitle() const
3472 {
3473  Q_D(const QWizardPage);
3474  return d->subTitle;
3475 }
3476 
3490 void QWizardPage::setPixmap(QWizard::WizardPixmap which, const QPixmap &pixmap)
3491 {
3492  Q_D(QWizardPage);
3493  Q_ASSERT(uint(which) < QWizard::NPixmaps);
3494  d->pixmaps[which] = pixmap;
3495  if (d->wizard && d->wizard->currentPage() == this)
3496  d->wizard->d_func()->updatePixmap(which);
3497 }
3498 
3508 QPixmap QWizardPage::pixmap(QWizard::WizardPixmap which) const
3509 {
3510  Q_D(const QWizardPage);
3511  Q_ASSERT(uint(which) < QWizard::NPixmaps);
3512 
3513  const QPixmap &pixmap = d->pixmaps[which];
3514  if (!pixmap.isNull())
3515  return pixmap;
3516 
3517  if (wizard())
3518  return wizard()->pixmap(which);
3519 
3520  return pixmap;
3521 }
3522 
3540 void QWizardPage::initializePage()
3541 {
3542 }
3543 
3555 void QWizardPage::cleanupPage()
3556 {
3557  Q_D(QWizardPage);
3558  if (d->wizard) {
3559  QVector<QWizardField> &fields = d->wizard->d_func()->fields;
3560  for (int i = 0; i < fields.count(); ++i) {
3561  const QWizardField &field = fields.at(i);
3562  if (field.page == this)
3563  field.object->setProperty(field.property, field.initialValue);
3564  }
3565  }
3566 }
3567 
3582 bool QWizardPage::validatePage()
3583 {
3584  return true;
3585 }
3586 
3604 bool QWizardPage::isComplete() const
3605 {
3606  Q_D(const QWizardPage);
3607 
3608  if (!d->wizard)
3609  return true;
3610 
3611  const QVector<QWizardField> &wizardFields = d->wizard->d_func()->fields;
3612  for (int i = wizardFields.count() - 1; i >= 0; --i) {
3613  const QWizardField &field = wizardFields.at(i);
3614  if (field.page == this && field.mandatory) {
3615  QVariant value = field.object->property(field.property);
3616  if (value == field.initialValue)
3617  return false;
3618 
3619 #ifndef QT_NO_LINEEDIT
3620  if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(field.object)) {
3621  if (!lineEdit->hasAcceptableInput())
3622  return false;
3623  }
3624 #endif
3625 #ifndef QT_NO_SPINBOX
3626  if (QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(field.object)) {
3627  if (!spinBox->hasAcceptableInput())
3628  return false;
3629  }
3630 #endif
3631  }
3632  }
3633  return true;
3634 }
3635 
3648 void QWizardPage::setFinalPage(bool finalPage)
3649 {
3650  Q_D(QWizardPage);
3651  d->explicitlyFinal = finalPage;
3652  QWizard *wizard = this->wizard();
3653  if (wizard && wizard->currentPage() == this)
3654  wizard->d_func()->updateCurrentPage();
3655 }
3656 
3669 bool QWizardPage::isFinalPage() const
3670 {
3671  Q_D(const QWizardPage);
3672  if (d->explicitlyFinal)
3673  return true;
3674 
3675  QWizard *wizard = this->wizard();
3676  if (wizard && wizard->currentPage() == this) {
3677  // try to use the QWizard implementation if possible
3678  return wizard->nextId() == -1;
3679  } else {
3680  return nextId() == -1;
3681  }
3682 }
3683 
3698 void QWizardPage::setCommitPage(bool commitPage)
3699 {
3700  Q_D(QWizardPage);
3701  d->commit = commitPage;
3702  QWizard *wizard = this->wizard();
3703  if (wizard && wizard->currentPage() == this)
3704  wizard->d_func()->updateCurrentPage();
3705 }
3706 
3712 bool QWizardPage::isCommitPage() const
3713 {
3714  Q_D(const QWizardPage);
3715  return d->commit;
3716 }
3717 
3726 void QWizardPage::setButtonText(QWizard::WizardButton which, const QString &text)
3727 {
3728  Q_D(QWizardPage);
3729  d->buttonCustomTexts.insert(which, text);
3730  if (wizard() && wizard()->currentPage() == this && wizard()->d_func()->btns[which])
3731  wizard()->d_func()->btns[which]->setText(text);
3732 }
3733 
3747 QString QWizardPage::buttonText(QWizard::WizardButton which) const
3748 {
3749  Q_D(const QWizardPage);
3750 
3751  if (d->buttonCustomTexts.contains(which))
3752  return d->buttonCustomTexts.value(which);
3753 
3754  if (wizard())
3755  return wizard()->buttonText(which);
3756 
3757  return QString();
3758 }
3759 
3776 int QWizardPage::nextId() const
3777 {
3778  Q_D(const QWizardPage);
3779 
3780  if (!d->wizard)
3781  return -1;
3782 
3783  bool foundCurrentPage = false;
3784 
3785  const QWizardPrivate::PageMap &pageMap = d->wizard->d_func()->pageMap;
3786  QWizardPrivate::PageMap::const_iterator i = pageMap.constBegin();
3787  QWizardPrivate::PageMap::const_iterator end = pageMap.constEnd();
3788 
3789  for (; i != end; ++i) {
3790  if (i.value() == this) {
3791  foundCurrentPage = true;
3792  } else if (foundCurrentPage) {
3793  return i.key();
3794  }
3795  }
3796  return -1;
3797 }
3798 
3822 void QWizardPage::setField(const QString &name, const QVariant &value)
3823 {
3824  Q_D(QWizardPage);
3825  if (!d->wizard)
3826  return;
3827  d->wizard->setField(name, value);
3828 }
3829 
3843 QVariant QWizardPage::field(const QString &name) const
3844 {
3845  Q_D(const QWizardPage);
3846  if (!d->wizard)
3847  return QVariant();
3848  return d->wizard->field(name);
3849 }
3850 
3897 void QWizardPage::registerField(const QString &name, QWidget *widget, const char *property,
3898  const char *changedSignal)
3899 {
3900  Q_D(QWizardPage);
3901  QWizardField field(this, name, widget, property, changedSignal);
3902  if (d->wizard) {
3903  d->wizard->d_func()->addField(field);
3904  } else {
3905  d->pendingFields += field;
3906  }
3907 }
3908 
3915 QWizard *QWizardPage::wizard() const
3916 {
3917  Q_D(const QWizardPage);
3918  return d->wizard;
3919 }
3920 
3921 #include "moc_qwizard.cpp"
QWizard::restart
void restart()
Definition: qwizard.cpp:3121
ClassicHMargin
const int ClassicHMargin
Definition: qwizard.cpp:79
QWizardPage::nextId
virtual int nextId() const
Definition: qwizard.cpp:3776
QWizard::ClassicStyle
Definition: qwizard.h:90
QWizard::paintEvent
void paintEvent(QPaintEvent *event)
Definition: qwizard.cpp:3178
flags
static const char * flags[]
Definition: readerstatus.cpp:115
QWizard::NStandardButtons
Definition: qwizard.h:77
QWizardPage::setTitle
void setTitle(const QString &title)
Definition: qwizard.cpp:3430
QWizard::hasVisitedPage
bool hasVisitedPage(int id) const
Definition: qwizard.cpp:2365
QWizard::setButton
void setButton(WizardButton which, QAbstractButton *button)
Definition: qwizard.cpp:2743
QWizardPage::field
QVariant field(const QString &name) const
Definition: qwizard.cpp:3843
QWizard::WizardButton
WizardButton
Definition: qwizard.h:64
MacLayoutRightMargin
const int MacLayoutRightMargin
Definition: qwizard.cpp:83
QWizard::resizeEvent
void resizeEvent(QResizeEvent *event)
Definition: qwizard.cpp:3156
QWizardPage::completeChanged
void completeChanged()
QWizard::HaveCustomButton1
Definition: qwizard.h:111
QWizard::ExtendedWatermarkPixmap
Definition: qwizard.h:100
QWizard::WatermarkPixmap
Definition: qwizard.h:82
QWizard::setWizardStyle
void setWizardStyle(WizardStyle style)
Definition: qwizard.cpp:2519
QWizard::BackButton
Definition: qwizard.h:65
QWizardPage::wizard
QWizard * wizard() const
Definition: qwizard.cpp:3915
QWizard::HelpButtonOnRight
Definition: qwizard.h:110
QWizard::setDefaultProperty
void setDefaultProperty(const char *className, const char *property, const char *changedSignal)
Definition: qwizard.cpp:2891
changeSpacerSize
static void changeSpacerSize(QLayout *layout, int index, int width, int height)
Definition: qwizard.cpp:86
QWizardPage::title
QString title() const
changedSignal
const char * changedSignal
Definition: qwizard.cpp:131
QWizard::HaveCustomButton3
Definition: qwizard.h:113
QDialog
QWizardPage::setField
void setField(const QString &name, const QVariant &value)
Definition: qwizard.cpp:3822
QWizardPage
The QWizardPage class is the base class for wizard pages.
Definition: qwizard.h:206
buttonDefaultText
static QString buttonDefaultText(int wstyle, int which, const QWizardPrivate *wizardPrivate)
Definition: qwizard.cpp:674
NFallbackDefaultProperties
const int NFallbackDefaultProperties
Definition: qwizard.cpp:126
QWizard::pageAdded
void pageAdded(int id)
QWizard::done
void done(int result)
Definition: qwizard.cpp:3231
QWizardPage::validatePage
virtual bool validatePage()
Definition: qwizard.cpp:3582
QWizard::field
QVariant field(const QString &name) const
Definition: qwizard.cpp:2493
QWizard::CustomButton2
Definition: qwizard.h:72
QWidget
QWizard::NoBackButtonOnLastPage
Definition: qwizard.h:103
iWantTheFocus
static QWidget * iWantTheFocus(QWidget *ancestor)
Definition: qwizard.cpp:94
QWizard::setOption
void setOption(WizardOption option, bool on=true)
Definition: qwizard.cpp:2562
QWizard::NoDefaultButton
Definition: qwizard.h:101
QWizard::AeroStyle
Definition: qwizard.h:93
QWizardPage::isCommitPage
bool isCommitPage() const
Definition: qwizard.cpp:3712
QWizard::cleanupPage
virtual void cleanupPage(int id)
Definition: qwizard.cpp:3280
QWizard::HaveCustomButton2
Definition: qwizard.h:112
resolve
static QStringList resolve(const QStringList &paths, const QStringList &blacklist, const QStringList &whitelist)
Definition: filesystemwatcher.cpp:272
option
const char * option
Definition: kleopatraapplication.cpp:91
QWizard::CancelButtonOnLeft
Definition: qwizard.h:108
QWizard::IndependentPages
Definition: qwizard.h:98
QScrollArea
QWizard::currentId
int currentId() const
QWizardPage::cleanupPage
virtual void cleanupPage()
Definition: qwizard.cpp:3555
className
const char * className
Definition: qwizard.cpp:129
QWizard::pageRemoved
void pageRemoved(int id)
image
static QString image(const char *img)
Definition: task.cpp:213
QWizard::BannerPixmap
Definition: qwizard.h:84
fallbackProperties
const struct @9 fallbackProperties[NFallbackDefaultProperties]
QWizard::validateCurrentPage
virtual bool validateCurrentPage()
Definition: qwizard.cpp:3303
MacLayoutBottomMargin
const int MacLayoutBottomMargin
Definition: qwizard.cpp:84
QWizardPage::setFinalPage
void setFinalPage(bool finalPage)
Definition: qwizard.cpp:3648
QWizard::Stretch
Definition: qwizard.h:74
QWizard::button
QAbstractButton * button(WizardButton which) const
Definition: qwizard.cpp:2773
QWizard::HaveNextButtonOnLastPage
Definition: qwizard.h:105
QWizard::CommitButton
Definition: qwizard.h:67
d
#define d
Definition: adduseridcommand.cpp:90
QWizard::setSubTitleFormat
void setSubTitleFormat(Qt::TextFormat format)
Definition: qwizard.cpp:2814
QWizardPage::setCommitPage
void setCommitPage(bool commitPage)
Definition: qwizard.cpp:3698
QWizard::addPage
int addPage(QWizardPage *page)
Definition: qwizard.cpp:2199
QWizard::QWizard
QWizard(QWidget *parent=0, Qt::WindowFlags flags=0)
Definition: qwizard.cpp:2175
QWizard::wizardStyle
WizardStyle wizardStyle() const
QWizard::pixmap
QPixmap pixmap(WizardPixmap which) const
Definition: qwizard.cpp:2855
QWizard::event
bool event(QEvent *event)
Definition: qwizard.cpp:3133
QWizard::setButtonText
void setButtonText(WizardButton which, const QString &text)
Definition: qwizard.cpp:2646
QWizard::pageIds
QList< int > pageIds() const
Definition: qwizard.cpp:2389
QWizard::WizardOption
WizardOption
Definition: qwizard.h:97
QWizard::sizeHint
QSize sizeHint() const
Definition: qwizard.cpp:2969
QWizard::CustomButton3
Definition: qwizard.h:73
QWizardPage::setButtonText
void setButtonText(QWizard::WizardButton which, const QString &text)
Definition: qwizard.cpp:3726
QWizard::titleFormat
Qt::TextFormat titleFormat() const
QWizardPage::subTitle
QString subTitle
the subtitle of the page
Definition: qwizard.h:210
QWizard::setSideWidget
void setSideWidget(QWidget *widget)
Definition: qwizard.cpp:2928
QWizard::DisabledBackButtonOnLastPage
Definition: qwizard.h:104
QWizard::NoButton
Definition: qwizard.h:76
QWizard::setStartId
void setStartId(int id)
Definition: qwizard.cpp:2405
QWizard::startId
int startId() const
QWizard::NextButton
Definition: qwizard.h:66
QWizard::back
void back()
Definition: qwizard.cpp:3076
ModernHeaderTopMargin
const int ModernHeaderTopMargin
Definition: qwizard.cpp:78
qwizard.h
QWizard::setButtonLayout
void setButtonLayout(const QList< WizardButton > &layout)
Definition: qwizard.cpp:2706
QWizard::LogoPixmap
Definition: qwizard.h:83
QWizard::NButtons
Definition: qwizard.h:78
QWizard::HelpButton
Definition: qwizard.h:70
Kleo::Crypto::operator!=
bool operator!=(const Recipient &lhs, const Recipient &rhs)
Definition: recipient.h:92
QWizard::setTitleFormat
void setTitleFormat(Qt::TextFormat format)
Definition: qwizard.cpp:2793
MacLayoutLeftMargin
const int MacLayoutLeftMargin
Definition: qwizard.cpp:81
QWizard::next
void next()
Definition: qwizard.cpp:3092
KMime::Types::operator==
static bool operator==(const AddrSpec &lhs, const AddrSpec &rhs)
Definition: recipient.cpp:55
QWizard::initializePage
virtual void initializePage(int id)
Definition: qwizard.cpp:3262
QWizard::setField
void setField(const QString &name, const QVariant &value)
Definition: qwizard.cpp:2470
QWizardPage::isFinalPage
bool isFinalPage() const
Definition: qwizard.cpp:3669
QWizardPage::subTitle
QString subTitle() const
QWizard::options
WizardOptions options() const
QWizard::CancelButton
Definition: qwizard.h:69
QWizard::MacStyle
Definition: qwizard.h:92
QWizard::~QWizard
~QWizard()
Definition: qwizard.cpp:2185
QWizardPage::setPixmap
void setPixmap(QWizard::WizardPixmap which, const QPixmap &pixmap)
Definition: qwizard.cpp:3490
QWizard::currentPage
QWizardPage * currentPage() const
Definition: qwizard.cpp:2439
QWizard::WizardStyle
WizardStyle
Definition: qwizard.h:89
QWizard::setOptions
void setOptions(WizardOptions options)
Definition: qwizard.cpp:2595
QWizard::NoCancelButton
Definition: qwizard.h:107
QWizardPage::pixmap
QPixmap pixmap(QWizard::WizardPixmap which) const
Definition: qwizard.cpp:3508
QWizardPage::QWizardPage
QWizardPage(QWidget *parent=0)
Definition: qwizard.cpp:3410
QWizard::HaveHelpButton
Definition: qwizard.h:109
property
const char * property
Definition: qwizard.cpp:130
QWizardPage::title
QString title
the title of the page
Definition: qwizard.h:209
q
#define q
Definition: adduseridcommand.cpp:91
buttonSlots
static const char *const buttonSlots[QWizard::NStandardButtons]
Definition: qwizard.cpp:895
QWizard::CustomButton1
Definition: qwizard.h:71
QWizardPage::buttonText
QString buttonText(QWizard::WizardButton which) const
Definition: qwizard.cpp:3747
QWizard::FinishButton
Definition: qwizard.h:68
QWizard::nextId
virtual int nextId() const
Definition: qwizard.cpp:3326
QWizard::HaveFinishButtonOnEarlyPages
Definition: qwizard.h:106
name
const char * name
Definition: uiserver/selectcertificatecommand.cpp:114
QWizard::setPixmap
void setPixmap(WizardPixmap which, const QPixmap &pixmap)
Definition: qwizard.cpp:2839
QWizard::page
QWizardPage * page(int id) const
Definition: qwizard.cpp:2349
QWizard::subTitleFormat
Qt::TextFormat subTitleFormat() const
QWizard::buttonText
QString buttonText(WizardButton which) const
Definition: qwizard.cpp:2671
QWizard::removePage
void removePage(int id)
Definition: qwizard.cpp:2275
extension
static const char * extension(bool pgp, bool sign, bool encrypt, bool ascii, bool detached)
Definition: signencryptfilescontroller.cpp:285
QWizard::IgnoreSubTitles
Definition: qwizard.h:99
QWizard::visitedPages
QList< int > visitedPages() const
Definition: qwizard.cpp:2379
QWizard::testOption
bool testOption(WizardOption option) const
Definition: qwizard.cpp:2575
QWizardPage::initializePage
virtual void initializePage()
Definition: qwizard.cpp:3540
QWizard::WizardPixmap
WizardPixmap
Definition: qwizard.h:81
QWizardPage::isComplete
virtual bool isComplete() const
Definition: qwizard.cpp:3604
GapBetweenLogoAndRightEdge
const int GapBetweenLogoAndRightEdge
Definition: qwizard.cpp:77
objectInheritsXAndXIsCloserThanY
static bool objectInheritsXAndXIsCloserThanY(const QObject *object, const QByteArray &classX, const QByteArray &classY)
Definition: qwizard.cpp:112
MacButtonTopMargin
const int MacButtonTopMargin
Definition: qwizard.cpp:80
QWizard::NPixmaps
Definition: qwizard.h:86
QWizard::setPage
void setPage(int id, QWizardPage *page)
Definition: qwizard.cpp:2219
QMap< int, QString >
QWizard::ModernStyle
Definition: qwizard.h:91
QWizard::BackgroundPixmap
Definition: qwizard.h:85
QWizard::NoBackButtonOnStartPage
Definition: qwizard.h:102
QWizard::sideWidget
QWidget * sideWidget() const
Definition: qwizard.cpp:2946
QWizard
The QWizard class provides a framework for wizards.
Definition: qwizard.h:51
QWizard::setVisible
void setVisible(bool visible)
Definition: qwizard.cpp:2956
QWizardPage::setSubTitle
void setSubTitle(const QString &subTitle)
Definition: qwizard.cpp:3463
QList< int >
QWizardPage::registerField
void registerField(const QString &name, QWidget *widget, const char *property=0, const char *changedSignal=0)
Definition: qwizard.cpp:3897
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:56:41 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kleopatra

Skip menu "kleopatra"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal