cmake: avoid de-duplication of user's CXXFLAGS
[quassel.git] / src / qtui / settingsdlg.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2022 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, &QTreeWidget::itemSelectionChanged, this, &SettingsDlg::itemSelected);
42     connect(ui.buttonBox, &QDialogButtonBox::clicked, this, &SettingsDlg::buttonClicked);
43
44     connect(Client::instance(), &Client::coreConnectionStateChanged, this, &SettingsDlg::coreConnectionStateChanged);
45
46     setButtonStates();
47 }
48
49 void SettingsDlg::coreConnectionStateChanged()
50 {
51     for (int i = 0; i < ui.settingsTree->topLevelItemCount(); i++) {
52         QTreeWidgetItem* catItem = ui.settingsTree->topLevelItem(i);
53         for (int j = 0; j < catItem->childCount(); j++) {
54             QTreeWidgetItem* item = catItem->child(j);
55             setItemState(item);
56         }
57         setItemState(catItem);
58     }
59 }
60
61 void SettingsDlg::setItemState(QTreeWidgetItem* item)
62 {
63     auto* sp = qobject_cast<SettingsPage*>(item->data(0, SettingsPageRole).value<QObject*>());
64     Q_ASSERT(sp);
65     bool disabledDueToConnection = !Client::isConnected() && sp->needsCoreConnection();
66     bool disabledDueToOwnChoice = !sp->isSelectable();
67     item->setDisabled(disabledDueToConnection || disabledDueToOwnChoice);
68 }
69
70 void SettingsDlg::registerSettingsPage(SettingsPage* sp)
71 {
72     sp->setParent(ui.settingsStack);
73     ui.settingsStack->addWidget(sp);
74
75     connect(sp, &SettingsPage::changed, this, &SettingsDlg::setButtonStates);
76
77     QTreeWidgetItem* cat;
78     QList<QTreeWidgetItem*> cats = ui.settingsTree->findItems(sp->category(), Qt::MatchExactly);
79     if (!cats.count()) {
80         cat = new QTreeWidgetItem(ui.settingsTree, QStringList(sp->category()));
81         cat->setExpanded(true);
82         cat->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
83     }
84     else {
85         cat = cats[0];
86     }
87
88     QTreeWidgetItem* item;
89     if (sp->title().isEmpty())
90         item = cat;
91     else
92         item = new QTreeWidgetItem(cat, QStringList(sp->title()));
93
94     item->setData(0, SettingsPageRole, QVariant::fromValue(sp));
95     pageIsLoaded[sp] = false;
96     if (!ui.settingsTree->selectedItems().count())
97         ui.settingsTree->setCurrentItem(item);
98
99     setItemState(item);
100 }
101
102 void SettingsDlg::selectPage(SettingsPage* sp)
103 {
104     if (!sp) {
105         _currentPage = nullptr;
106         ui.settingsStack->setCurrentIndex(0);
107         ui.pageTitle->setText(tr("Settings"));
108         return;
109     }
110
111     if (!pageIsLoaded[sp]) {
112         sp->load();
113         pageIsLoaded[sp] = true;
114     }
115
116     if (sp != currentPage() && currentPage() != nullptr && currentPage()->hasChanged()) {
117         int ret = QMessageBox::
118             warning(this,
119                     tr("Save changes"),
120                     tr("There are unsaved changes on the current configuration page. Would you like to apply your changes now?"),
121                     QMessageBox::Discard | QMessageBox::Save | QMessageBox::Cancel,
122                     QMessageBox::Cancel);
123         if (ret == QMessageBox::Save) {
124             if (!applyChanges())
125                 sp = currentPage();
126         }
127         else if (ret == QMessageBox::Discard) {
128             undoChanges();
129         }
130         else
131             sp = currentPage();
132     }
133
134     if (sp != currentPage()) {
135         if (sp->title().isEmpty()) {
136             ui.pageTitle->setText(sp->category());
137             setWindowTitle(tr("Configure %1").arg(sp->category()));
138         }
139         else {
140             ui.pageTitle->setText(sp->title());
141             setWindowTitle(tr("Configure %1").arg(sp->title()));
142         }
143
144         ui.settingsStack->setCurrentWidget(sp);
145         _currentPage = sp;
146     }
147     setButtonStates();
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 void SettingsDlg::setButtonStates()
161 {
162     SettingsPage* sp = currentPage();
163     ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged());
164     ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged());
165     ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(sp && sp->hasDefaults());
166 }
167
168 void SettingsDlg::buttonClicked(QAbstractButton* button)
169 {
170     switch (ui.buttonBox->standardButton(button)) {
171     case QDialogButtonBox::Ok:
172         if (currentPage() && currentPage()->hasChanged()) {
173             if (applyChanges())
174                 accept();
175         }
176         else
177             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 bool SettingsDlg::applyChanges()
198 {
199     if (!currentPage())
200         return false;
201     if (currentPage()->aboutToSave()) {
202         currentPage()->save();
203         return true;
204     }
205     return false;
206 }
207
208 void SettingsDlg::undoChanges()
209 {
210     if (currentPage()) {
211         currentPage()->load();
212     }
213 }
214
215 void SettingsDlg::reload()
216 {
217     if (!currentPage())
218         return;
219     int ret = QMessageBox::question(this,
220                                     tr("Reload Settings"),
221                                     tr("Do you like to reload the settings, undoing your changes on this page?"),
222                                     QMessageBox::Yes | QMessageBox::No,
223                                     QMessageBox::No);
224     if (ret == QMessageBox::Yes) {
225         currentPage()->load();
226     }
227 }
228
229 void SettingsDlg::loadDefaults()
230 {
231     if (!currentPage())
232         return;
233     int ret = QMessageBox::question(this,
234                                     tr("Restore Defaults"),
235                                     tr("Do you like to restore the default values for this page?"),
236                                     QMessageBox::RestoreDefaults | QMessageBox::Cancel,
237                                     QMessageBox::Cancel);
238     if (ret == QMessageBox::RestoreDefaults) {
239         currentPage()->defaults();
240     }
241 }