qtui: Properly fix the SettingsDlg layout
[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 <QIcon>
22 #include <QMessageBox>
23 #include <QPushButton>
24
25 #include "settingsdlg.h"
26
27 #include "client.h"
28
29 SettingsDlg::SettingsDlg(QWidget *parent)
30     : QDialog(parent),
31     _currentPage(0)
32 {
33     ui.setupUi(this);
34     setModal(true);
35     setAttribute(Qt::WA_DeleteOnClose, true);
36     setWindowIcon(QIcon::fromTheme("configure"));
37
38     updateGeometry();
39
40     ui.settingsTree->setRootIsDecorated(false);
41
42     connect(ui.settingsTree, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelected()));
43     connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *)));
44
45     connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), SLOT(coreConnectionStateChanged()));
46
47     setButtonStates();
48 }
49
50
51 void SettingsDlg::coreConnectionStateChanged()
52 {
53     for (int i = 0; i < ui.settingsTree->topLevelItemCount(); i++) {
54         QTreeWidgetItem *catItem = ui.settingsTree->topLevelItem(i);
55         for (int j = 0; j < catItem->childCount(); j++) {
56             QTreeWidgetItem *item = catItem->child(j);
57             setItemState(item);
58         }
59         setItemState(catItem);
60     }
61 }
62
63
64 void SettingsDlg::setItemState(QTreeWidgetItem *item)
65 {
66     SettingsPage *sp = qobject_cast<SettingsPage *>(item->data(0, SettingsPageRole).value<QObject *>());
67     Q_ASSERT(sp);
68     bool disabledDueToConnection = !Client::isConnected() && sp->needsCoreConnection();
69     bool disabledDueToOwnChoice = !sp->isSelectable();
70     item->setDisabled(disabledDueToConnection || disabledDueToOwnChoice);
71 }
72
73
74 void SettingsDlg::registerSettingsPage(SettingsPage *sp)
75 {
76     sp->setParent(ui.settingsStack);
77     ui.settingsStack->addWidget(sp);
78
79     connect(sp, SIGNAL(changed(bool)), this, SLOT(setButtonStates()));
80
81     QTreeWidgetItem *cat;
82     QList<QTreeWidgetItem *> cats = ui.settingsTree->findItems(sp->category(), Qt::MatchExactly);
83     if (!cats.count()) {
84         cat = new QTreeWidgetItem(ui.settingsTree, QStringList(sp->category()));
85         cat->setExpanded(true);
86         cat->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
87     }
88     else {
89         cat = cats[0];
90     }
91
92     QTreeWidgetItem *item;
93     if (sp->title().isEmpty())
94         item = cat;
95     else
96         item = new QTreeWidgetItem(cat, QStringList(sp->title()));
97
98     item->setData(0, SettingsPageRole, QVariant::fromValue<QObject *>(sp));
99     pageIsLoaded[sp] = false;
100     if (!ui.settingsTree->selectedItems().count())
101         ui.settingsTree->setCurrentItem(item);
102
103     setItemState(item);
104 }
105
106
107 void SettingsDlg::selectPage(SettingsPage *sp)
108 {
109     if (!sp) {
110         _currentPage = 0;
111         ui.settingsStack->setCurrentIndex(0);
112         ui.pageTitle->setText(tr("Settings"));
113         return;
114     }
115
116     if (!pageIsLoaded[sp]) {
117         sp->load();
118         pageIsLoaded[sp] = true;
119     }
120
121     if (sp != currentPage() && currentPage() != 0 && currentPage()->hasChanged()) {
122         int ret = QMessageBox::warning(this, tr("Save changes"),
123             tr("There are unsaved changes on the current configuration page. Would you like to apply your changes now?"),
124             QMessageBox::Discard|QMessageBox::Save|QMessageBox::Cancel, QMessageBox::Cancel);
125         if (ret == QMessageBox::Save) {
126             if (!applyChanges()) sp = currentPage();
127         }
128         else if (ret == QMessageBox::Discard) {
129             undoChanges();
130         }
131         else 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
151 void SettingsDlg::itemSelected()
152 {
153     QList<QTreeWidgetItem *> items = ui.settingsTree->selectedItems();
154     SettingsPage *sp = 0;
155     if (!items.isEmpty()) {
156         sp = qobject_cast<SettingsPage *>(items[0]->data(0, SettingsPageRole).value<QObject *>());
157     }
158     selectPage(sp);
159 }
160
161
162 void SettingsDlg::setButtonStates()
163 {
164     SettingsPage *sp = currentPage();
165     ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged());
166     ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged());
167     ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(sp && sp->hasDefaults());
168 }
169
170
171 void SettingsDlg::buttonClicked(QAbstractButton *button)
172 {
173     switch (ui.buttonBox->standardButton(button)) {
174     case QDialogButtonBox::Ok:
175         if (currentPage() && currentPage()->hasChanged()) {
176             if (applyChanges()) accept();
177         }
178         else accept();
179         break;
180     case QDialogButtonBox::Apply:
181         applyChanges();
182         break;
183     case QDialogButtonBox::Cancel:
184         undoChanges();
185         reject();
186         break;
187     case QDialogButtonBox::Reset:
188         reload();
189         break;
190     case QDialogButtonBox::RestoreDefaults:
191         loadDefaults();
192         break;
193     default:
194         break;
195     }
196 }
197
198
199 bool SettingsDlg::applyChanges()
200 {
201     if (!currentPage()) return false;
202     if (currentPage()->aboutToSave()) {
203         currentPage()->save();
204         return true;
205     }
206     return false;
207 }
208
209
210 void SettingsDlg::undoChanges()
211 {
212     if (currentPage()) {
213         currentPage()->load();
214     }
215 }
216
217
218 void SettingsDlg::reload()
219 {
220     if (!currentPage()) return;
221     int ret = QMessageBox::question(this, tr("Reload Settings"), tr("Do you like to reload the settings, undoing your changes on this page?"),
222         QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
223     if (ret == QMessageBox::Yes) {
224         currentPage()->load();
225     }
226 }
227
228
229 void SettingsDlg::loadDefaults()
230 {
231     if (!currentPage()) return;
232     int ret = QMessageBox::question(this, tr("Restore Defaults"), tr("Do you like to restore the default values for this page?"),
233         QMessageBox::RestoreDefaults|QMessageBox::Cancel, QMessageBox::Cancel);
234     if (ret == QMessageBox::RestoreDefaults) {
235         currentPage()->defaults();
236     }
237 }