Introduce automagic child widget handling in SettingsPage
[quassel.git] / src / uisupport / settingspage.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-08 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) any later version.                                   *
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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include "settingspage.h"
22
23 #include <QCheckBox>
24 #include <QComboBox>
25 #include <QSpinBox>
26 #include <QVariant>
27
28 #include <QDebug>
29
30 #include "uisettings.h"
31
32 SettingsPage::SettingsPage(const QString &category, const QString &title, QWidget *parent)
33   : QWidget(parent),
34     _category(category),
35     _title(title),
36     _changed(false)
37 {
38 }
39
40 void SettingsPage::setChangedState(bool hasChanged_) {
41   if(hasChanged_ != _changed) {
42     bool old = hasChanged();
43     _changed = hasChanged_;
44     if(hasChanged() != old)
45       emit changed(hasChanged());
46   }
47 }
48
49 void SettingsPage::load(QCheckBox *box, bool checked) {
50   box->setProperty("StoredValue", checked);
51   box->setChecked(checked);
52 }
53
54 bool SettingsPage::hasChanged(QCheckBox *box) {
55   return box->property("StoredValue").toBool() == box->isChecked();
56 }
57
58
59 void SettingsPage::load(QComboBox *box, int index) {
60   box->setProperty("StoredValue", index);
61   box->setCurrentIndex(index);
62 }
63
64 bool SettingsPage::hasChanged(QComboBox *box) {
65   return box->property("StoredValue").toInt() == box->currentIndex();
66 }
67
68 void SettingsPage::load(QSpinBox *box, int value) {
69   box->setProperty("StoredValue", value);
70   box->setValue(value);
71 }
72
73 bool SettingsPage::hasChanged(QSpinBox *box) {
74   return box->property("StoredValue").toInt() == box->value();
75 }
76
77 /*** Auto child widget handling ***/
78
79 void SettingsPage::initAutoWidgets() {
80   _autoWidgets.clear();
81
82   if(settingsKey().isNull())
83     return;
84
85   // find all descendants that should be considered auto widgets
86   // we need to climb the QObject tree recursively
87   findAutoWidgets(this, &_autoWidgets);
88
89   foreach(QObject *widget, _autoWidgets) {
90     if(widget->inherits("QAbstractButton"))
91       connect(widget, SIGNAL(toggled(bool)), SLOT(autoWidgetHasChanged()));
92     else if(widget->inherits("QLineEdit") || widget->inherits("QTextEdit"))
93       connect(widget, SIGNAL(textChanged(const QString &)), SLOT(autoWidgetHasChanged()));
94     else if(widget->inherits("QComboBox"))
95       connect(widget, SIGNAL(currentIndexChanged(int)), SLOT(autoWidgetHasChanged()));
96     else if(widget->inherits("QSpinBox"))
97       connect(widget, SIGNAL(valueChanged(int)), SLOT(autoWidgetHasChanged()));
98     else
99       qWarning() << "SettingsPage::init(): Unknown autoWidget type" << widget->metaObject()->className();
100   }
101 }
102
103 void SettingsPage::findAutoWidgets(QObject *parent, QObjectList *autoList) const {
104   foreach(QObject *child, parent->children()) {
105     if(!child->property("settingsKey").toString().isEmpty())
106       autoList->append(child);
107     findAutoWidgets(child, autoList);
108   }
109 }
110
111 QByteArray SettingsPage::autoWidgetPropertyName(QObject *widget) const {
112   QByteArray prop;
113   if(widget->inherits("QAbstractButton"))
114     prop = "checked";
115   else if(widget->inherits("QLineEdit") || widget->inherits("QTextEdit"))
116     prop = "text";
117   else if(widget->inherits("QComboBox"))
118     prop = "currentIndex";
119   else if(widget->inherits("QSpinBox"))
120     prop = "value";
121   else
122     qWarning() << "SettingsPage::autoWidgetPropertyName(): Unhandled widget type for" << widget;
123
124   return prop;
125 }
126
127 QString SettingsPage::autoWidgetSettingsKey(QObject *widget) const {
128   QString key = widget->property("settingsKey").toString();
129   if(key.startsWith('/'))
130     key.remove(0, 1);
131   else
132     key.prepend(settingsKey() + '/');
133   return key;
134 }
135
136 void SettingsPage::autoWidgetHasChanged() {
137   bool changed_ = false;
138   foreach(QObject *widget, _autoWidgets) {
139     QVariant curValue = widget->property(autoWidgetPropertyName(widget));
140     if(!curValue.isValid())
141       qWarning() << "SettingsPage::autoWidgetHasChanged(): Unknown property";
142
143     if(curValue != widget->property("storedValue")) {
144       changed_ = true;
145       break;
146     }
147   }
148
149   if(changed_ != _autoWidgetsChanged) {
150     bool old = hasChanged();
151     _autoWidgetsChanged = changed_;
152     if(hasChanged() != old)
153       emit changed(hasChanged());
154   }
155 }
156
157 void SettingsPage::load() {
158   UiSettings s("");
159   foreach(QObject *widget, _autoWidgets) {
160     QVariant val = s.value(autoWidgetSettingsKey(widget), widget->property("defaultValue"));
161     widget->setProperty(autoWidgetPropertyName(widget), val);
162     widget->setProperty("storedValue", val);
163   }
164   bool old = hasChanged();
165   _autoWidgetsChanged = _changed = false;
166   if(hasChanged() != old)
167     emit changed(hasChanged());
168 }
169
170 void SettingsPage::save() {
171   UiSettings s("");
172   foreach(QObject *widget, _autoWidgets) {
173     QVariant val = widget->property(autoWidgetPropertyName(widget));
174     widget->setProperty("storedValue", val);
175     s.setValue(autoWidgetSettingsKey(widget), val);
176   }
177   bool old = hasChanged();
178   _autoWidgetsChanged = _changed = false;
179   if(hasChanged() != old)
180     emit changed(hasChanged());
181 }
182
183 void SettingsPage::defaults() {
184   foreach(QObject *widget, _autoWidgets) {
185     QVariant val = widget->property("defaultValue");
186     widget->setProperty(autoWidgetPropertyName(widget), val);
187   }
188   autoWidgetHasChanged();
189 }