modernize: Use auto where the type is clear from context
[quassel.git] / src / qtui / settingsdlg.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include "settingsdlg.h"
22
23 #include <QMessageBox>
24 #include <QPushButton>
25
26 #include "client.h"
27 #include "icon.h"
28
29 SettingsDlg::SettingsDlg(QWidget *parent)
30     : QDialog(parent)
31 {
32     ui.setupUi(this);
33     setModal(true);
34     setAttribute(Qt::WA_DeleteOnClose, true);
35     setWindowIcon(icon::get("configure"));
36
37     updateGeometry();
38
39     ui.settingsTree->setRootIsDecorated(false);
40
41     connect(ui.settingsTree, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelected()));
42     connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *)));
43
44     connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), SLOT(coreConnectionStateChanged()));
45
46     setButtonStates();
47 }
48
49
50 void SettingsDlg::coreConnectionStateChanged()
51 {
52     for (int i = 0; i < ui.settingsTree->topLevelItemCount(); i++) {
53         QTreeWidgetItem *catItem = ui.settingsTree->topLevelItem(i);
54         for (int j = 0; j < catItem->childCount(); j++) {
55             QTreeWidgetItem *item = catItem->child(j);
56             setItemState(item);
57         }
58         setItemState(catItem);
59     }
60 }
61
62
63 void SettingsDlg::setItemState(QTreeWidgetItem *item)
64 {
65     auto *sp = qobject_cast<SettingsPage *>(item->data(0, SettingsPageRole).value<QObject *>());
66     Q_ASSERT(sp);
67     bool disabledDueToConnection = !Client::isConnected() && sp->needsCoreConnection();
68     bool disabledDueToOwnChoice = !sp->isSelectable();
69     item->setDisabled(disabledDueToConnection || disabledDueToOwnChoice);
70 }
71
72
73 void SettingsDlg::registerSettingsPage(SettingsPage *sp)
74 {
75     sp->setParent(ui.settingsStack);
76     ui.settingsStack->addWidget(sp);
77
78     connect(sp, SIGNAL(changed(bool)), this, SLOT(setButtonStates()));
79
80     QTreeWidgetItem *cat;
81     QList<QTreeWidgetItem *> cats = ui.settingsTree->findItems(sp->category(), Qt::MatchExactly);
82     if (!cats.count()) {
83         cat = new QTreeWidgetItem(ui.settingsTree, QStringList(sp->category()));
84         cat->setExpanded(true);
85         cat->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
86     }
87     else {
88         cat = cats[0];
89     }
90
91     QTreeWidgetItem *item;
92     if (sp->title().isEmpty())
93         item = cat;
94     else
95         item = new QTreeWidgetItem(cat, QStringList(sp->title()));
96
97     item->setData(0, SettingsPageRole, QVariant::fromValue<QObject *>(sp));
98     pageIsLoaded[sp] = false;
99     if (!ui.settingsTree->selectedItems().count())
100         ui.settingsTree->setCurrentItem(item);
101
102     setItemState(item);
103 }
104
105
106 void SettingsDlg::selectPage(SettingsPage *sp)
107 {
108     if (!sp) {
109         _currentPage = nullptr;
110         ui.settingsStack->setCurrentIndex(0);
111         ui.pageTitle->setText(tr("Settings"));
112         return;
113     }
114
115     if (!pageIsLoaded[sp]) {
116         sp->load();
117         pageIsLoaded[sp] = true;
118     }
119
120     if (sp != currentPage() && currentPage() != nullptr && currentPage()->hasChanged()) {
121         int ret = QMessageBox::warning(this, tr("Save changes"),
122             tr("There are unsaved changes on the current configuration page. Would you like to apply your changes now?"),
123             QMessageBox::Discard|QMessageBox::Save|QMessageBox::Cancel, QMessageBox::Cancel);
124         if (ret == QMessageBox::Save) {
125             if (!applyChanges()) sp = currentPage();
126         }
127         else if (ret == QMessageBox::Discard) {
128             undoChanges();
129         }
130         else sp = currentPage();
131     }
132
133     if (sp != currentPage()) {
134         if (sp->title().isEmpty()) {
135             ui.pageTitle->setText(sp->category());
136             setWindowTitle(tr("Configure %1").arg(sp->category()));
137         }
138         else {
139             ui.pageTitle->setText(sp->title());
140             setWindowTitle(tr("Configure %1").arg(sp->title()));
141         }
142
143         ui.settingsStack->setCurrentWidget(sp);
144         _currentPage = sp;
145     }
146     setButtonStates();
147 }
148
149
150 void SettingsDlg::itemSelected()
151 {
152     QList<QTreeWidgetItem *> items = ui.settingsTree->selectedItems();
153     SettingsPage *sp = nullptr;
154     if (!items.isEmpty()) {
155         sp = qobject_cast<SettingsPage *>(items[0]->data(0, SettingsPageRole).value<QObject *>());
156     }
157     selectPage(sp);
158 }
159
160
161 void SettingsDlg::setButtonStates()
162 {
163     SettingsPage *sp = currentPage();
164     ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged());
165     ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged());
166     ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(sp && sp->hasDefaults());
167 }
168
169
170 void SettingsDlg::buttonClicked(QAbstractButton *button)
171 {
172     switch (ui.buttonBox->standardButton(button)) {
173     case QDialogButtonBox::Ok:
174         if (currentPage() && currentPage()->hasChanged()) {
175             if (applyChanges()) accept();
176         }
177         else accept();
178         break;
179     case QDialogButtonBox::Apply:
180         applyChanges();
181         break;
182     case QDialogButtonBox::Cancel:
183         undoChanges();
184         reject();
185         break;
186     case QDialogButtonBox::Reset:
187         reload();
188         break;
189     case QDialogButtonBox::RestoreDefaults:
190         loadDefaults();
191         break;
192     default:
193         break;
194     }
195 }
196
197
198 bool SettingsDlg::applyChanges()
199 {
200     if (!currentPage()) return false;
201     if (currentPage()->aboutToSave()) {
202         currentPage()->save();
203         return true;
204     }
205     return false;
206 }
207
208
209 void SettingsDlg::undoChanges()
210 {
211     if (currentPage()) {
212         currentPage()->load();
213     }
214 }
215
216
217 void SettingsDlg::reload()
218 {
219     if (!currentPage()) return;
220     int ret = QMessageBox::question(this, tr("Reload Settings"), tr("Do you like to reload the settings, undoing your changes on this page?"),
221         QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
222     if (ret == QMessageBox::Yes) {
223         currentPage()->load();
224     }
225 }
226
227
228 void SettingsDlg::loadDefaults()
229 {
230     if (!currentPage()) return;
231     int ret = QMessageBox::question(this, tr("Restore Defaults"), tr("Do you like to restore the default values for this page?"),
232         QMessageBox::RestoreDefaults|QMessageBox::Cancel, QMessageBox::Cancel);
233     if (ret == QMessageBox::RestoreDefaults) {
234         currentPage()->defaults();
235     }
236 }