File indexing completed on 2024-04-28 15:31:57

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"