File indexing completed on 2025-02-02 14:19:56
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2006 Olivier Goffart <ogoffart at kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "kassistantdialog.h" 0009 0010 #include "kpagedialog_p.h" 0011 #include <QApplication> 0012 #include <QDialogButtonBox> 0013 #include <QIcon> 0014 #include <QPushButton> 0015 0016 #include <QHash> 0017 0018 class KAssistantDialogPrivate : public KPageDialogPrivate 0019 { 0020 Q_DECLARE_PUBLIC(KAssistantDialog) 0021 Q_DECLARE_TR_FUNCTIONS(KAssistantDialog) 0022 0023 public: 0024 KAssistantDialogPrivate(KAssistantDialog *qq) 0025 : KPageDialogPrivate(qq) 0026 { 0027 } 0028 0029 QHash<KPageWidgetItem *, bool> valid; 0030 QHash<KPageWidgetItem *, bool> appropriate; 0031 KPageWidgetModel *pageModel = nullptr; 0032 QPushButton *backButton = nullptr; 0033 QPushButton *nextButton = nullptr; 0034 QPushButton *finishButton = nullptr; 0035 0036 void init(); 0037 void slotUpdateButtons(); 0038 0039 QModelIndex getNext(QModelIndex nextIndex) 0040 { 0041 QModelIndex currentIndex; 0042 do { 0043 currentIndex = nextIndex; 0044 nextIndex = pageModel->index(0, 0, currentIndex); 0045 if (!nextIndex.isValid()) { 0046 nextIndex = currentIndex.sibling(currentIndex.row() + 1, 0); 0047 } 0048 } while (nextIndex.isValid() && !appropriate.value(pageModel->item(nextIndex), true)); 0049 return nextIndex; 0050 } 0051 0052 QModelIndex getPrevious(QModelIndex nextIndex) 0053 { 0054 QModelIndex currentIndex; 0055 do { 0056 currentIndex = nextIndex; 0057 nextIndex = currentIndex.sibling(currentIndex.row() - 1, 0); 0058 if (!nextIndex.isValid()) { 0059 nextIndex = currentIndex.parent(); 0060 } 0061 } while (nextIndex.isValid() && !appropriate.value(pageModel->item(nextIndex), true)); 0062 return nextIndex; 0063 } 0064 }; 0065 0066 KAssistantDialog::KAssistantDialog(QWidget *parent, Qt::WindowFlags flags) 0067 : KPageDialog(*new KAssistantDialogPrivate(this), nullptr, parent, flags) 0068 { 0069 Q_D(KAssistantDialog); 0070 0071 d->init(); 0072 // workaround to get the page model 0073 KPageWidget *pagewidget = findChild<KPageWidget *>(); 0074 Q_ASSERT(pagewidget); 0075 d->pageModel = static_cast<KPageWidgetModel *>(pagewidget->model()); 0076 } 0077 0078 KAssistantDialog::KAssistantDialog(KPageWidget *widget, QWidget *parent, Qt::WindowFlags flags) 0079 : KPageDialog(*new KAssistantDialogPrivate(this), widget, parent, flags) 0080 { 0081 Q_D(KAssistantDialog); 0082 0083 d->init(); 0084 d->pageModel = static_cast<KPageWidgetModel *>(widget->model()); 0085 } 0086 0087 KAssistantDialog::~KAssistantDialog() = default; 0088 0089 void KAssistantDialogPrivate::init() 0090 { 0091 Q_Q(KAssistantDialog); 0092 0093 QDialogButtonBox *buttonBox = q->buttonBox(); 0094 0095 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Help); 0096 backButton = new QPushButton; 0097 0098 const QString iconBack = QApplication::isRightToLeft() ? QStringLiteral("go-next") : QStringLiteral("go-previous"); 0099 const QString iconNext = QApplication::isRightToLeft() ? QStringLiteral("go-previous") : QStringLiteral("go-next"); 0100 backButton->setText(tr("&Back", "@action:button go back")); 0101 backButton->setIcon(QIcon::fromTheme(iconBack)); 0102 backButton->setToolTip(tr("Go back one step", "@info:tooltip")); 0103 q->connect(backButton, &QAbstractButton::clicked, q, &KAssistantDialog::back); 0104 buttonBox->addButton(backButton, QDialogButtonBox::ActionRole); 0105 0106 nextButton = new QPushButton; 0107 nextButton->setText(tr("Next", "@action:button Opposite to Back")); 0108 nextButton->setIcon(QIcon::fromTheme(iconNext)); 0109 nextButton->setDefault(true); 0110 q->connect(nextButton, &QAbstractButton::clicked, q, &KAssistantDialog::next); 0111 buttonBox->addButton(nextButton, QDialogButtonBox::ActionRole); 0112 0113 finishButton = new QPushButton; 0114 finishButton->setText(tr("Finish", "@action:button")); 0115 finishButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply"))); 0116 buttonBox->addButton(finishButton, QDialogButtonBox::AcceptRole); 0117 0118 q->setFaceType(KPageDialog::Plain); 0119 0120 q->connect(q, &KAssistantDialog::currentPageChanged, q, [this]() { 0121 slotUpdateButtons(); 0122 }); 0123 } 0124 0125 void KAssistantDialog::back() 0126 { 0127 Q_D(KAssistantDialog); 0128 0129 QModelIndex nextIndex = d->getPrevious(d->pageModel->index(currentPage())); 0130 if (nextIndex.isValid()) { 0131 setCurrentPage(d->pageModel->item(nextIndex)); 0132 } 0133 } 0134 0135 void KAssistantDialog::next() 0136 { 0137 Q_D(KAssistantDialog); 0138 0139 QModelIndex nextIndex = d->getNext(d->pageModel->index(currentPage())); 0140 if (nextIndex.isValid()) { 0141 setCurrentPage(d->pageModel->item(nextIndex)); 0142 } else if (isValid(currentPage())) { 0143 accept(); 0144 } 0145 } 0146 0147 void KAssistantDialog::setValid(KPageWidgetItem *page, bool enable) 0148 { 0149 Q_D(KAssistantDialog); 0150 0151 d->valid[page] = enable; 0152 if (page == currentPage()) { 0153 d->slotUpdateButtons(); 0154 } 0155 } 0156 0157 bool KAssistantDialog::isValid(KPageWidgetItem *page) const 0158 { 0159 Q_D(const KAssistantDialog); 0160 0161 return d->valid.value(page, true); 0162 } 0163 0164 void KAssistantDialogPrivate::slotUpdateButtons() 0165 { 0166 Q_Q(KAssistantDialog); 0167 0168 QModelIndex currentIndex = pageModel->index(q->currentPage()); 0169 // change the title of the next/finish button 0170 QModelIndex nextIndex = getNext(currentIndex); 0171 finishButton->setEnabled(!nextIndex.isValid() && q->isValid(q->currentPage())); 0172 nextButton->setEnabled(nextIndex.isValid() && q->isValid(q->currentPage())); 0173 finishButton->setDefault(!nextIndex.isValid()); 0174 nextButton->setDefault(nextIndex.isValid()); 0175 // enable or disable the back button; 0176 nextIndex = getPrevious(currentIndex); 0177 backButton->setEnabled(nextIndex.isValid()); 0178 } 0179 0180 void KAssistantDialog::showEvent(QShowEvent *event) 0181 { 0182 Q_D(KAssistantDialog); 0183 0184 d->slotUpdateButtons(); // called because last time that function was called is when the first page was added, so the next button show "finish" 0185 KPageDialog::showEvent(event); 0186 } 0187 0188 void KAssistantDialog::setAppropriate(KPageWidgetItem *page, bool appropriate) 0189 { 0190 Q_D(KAssistantDialog); 0191 0192 d->appropriate[page] = appropriate; 0193 d->slotUpdateButtons(); 0194 } 0195 0196 bool KAssistantDialog::isAppropriate(KPageWidgetItem *page) const 0197 { 0198 Q_D(const KAssistantDialog); 0199 0200 return d->appropriate.value(page, true); 0201 } 0202 0203 QPushButton *KAssistantDialog::backButton() const 0204 { 0205 Q_D(const KAssistantDialog); 0206 0207 return d->backButton; 0208 } 0209 0210 QPushButton *KAssistantDialog::nextButton() const 0211 { 0212 Q_D(const KAssistantDialog); 0213 0214 return d->nextButton; 0215 } 0216 0217 QPushButton *KAssistantDialog::finishButton() const 0218 { 0219 Q_D(const KAssistantDialog); 0220 0221 return d->finishButton; 0222 } 0223 0224 #include "moc_kassistantdialog.cpp"