1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
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
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
36 #include <QtCore/QMap>
37 #include <QtCore/QHash>
38 #include <QtCore/QVariant>
40 #include <QtGui/QLabel>
41 #include <QtGui/QVBoxLayout>
42 #include <QtGui/QHBoxLayout>
43 #include <QtGui/QStyle>
45 /*! \class Utils::Wizard
47 \brief A wizard with a progress bar on the left.
49 Informs the user about the progress.
54 class ProgressItemWidget : public QWidget
58 ProgressItemWidget(const QPixmap &indicatorPixmap, const QString &title, QWidget *parent = 0)
60 m_indicatorVisible(false),
61 m_indicatorPixmap(indicatorPixmap)
63 m_indicatorLabel = new QLabel(this);
64 m_indicatorLabel->setFixedSize(m_indicatorPixmap.size());
65 m_titleLabel = new QLabel(title, this);
66 QHBoxLayout *l = new QHBoxLayout(this);
68 l->addWidget(m_indicatorLabel);
69 l->addWidget(m_titleLabel);
71 void setIndicatorVisible(bool visible) {
72 if (m_indicatorVisible == visible)
74 m_indicatorVisible = visible;
75 if (m_indicatorVisible)
76 m_indicatorLabel->setPixmap(m_indicatorPixmap);
78 m_indicatorLabel->setPixmap(QPixmap());
80 void setTitle(const QString &title) {
81 m_titleLabel->setText(title);
83 void setWordWrap(bool wrap) {
84 m_titleLabel->setWordWrap(wrap);
88 bool m_indicatorVisible;
89 QPixmap m_indicatorPixmap;
90 QLabel *m_indicatorLabel;
94 class LinearProgressWidget : public QWidget
98 LinearProgressWidget(WizardProgress *progress, QWidget *parent = 0);
101 void slotItemAdded(WizardProgressItem *item);
102 void slotItemRemoved(WizardProgressItem *item);
103 void slotItemChanged(WizardProgressItem *item);
104 void slotNextItemsChanged(WizardProgressItem *item, const QList<WizardProgressItem *> &nextItems);
105 void slotNextShownItemChanged(WizardProgressItem *item, WizardProgressItem *nextItem);
106 void slotStartItemChanged(WizardProgressItem *item);
107 void slotCurrentItemChanged(WizardProgressItem *item);
110 void recreateLayout();
111 void updateProgress();
112 void disableUpdates();
113 void enableUpdates();
115 QVBoxLayout *m_mainLayout;
116 QVBoxLayout *m_itemWidgetLayout;
117 WizardProgress *m_wizardProgress;
118 QMap<WizardProgressItem *, ProgressItemWidget *> m_itemToItemWidget;
119 QMap<ProgressItemWidget *, WizardProgressItem *> m_itemWidgetToItem;
120 QList<WizardProgressItem *> m_visibleItems;
121 ProgressItemWidget *m_dotsItemWidget;
122 int m_disableUpdatesCount;
123 QPixmap m_indicatorPixmap;
126 LinearProgressWidget::LinearProgressWidget(WizardProgress *progress, QWidget *parent)
130 m_disableUpdatesCount(0)
132 m_indicatorPixmap = QIcon::fromTheme(QLatin1String("go-next"), QIcon(QLatin1String(":/utils/images/arrow.png"))).pixmap(16);
133 m_wizardProgress = progress;
134 m_mainLayout = new QVBoxLayout(this);
135 m_itemWidgetLayout = new QVBoxLayout();
136 QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding);
137 m_mainLayout->addLayout(m_itemWidgetLayout);
138 m_mainLayout->addSpacerItem(spacer);
140 m_dotsItemWidget = new ProgressItemWidget(m_indicatorPixmap, tr("..."), this);
141 m_dotsItemWidget->setVisible(false);
142 m_dotsItemWidget->setEnabled(false);
144 connect(m_wizardProgress, SIGNAL(itemAdded(WizardProgressItem *)),
145 this, SLOT(slotItemAdded(WizardProgressItem *)));
146 connect(m_wizardProgress, SIGNAL(itemRemoved(WizardProgressItem *)),
147 this, SLOT(slotItemRemoved(WizardProgressItem *)));
148 connect(m_wizardProgress, SIGNAL(itemChanged(WizardProgressItem *)),
149 this, SLOT(slotItemChanged(WizardProgressItem *)));
150 connect(m_wizardProgress, SIGNAL(nextItemsChanged(WizardProgressItem *, const QList<WizardProgressItem *> &)),
151 this, SLOT(slotNextItemsChanged(WizardProgressItem *, const QList<WizardProgressItem *> &)));
152 connect(m_wizardProgress, SIGNAL(nextShownItemChanged(WizardProgressItem *, WizardProgressItem *)),
153 this, SLOT(slotNextShownItemChanged(WizardProgressItem *, WizardProgressItem *)));
154 connect(m_wizardProgress, SIGNAL(startItemChanged(WizardProgressItem *)),
155 this, SLOT(slotStartItemChanged(WizardProgressItem *)));
156 connect(m_wizardProgress, SIGNAL(currentItemChanged(WizardProgressItem *)),
157 this, SLOT(slotCurrentItemChanged(WizardProgressItem *)));
159 QList<WizardProgressItem *> items = m_wizardProgress->items();
160 for (int i = 0; i < items.count(); i++)
161 slotItemAdded(items.at(i));
164 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
167 void LinearProgressWidget::slotItemAdded(WizardProgressItem *item)
169 ProgressItemWidget *itemWidget = new ProgressItemWidget(m_indicatorPixmap, item->title(), this);
170 itemWidget->setVisible(false);
171 itemWidget->setWordWrap(item->titleWordWrap());
172 m_itemToItemWidget.insert(item, itemWidget);
173 m_itemWidgetToItem.insert(itemWidget, item);
176 void LinearProgressWidget::slotItemRemoved(WizardProgressItem *item)
178 ProgressItemWidget *itemWidget = m_itemToItemWidget.value(item);
182 m_itemWidgetToItem.remove(itemWidget);
183 m_itemToItemWidget.remove(item);
190 void LinearProgressWidget::slotItemChanged(WizardProgressItem *item)
192 ProgressItemWidget *itemWidget = m_itemToItemWidget.value(item);
196 itemWidget->setTitle(item->title());
197 itemWidget->setWordWrap(item->titleWordWrap());
200 void LinearProgressWidget::slotNextItemsChanged(WizardProgressItem *item, const QList<WizardProgressItem *> &nextItems)
203 if (m_visibleItems.contains(item))
207 void LinearProgressWidget::slotNextShownItemChanged(WizardProgressItem *item, WizardProgressItem *nextItem)
210 if (m_visibleItems.contains(item))
214 void LinearProgressWidget::slotStartItemChanged(WizardProgressItem *item)
220 void LinearProgressWidget::slotCurrentItemChanged(WizardProgressItem *item)
223 if (m_wizardProgress->directlyReachableItems() == m_visibleItems)
229 void LinearProgressWidget::recreateLayout()
233 QMap<WizardProgressItem *, ProgressItemWidget *>::ConstIterator it = m_itemToItemWidget.constBegin();
234 QMap<WizardProgressItem *, ProgressItemWidget *>::ConstIterator itEnd = m_itemToItemWidget.constEnd();
235 while (it != itEnd) {
236 it.value()->setVisible(false);
239 m_dotsItemWidget->setVisible(false);
241 for (int i = m_itemWidgetLayout->count() - 1; i >= 0; --i) {
242 QLayoutItem *item = m_itemWidgetLayout->takeAt(i);
246 m_visibleItems = m_wizardProgress->directlyReachableItems();
247 for (int i = 0; i < m_visibleItems.count(); i++) {
248 ProgressItemWidget *itemWidget = m_itemToItemWidget.value(m_visibleItems.at(i));
249 m_itemWidgetLayout->addWidget(itemWidget);
250 itemWidget->setVisible(true);
253 if (!m_wizardProgress->isFinalItemDirectlyReachable()) {
254 m_itemWidgetLayout->addWidget(m_dotsItemWidget);
255 m_dotsItemWidget->setVisible(true);
262 void LinearProgressWidget::updateProgress()
266 QList<WizardProgressItem *> visitedItems = m_wizardProgress->visitedItems();
268 QMap<WizardProgressItem *, ProgressItemWidget *>::ConstIterator it = m_itemToItemWidget.constBegin();
269 QMap<WizardProgressItem *, ProgressItemWidget *>::ConstIterator itEnd = m_itemToItemWidget.constEnd();
270 while (it != itEnd) {
271 WizardProgressItem *item = it.key();
272 ProgressItemWidget *itemWidget = it.value();
273 itemWidget->setEnabled(visitedItems.contains(item));
274 itemWidget->setIndicatorVisible(false);
278 WizardProgressItem *currentItem = m_wizardProgress->currentItem();
279 ProgressItemWidget *currentItemWidget = m_itemToItemWidget.value(currentItem);
280 if (currentItemWidget)
281 currentItemWidget->setIndicatorVisible(true);
286 void LinearProgressWidget::disableUpdates()
288 if (m_disableUpdatesCount++ == 0) {
289 setUpdatesEnabled(false);
294 void LinearProgressWidget::enableUpdates()
296 if (--m_disableUpdatesCount == 0) {
298 setUpdatesEnabled(true);
305 Q_DECLARE_PUBLIC(Wizard)
310 m_automaticProgressCreation(true),
314 bool m_automaticProgressCreation;
315 WizardProgress *m_wizardProgress;
318 Wizard::Wizard(QWidget *parent, Qt::WindowFlags flags) :
319 QWizard(parent, flags), d_ptr(new WizardPrivate)
322 d_ptr->m_wizardProgress = new WizardProgress(this);
323 connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(_q_currentPageChanged(int)));
324 connect(this, SIGNAL(pageAdded(int)), this, SLOT(_q_pageAdded(int)));
325 connect(this, SIGNAL(pageRemoved(int)), this, SLOT(_q_pageRemoved(int)));
326 setSideWidget(new LinearProgressWidget(d_ptr->m_wizardProgress, this));
334 bool Wizard::isAutomaticProgressCreationEnabled() const
338 return d->m_automaticProgressCreation;
341 void Wizard::setAutomaticProgressCreationEnabled(bool enabled)
345 d->m_automaticProgressCreation = enabled;
348 void Wizard::setStartId(int pageId)
352 QWizard::setStartId(pageId);
353 d->m_wizardProgress->setStartPage(startId());
356 WizardProgress *Wizard::wizardProgress() const
360 return d->m_wizardProgress;
363 bool Wizard::validateCurrentPage()
366 return QWizard::validateCurrentPage();
369 void Wizard::_q_currentPageChanged(int pageId)
373 d->m_wizardProgress->setCurrentPage(pageId);
376 void Wizard::_q_pageAdded(int pageId)
380 if (!d->m_automaticProgressCreation)
383 WizardProgressItem *item = d->m_wizardProgress->addItem(page(pageId)->title());
384 item->addPage(pageId);
385 d->m_wizardProgress->setStartPage(startId());
386 if (!d->m_wizardProgress->startItem())
389 QList<int> pages = pageIds();
390 int index = pages.indexOf(pageId);
394 prevId = pages.at(index - 1);
395 if (index < pages.count() - 1)
396 nextId = pages.at(index + 1);
398 WizardProgressItem *prevItem = 0;
399 WizardProgressItem *nextItem = 0;
402 prevItem = d->m_wizardProgress->item(prevId);
404 nextItem = d->m_wizardProgress->item(nextId);
407 prevItem->setNextItems(QList<WizardProgressItem *>() << item);
409 item->setNextItems(QList<WizardProgressItem *>() << nextItem);
412 void Wizard::_q_pageRemoved(int pageId)
416 if (!d->m_automaticProgressCreation)
419 WizardProgressItem *item = d->m_wizardProgress->item(pageId);
420 d->m_wizardProgress->removePage(pageId);
421 d->m_wizardProgress->setStartPage(startId());
423 if (!item->pages().isEmpty())
426 QList<int> pages = pageIds();
427 int index = pages.indexOf(pageId);
431 prevId = pages.at(index - 1);
432 if (index < pages.count() - 1)
433 nextId = pages.at(index + 1);
435 WizardProgressItem *prevItem = 0;
436 WizardProgressItem *nextItem = 0;
439 prevItem = d->m_wizardProgress->item(prevId);
441 nextItem = d->m_wizardProgress->item(nextId);
443 if (prevItem && nextItem) {
444 QList<WizardProgressItem *> nextItems = prevItem->nextItems();
445 nextItems.removeOne(item);
446 if (!nextItems.contains(nextItem))
447 nextItems.append(nextItem);
448 prevItem->setNextItems(nextItems);
450 d->m_wizardProgress->removeItem(item);
456 class WizardProgressPrivate
458 WizardProgress *q_ptr;
459 Q_DECLARE_PUBLIC(WizardProgress)
462 WizardProgressPrivate()
469 bool isNextItem(WizardProgressItem *item, WizardProgressItem *nextItem) const;
470 // if multiple paths are possible the empty list is returned
471 QList<WizardProgressItem *> singlePathBetween(WizardProgressItem *fromItem, WizardProgressItem *toItem) const;
472 void updateReachableItems();
474 QMap<int, WizardProgressItem *> m_pageToItem;
475 QMap<WizardProgressItem *, WizardProgressItem *> m_itemToItem;
477 QList<WizardProgressItem *> m_items;
479 QList<WizardProgressItem *> m_visitedItems;
480 QList<WizardProgressItem *> m_reachableItems;
482 WizardProgressItem *m_currentItem;
483 WizardProgressItem *m_startItem;
486 class WizardProgressItemPrivate
488 WizardProgressItem *q_ptr;
489 Q_DECLARE_PUBLIC(WizardProgressItem)
492 bool m_titleWordWrap;
493 WizardProgress *m_wizardProgress;
495 QList<WizardProgressItem *> m_nextItems;
496 QList<WizardProgressItem *> m_prevItems;
497 WizardProgressItem *m_nextShownItem;
500 bool WizardProgressPrivate::isNextItem(WizardProgressItem *item, WizardProgressItem *nextItem) const
502 QHash<WizardProgressItem *, bool> visitedItems;
503 QList<WizardProgressItem *> workingItems = item->nextItems();
504 while (!workingItems.isEmpty()) {
505 WizardProgressItem *workingItem = workingItems.takeFirst();
506 if (workingItem == nextItem)
508 if (visitedItems.contains(workingItem))
510 visitedItems.insert(workingItem, true);
511 workingItems += workingItem->nextItems();
516 QList<WizardProgressItem *> WizardProgressPrivate::singlePathBetween(WizardProgressItem *fromItem, WizardProgressItem *toItem) const
518 WizardProgressItem *item = fromItem;
522 return QList<WizardProgressItem *>();
524 // Optimization. It is workaround for case A->B, B->C, A->C where "from" is A and "to" is C.
525 // When we had X->A in addition and "from" was X and "to" was C, this would not work
526 // (it should return the shortest path which would be X->A->C).
527 if (item->nextItems().contains(toItem))
528 return QList<WizardProgressItem *>() << toItem;
530 QHash<WizardProgressItem *, QHash<WizardProgressItem *, bool> > visitedItemsToParents;
531 QList<QPair<WizardProgressItem *, WizardProgressItem *> > workingItems; // next to prev item
533 QList<WizardProgressItem *> items = item->nextItems();
534 for (int i = 0; i < items.count(); i++)
535 workingItems.append(qMakePair(items.at(i), item));
537 while (!workingItems.isEmpty()) {
538 QPair<WizardProgressItem *, WizardProgressItem *> workingItem = workingItems.takeFirst();
540 QHash<WizardProgressItem *, bool> &parents = visitedItemsToParents[workingItem.first];
541 parents.insert(workingItem.second, true);
542 if (parents.count() > 1)
545 QList<WizardProgressItem *> items = workingItem.first->nextItems();
546 for (int i = 0; i < items.count(); i++)
547 workingItems.append(qMakePair(items.at(i), workingItem.first));
550 QList<WizardProgressItem *> path;
552 WizardProgressItem *it = toItem;
553 QHash<WizardProgressItem *, QHash<WizardProgressItem *, bool> >::ConstIterator itItem = visitedItemsToParents.constFind(it);
554 QHash<WizardProgressItem *, QHash<WizardProgressItem *, bool> >::ConstIterator itEnd = visitedItemsToParents.constEnd();
555 while (itItem != itEnd) {
556 path.prepend(itItem.key());
557 if (itItem.value().count() != 1)
558 return QList<WizardProgressItem *>();
559 it = itItem.value().constBegin().key();
563 itItem = visitedItemsToParents.constFind(it);
565 return QList<WizardProgressItem *>();
568 void WizardProgressPrivate::updateReachableItems()
570 m_reachableItems = m_visitedItems;
571 WizardProgressItem *item = 0;
572 if (m_visitedItems.count() > 0)
573 item = m_visitedItems.last();
576 m_reachableItems.append(item);
580 while (item->nextShownItem()) {
581 item = item->nextShownItem();
582 m_reachableItems.append(item);
587 WizardProgress::WizardProgress(QObject *parent)
588 : QObject(parent), d_ptr(new WizardProgressPrivate)
593 WizardProgress::~WizardProgress()
597 QMap<WizardProgressItem *, WizardProgressItem *>::ConstIterator it = d->m_itemToItem.constBegin();
598 QMap<WizardProgressItem *, WizardProgressItem *>::ConstIterator itEnd = d->m_itemToItem.constEnd();
599 while (it != itEnd) {
606 WizardProgressItem *WizardProgress::addItem(const QString &title)
610 WizardProgressItem *item = new WizardProgressItem(this, title);
611 d->m_itemToItem.insert(item, item);
612 emit itemAdded(item);
616 void WizardProgress::removeItem(WizardProgressItem *item)
620 QMap<WizardProgressItem *, WizardProgressItem *>::iterator it = d->m_itemToItem.find(item);
621 if (it == d->m_itemToItem.end()) {
622 qWarning("WizardProgress::removePage: Item is not a part of the wizard");
626 // remove item from prev items
627 QList<WizardProgressItem *> prevItems = item->d_ptr->m_prevItems;
628 for (int i = 0; i < prevItems.count(); i++) {
629 WizardProgressItem *prevItem = prevItems.at(i);
630 prevItem->d_ptr->m_nextItems.removeOne(item);
633 // remove item from next items
634 QList<WizardProgressItem *> nextItems = item->d_ptr->m_nextItems;
635 for (int i = 0; i < nextItems.count(); i++) {
636 WizardProgressItem *nextItem = nextItems.at(i);
637 nextItem->d_ptr->m_prevItems.removeOne(item);
641 int idx = d->m_visitedItems.indexOf(item);
643 d->m_visitedItems.removeAt(idx);
645 // update reachable items
646 d->updateReachableItems();
648 emit itemRemoved(item);
650 QList<int> pages = item->pages();
651 for (int i = 0; i < pages.count(); i++)
652 d->m_pageToItem.remove(pages.at(i));
653 d->m_itemToItem.erase(it);
657 void WizardProgress::removePage(int pageId)
661 QMap<int, WizardProgressItem *>::iterator it = d->m_pageToItem.find(pageId);
662 if (it == d->m_pageToItem.end()) {
663 qWarning("WizardProgress::removePage: page is not a part of the wizard");
666 WizardProgressItem *item = it.value();
667 d->m_pageToItem.erase(it);
668 item->d_ptr->m_pages.removeOne(pageId);
671 QList<int> WizardProgress::pages(WizardProgressItem *item) const
673 return item->pages();
676 WizardProgressItem *WizardProgress::item(int pageId) const
678 Q_D(const WizardProgress);
680 return d->m_pageToItem.value(pageId);
683 WizardProgressItem *WizardProgress::currentItem() const
685 Q_D(const WizardProgress);
687 return d->m_currentItem;
690 QList<WizardProgressItem *> WizardProgress::items() const
692 Q_D(const WizardProgress);
694 return d->m_itemToItem.keys();
697 WizardProgressItem *WizardProgress::startItem() const
699 Q_D(const WizardProgress);
701 return d->m_startItem;
704 QList<WizardProgressItem *> WizardProgress::visitedItems() const
706 Q_D(const WizardProgress);
708 return d->m_visitedItems;
711 QList<WizardProgressItem *> WizardProgress::directlyReachableItems() const
713 Q_D(const WizardProgress);
715 return d->m_reachableItems;
718 bool WizardProgress::isFinalItemDirectlyReachable() const
720 Q_D(const WizardProgress);
722 if (d->m_reachableItems.isEmpty())
725 return d->m_reachableItems.last()->isFinalItem();
728 void WizardProgress::setCurrentPage(int pageId)
732 if (pageId < 0) { // reset history
733 d->m_currentItem = 0;
734 d->m_visitedItems.clear();
735 d->m_reachableItems.clear();
736 d->updateReachableItems();
740 WizardProgressItem *item = d->m_pageToItem.value(pageId);
742 qWarning("WizardProgress::setCurrentPage: page is not mapped to any wizard progress item");
746 if (d->m_currentItem == item) // nothing changes
749 const bool currentStartItem = !d->m_currentItem && d->m_startItem && d->m_startItem == item;
751 // Check if item is reachable with the provided history or with the next items.
752 const QList<WizardProgressItem *> singleItemPath = d->singlePathBetween(d->m_currentItem, item);
753 const int prevItemIndex = d->m_visitedItems.indexOf(item);
755 if (singleItemPath.isEmpty() && prevItemIndex < 0 && !currentStartItem) {
756 qWarning("WizardProgress::setCurrentPage: new current item is not directly reachable from the old current item");
760 // Update the history accordingly.
761 if (prevItemIndex >= 0) {
762 while (prevItemIndex + 1 < d->m_visitedItems.count())
763 d->m_visitedItems.removeLast();
765 if ((!d->m_currentItem && d->m_startItem && !singleItemPath.isEmpty()) || currentStartItem)
766 d->m_visitedItems += d->m_startItem;
767 d->m_visitedItems += singleItemPath;
770 d->m_currentItem = item;
772 // Update reachable items accordingly.
773 d->updateReachableItems();
775 emit currentItemChanged(item);
778 void WizardProgress::setStartPage(int pageId)
782 WizardProgressItem *item = d->m_pageToItem.value(pageId);
784 qWarning("WizardProgress::setStartPage: page is not mapped to any wizard progress item");
788 d->m_startItem = item;
789 d->updateReachableItems();
791 emit startItemChanged(item);
794 WizardProgressItem::WizardProgressItem(WizardProgress *progress, const QString &title)
795 : d_ptr(new WizardProgressItemPrivate)
798 d_ptr->m_title = title;
799 d_ptr->m_titleWordWrap = false;
800 d_ptr->m_wizardProgress = progress;
801 d_ptr->m_nextShownItem = 0;
804 WizardProgressItem::~WizardProgressItem()
809 void WizardProgressItem::addPage(int pageId)
811 Q_D(WizardProgressItem);
813 if (d->m_wizardProgress->d_ptr->m_pageToItem.contains(pageId)) {
814 qWarning("WizardProgress::addPage: Page is already added to the item");
817 d->m_pages.append(pageId);
818 d->m_wizardProgress->d_ptr->m_pageToItem.insert(pageId, this);
821 QList<int> WizardProgressItem::pages() const
823 Q_D(const WizardProgressItem);
828 void WizardProgressItem::setNextItems(const QList<WizardProgressItem *> &items)
830 Q_D(WizardProgressItem);
832 // check if we create cycle
833 for (int i = 0; i < items.count(); i++) {
834 WizardProgressItem *nextItem = items.at(i);
835 if (nextItem == this || d->m_wizardProgress->d_ptr->isNextItem(nextItem, this)) {
836 qWarning("WizardProgress::setNextItems: Setting one of the next items would create a cycle");
841 if (d->m_nextItems == items) // nothing changes
844 if (!items.contains(d->m_nextShownItem))
847 // update prev items (remove this item from the old next items)
848 for (int i = 0; i < d->m_nextItems.count(); i++) {
849 WizardProgressItem *nextItem = d->m_nextItems.at(i);
850 nextItem->d_ptr->m_prevItems.removeOne(this);
853 d->m_nextItems = items;
855 // update prev items (add this item to the new next items)
856 for (int i = 0; i < d->m_nextItems.count(); i++) {
857 WizardProgressItem *nextItem = d->m_nextItems.at(i);
858 nextItem->d_ptr->m_prevItems.append(this);
861 d->m_wizardProgress->d_ptr->updateReachableItems();
863 emit d->m_wizardProgress->nextItemsChanged(this, items);
865 if (items.count() == 1)
866 setNextShownItem(items.first());
869 QList<WizardProgressItem *> WizardProgressItem::nextItems() const
871 Q_D(const WizardProgressItem);
873 return d->m_nextItems;
876 void WizardProgressItem::setNextShownItem(WizardProgressItem *item)
878 Q_D(WizardProgressItem);
880 if (d->m_nextShownItem == item) // nothing changes
883 if (item && !d->m_nextItems.contains(item)) // the "item" is not a one of next items
886 d->m_nextShownItem = item;
888 d->m_wizardProgress->d_ptr->updateReachableItems();
890 emit d->m_wizardProgress->nextShownItemChanged(this, item);
893 WizardProgressItem *WizardProgressItem::nextShownItem() const
895 Q_D(const WizardProgressItem);
897 return d->m_nextShownItem;
900 bool WizardProgressItem::isFinalItem() const
902 return nextItems().isEmpty();
905 void WizardProgressItem::setTitle(const QString &title)
907 Q_D(WizardProgressItem);
910 emit d->m_wizardProgress->itemChanged(this);
913 QString WizardProgressItem::title() const
915 Q_D(const WizardProgressItem);
920 void WizardProgressItem::setTitleWordWrap(bool wrap)
922 Q_D(WizardProgressItem);
924 d->m_titleWordWrap = wrap;
925 emit d->m_wizardProgress->itemChanged(this);
928 bool WizardProgressItem::titleWordWrap() const
930 Q_D(const WizardProgressItem);
932 return d->m_titleWordWrap;
937 #include "wizard.moc"
938 #include "moc_wizard.cpp"