1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2006 Olivier Goffart <ogoffart at kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#include "kassistantdialog.h"
9
10#include "kpagedialog_p.h"
11#include <QApplication>
12#include <QDialogButtonBox>
13#include <QIcon>
14#include <QPushButton>
15
16#include <QHash>
17
18class KAssistantDialogPrivate : public KPageDialogPrivate
19{
20 Q_DECLARE_PUBLIC(KAssistantDialog)
21 Q_DECLARE_TR_FUNCTIONS(KAssistantDialog)
22
23public:
24 KAssistantDialogPrivate(KAssistantDialog *qq)
25 : KPageDialogPrivate(qq)
26 {
27 }
28
29 QHash<KPageWidgetItem *, bool> valid;
30 QHash<KPageWidgetItem *, bool> appropriate;
31 KPageWidgetModel *pageModel = nullptr;
32 QPushButton *backButton = nullptr;
33 QPushButton *nextButton = nullptr;
34 QPushButton *finishButton = nullptr;
35
36 void init();
37 void slotUpdateButtons();
38
39 QModelIndex getNext(QModelIndex nextIndex)
40 {
41 QModelIndex currentIndex;
42 do {
43 currentIndex = nextIndex;
44 nextIndex = pageModel->index(row: 0, column: 0, parent: currentIndex);
45 if (!nextIndex.isValid()) {
46 nextIndex = currentIndex.sibling(arow: currentIndex.row() + 1, acolumn: 0);
47 }
48 } while (nextIndex.isValid() && !appropriate.value(key: pageModel->item(index: nextIndex), defaultValue: true));
49 return nextIndex;
50 }
51
52 QModelIndex getPrevious(QModelIndex nextIndex)
53 {
54 QModelIndex currentIndex;
55 do {
56 currentIndex = nextIndex;
57 nextIndex = currentIndex.sibling(arow: currentIndex.row() - 1, acolumn: 0);
58 if (!nextIndex.isValid()) {
59 nextIndex = currentIndex.parent();
60 }
61 } while (nextIndex.isValid() && !appropriate.value(key: pageModel->item(index: nextIndex), defaultValue: true));
62 return nextIndex;
63 }
64};
65
66KAssistantDialog::KAssistantDialog(QWidget *parent, Qt::WindowFlags flags)
67 : KPageDialog(*new KAssistantDialogPrivate(this), nullptr, parent, flags)
68{
69 Q_D(KAssistantDialog);
70
71 d->init();
72 // workaround to get the page model
73 KPageWidget *pagewidget = findChild<KPageWidget *>();
74 Q_ASSERT(pagewidget);
75 d->pageModel = static_cast<KPageWidgetModel *>(pagewidget->model());
76}
77
78KAssistantDialog::KAssistantDialog(KPageWidget *widget, QWidget *parent, Qt::WindowFlags flags)
79 : KPageDialog(*new KAssistantDialogPrivate(this), widget, parent, flags)
80{
81 Q_D(KAssistantDialog);
82
83 d->init();
84 d->pageModel = static_cast<KPageWidgetModel *>(widget->model());
85}
86
87KAssistantDialog::~KAssistantDialog() = default;
88
89void KAssistantDialogPrivate::init()
90{
91 Q_Q(KAssistantDialog);
92
93 QDialogButtonBox *buttonBox = q->buttonBox();
94
95 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Help);
96 backButton = new QPushButton;
97
98 const QString iconBack = QApplication::isRightToLeft() ? QStringLiteral("go-next") : QStringLiteral("go-previous");
99 const QString iconNext = QApplication::isRightToLeft() ? QStringLiteral("go-previous") : QStringLiteral("go-next");
100 backButton->setText(tr(sourceText: "&Back", disambiguation: "@action:button go back"));
101 backButton->setIcon(QIcon::fromTheme(name: iconBack));
102 backButton->setToolTip(tr(sourceText: "Go back one step", disambiguation: "@info:tooltip"));
103 q->connect(sender: backButton, signal: &QAbstractButton::clicked, context: q, slot: &KAssistantDialog::back);
104 buttonBox->addButton(button: backButton, role: QDialogButtonBox::ActionRole);
105
106 nextButton = new QPushButton;
107 nextButton->setText(tr(sourceText: "Next", disambiguation: "@action:button Opposite to Back"));
108 nextButton->setIcon(QIcon::fromTheme(name: iconNext));
109 nextButton->setDefault(true);
110 q->connect(sender: nextButton, signal: &QAbstractButton::clicked, context: q, slot: &KAssistantDialog::next);
111 buttonBox->addButton(button: nextButton, role: QDialogButtonBox::ActionRole);
112
113 finishButton = new QPushButton;
114 finishButton->setText(tr(sourceText: "Finish", disambiguation: "@action:button"));
115 finishButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply")));
116 buttonBox->addButton(button: finishButton, role: QDialogButtonBox::AcceptRole);
117
118 q->setFaceType(KPageDialog::Plain);
119
120 q->connect(sender: q, signal: &KAssistantDialog::currentPageChanged, context: q, slot: [this]() {
121 slotUpdateButtons();
122 });
123}
124
125void KAssistantDialog::back()
126{
127 Q_D(KAssistantDialog);
128
129 QModelIndex nextIndex = d->getPrevious(nextIndex: d->pageModel->index(item: currentPage()));
130 if (nextIndex.isValid()) {
131 setCurrentPage(d->pageModel->item(index: nextIndex));
132 }
133}
134
135void KAssistantDialog::next()
136{
137 Q_D(KAssistantDialog);
138
139 QModelIndex nextIndex = d->getNext(nextIndex: d->pageModel->index(item: currentPage()));
140 if (nextIndex.isValid()) {
141 setCurrentPage(d->pageModel->item(index: nextIndex));
142 } else if (isValid(page: currentPage())) {
143 accept();
144 }
145}
146
147void KAssistantDialog::setValid(KPageWidgetItem *page, bool enable)
148{
149 Q_D(KAssistantDialog);
150
151 d->valid[page] = enable;
152 if (page == currentPage()) {
153 d->slotUpdateButtons();
154 }
155}
156
157bool KAssistantDialog::isValid(KPageWidgetItem *page) const
158{
159 Q_D(const KAssistantDialog);
160
161 return d->valid.value(key: page, defaultValue: true);
162}
163
164void KAssistantDialogPrivate::slotUpdateButtons()
165{
166 Q_Q(KAssistantDialog);
167
168 QModelIndex currentIndex = pageModel->index(item: q->currentPage());
169 // change the title of the next/finish button
170 QModelIndex nextIndex = getNext(nextIndex: currentIndex);
171 finishButton->setEnabled(!nextIndex.isValid() && q->isValid(page: q->currentPage()));
172 nextButton->setEnabled(nextIndex.isValid() && q->isValid(page: q->currentPage()));
173 finishButton->setDefault(!nextIndex.isValid());
174 nextButton->setDefault(nextIndex.isValid());
175 // enable or disable the back button;
176 nextIndex = getPrevious(nextIndex: currentIndex);
177 backButton->setEnabled(nextIndex.isValid());
178}
179
180void KAssistantDialog::showEvent(QShowEvent *event)
181{
182 Q_D(KAssistantDialog);
183
184 d->slotUpdateButtons(); // called because last time that function was called is when the first page was added, so the next button show "finish"
185 KPageDialog::showEvent(event);
186}
187
188void KAssistantDialog::setAppropriate(KPageWidgetItem *page, bool appropriate)
189{
190 Q_D(KAssistantDialog);
191
192 d->appropriate[page] = appropriate;
193 d->slotUpdateButtons();
194}
195
196bool KAssistantDialog::isAppropriate(KPageWidgetItem *page) const
197{
198 Q_D(const KAssistantDialog);
199
200 return d->appropriate.value(key: page, defaultValue: true);
201}
202
203QPushButton *KAssistantDialog::backButton() const
204{
205 Q_D(const KAssistantDialog);
206
207 return d->backButton;
208}
209
210QPushButton *KAssistantDialog::nextButton() const
211{
212 Q_D(const KAssistantDialog);
213
214 return d->nextButton;
215}
216
217QPushButton *KAssistantDialog::finishButton() const
218{
219 Q_D(const KAssistantDialog);
220
221 return d->finishButton;
222}
223
224#include "moc_kassistantdialog.cpp"
225

source code of kwidgetsaddons/src/kassistantdialog.cpp