1 /*
2 * <one line to give the library's name and an idea of what it does.>
3 * Copyright (C) 2013 <copyright holder> <email>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "maindialog.h"
22 #include "ui_maindialog.h"
23 #include <QDebug>
24 #include <QDir>
25 #include <QFile>
26 #include <QFileInfo>
27 #include <QDBusInterface>
28 #include <QDBusConnection>
29 #include <QDialogButtonBox>
30 #include <QColorDialog>
31 #include <QMessageBox>
32
33 // dbus interface of compton
34 #define COMPTON_SERVICE_PREFIX "com.github.chjj.compton."
35 #define COMPTON_PATH "/"
36 #define COMPTON_INTERFACE "com.github.chjj.compton"
37
38
MainDialog(QString userConfigFile)39 MainDialog::MainDialog(QString userConfigFile) {
40 ui = new Ui::MainDialog;
41 ui->setupUi(this);
42
43 if(userConfigFile.isEmpty()) {
44 userConfigFile_ = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
45 if(userConfigFile_.isEmpty()) {
46 userConfigFile_ = QDir::homePath();
47 userConfigFile_ += QLatin1String("/.config");
48 }
49 // QDir configDir = QDir(userConfigFile);
50 // if(!configDir.exists())
51 userConfigFile_ += QLatin1String("/compton.conf");
52 }
53 else
54 userConfigFile_ = userConfigFile;
55
56 config_init(&config_);
57 if(config_read_file(&config_, userConfigFile_.toLocal8Bit().constData()) == CONFIG_FALSE) {
58 // loading user config file failed
59 // try our default example
60 qDebug() << "load fail, try " << COMPTON_CONF_DATA_DIR << "/compton.conf.example";
61 config_read_file(&config_, COMPTON_CONF_DATA_DIR "/compton.conf.example");
62 }
63
64 // set up signal handlers and initial values of the controls
65 connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(onDialogButtonClicked(QAbstractButton*)));
66 connect(ui->aboutButton, SIGNAL(clicked(bool)), SLOT(onAboutButtonClicked()));
67 connect(ui->shadow_color, SIGNAL(clicked(bool)), SLOT(onColorButtonClicked()));
68 double color;
69 shadowColor_.setRedF(config_lookup_float(&config_, "shadow-red", &color) == CONFIG_TRUE ? color : 0.0);
70 shadowColor_.setGreenF(config_lookup_float(&config_, "shadow-green", &color) == CONFIG_TRUE ? color : 0.0);
71 shadowColor_.setBlueF(config_lookup_float(&config_, "shadow-blue", &color) == CONFIG_TRUE ? color : 0.0);
72 updateShadowColorButton();
73
74 // objectNames are kept the same as config file key names.
75 const QList<QWidget*> widgets = findChildren<QWidget*>();
76 QList<QWidget*>::const_iterator i;
77 for(i = widgets.constBegin(); i != widgets.constEnd(); ++i) {
78 QWidget *child = *i;
79 if(!child->isWidgetType() || child->objectName().isEmpty())
80 continue;
81 // objectName uses _ while config file keys uses - as separator.
82 QByteArray keyName = child->objectName().replace(QLatin1Char('_'), QLatin1Char('-')).toLatin1(); // generate config key from objectName.
83 if(child->inherits("QCheckBox")) {
84 int val = -1;
85 if(config_lookup_bool(&config_, keyName.constData(), &val) == CONFIG_TRUE)
86 static_cast<QCheckBox*>(child)->setChecked((bool)val);
87 connect(child, SIGNAL(toggled(bool)), SLOT(onButtonToggled(bool)));
88 }
89 else if(child->inherits("QDoubleSpinBox")) {
90 double val;
91 if(config_lookup_float(&config_, keyName.constData(), &val) == CONFIG_TRUE)
92 static_cast<QDoubleSpinBox*>(child)->setValue(val);
93 connect(child, SIGNAL(valueChanged(double)), SLOT(onSpinValueChanged(double)));
94 }
95 else if(child->inherits("QSpinBox")) {
96 int val;
97 if(config_lookup_int(&config_, keyName.constData(), &val) == CONFIG_TRUE)
98 static_cast<QSpinBox*>(child)->setValue(val);
99 connect(child, SIGNAL(valueChanged(int)), SLOT(onSpinValueChanged(int)));
100 }
101 else if(child->inherits("QRadioButton")) {
102 if(child->parent()->inherits("QGroupBox")) {
103 QByteArray groupKeyName = child->parent()->objectName().replace(QLatin1Char('_'), QLatin1Char('-')).toLatin1();
104 if(keyName.startsWith(groupKeyName)) {
105 const char *val;
106 if(config_lookup_string(&config_, groupKeyName.constData(), &val) == CONFIG_TRUE)
107 static_cast<QRadioButton*>(child)->setChecked(keyName == groupKeyName.append('-').append(val));
108 connect(child, SIGNAL(toggled(bool)), SLOT(onRadioGroupToggled(bool)));
109 continue;
110 }
111 }
112 int val = -1;
113 if(config_lookup_bool(&config_, keyName.constData(), &val) == CONFIG_TRUE)
114 static_cast<QRadioButton*>(child)->setChecked((bool)val);
115 connect(child, SIGNAL(toggled(bool)), SLOT(onButtonToggled(bool)));
116 }
117 }
118 }
119
~MainDialog()120 MainDialog::~MainDialog() {
121 config_destroy(&config_);
122 delete ui;
123 }
124
onButtonToggled(bool checked)125 void MainDialog::onButtonToggled(bool checked) {
126 qDebug() << "toggled: " << sender()->objectName();
127 // generate config key from objectName.
128 QByteArray keyName = sender()->objectName().replace(QLatin1Char('_'), QLatin1Char('-')).toLatin1();
129 configSetBool(keyName.constData(), checked);
130 // saveConfig();
131 }
132
onSpinValueChanged(double d)133 void MainDialog::onSpinValueChanged(double d) {
134 qDebug() << "changed: " << sender()->objectName() << ": " << d;
135 // generate config key from objectName.
136 QByteArray keyName = sender()->objectName().replace(QLatin1Char('_'), QLatin1Char('-')).toLatin1();
137 configSetFloat(keyName.constData(), d);
138 // saveConfig();
139 }
140
onSpinValueChanged(int i)141 void MainDialog::onSpinValueChanged(int i) {
142 qDebug() << "changed: " << sender()->objectName() << ": " << i;
143 // generate config key from objectName.
144 QByteArray keyName = sender()->objectName().replace(QLatin1Char('_'), QLatin1Char('-')).toLatin1();
145 configSetInt(keyName.constData(), i);
146 // saveConfig();
147 }
148
onRadioGroupToggled(bool checked)149 void MainDialog::onRadioGroupToggled(bool checked) {
150 if (checked) {
151 qDebug() << "toggled: " << sender()->objectName();
152 // generate config key from objectName.
153 QByteArray keyName = sender()->parent()->objectName().replace(QLatin1Char('_'), QLatin1Char('-')).toLatin1();
154 QByteArray val = sender()->objectName().right(sender()->objectName().size() - (keyName.size() + 1)).replace(QLatin1Char('_'), QLatin1Char('-')).toLatin1();
155 configSetString(keyName.constData(), val.constData());
156 // saveConfig();
157 }
158 }
159
saveConfig()160 void MainDialog::saveConfig() {
161 // ensure the existance of user config dir
162 QString configDir = QFileInfo(userConfigFile_).dir().path();
163 QDir().mkpath(configDir);
164 qDebug() << userConfigFile_;
165 // save the config file
166 config_write_file(&config_, userConfigFile_.toLocal8Bit().constData());
167
168 // ask compton to reload the config
169 QString displayName = QString::fromLocal8Bit(qgetenv("DISPLAY"));
170 for(int i = 0; i < displayName.length(); ++i) {
171 if(!displayName[i].isNumber()) // replace non-numeric chars with _
172 displayName[i] = QLatin1Char('_');
173 }
174 QString comptonServiceName = QStringLiteral(COMPTON_SERVICE_PREFIX) + displayName;
175 QDBusInterface iface(comptonServiceName, QStringLiteral(COMPTON_PATH), QStringLiteral(COMPTON_INTERFACE));
176 if(iface.isValid()) {
177 iface.call(QStringLiteral("reset"));
178 // raise ourself to the top again (we'll loosing focus after reloading compton)
179 activateWindow();
180 }
181 // FIXME: dbus interface of compton is not always available and reset() creates
182 // much flickers. Maybe we should use internal dbus method set_opts().
183 // Or, we can patch compton to do what we want.
184 }
185
done(int res)186 void MainDialog::done(int res) {
187 QDialog::done(res);
188 }
189
onDialogButtonClicked(QAbstractButton * button)190 void MainDialog::onDialogButtonClicked(QAbstractButton* button) {
191 if(ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) {
192 saveConfig();
193 }
194 }
195
onColorButtonClicked()196 void MainDialog::onColorButtonClicked() {
197 QColorDialog dlg(shadowColor_);
198 dlg.setOption(QColorDialog::ShowAlphaChannel, false);
199 if(dlg.exec() == QDialog::Accepted) {
200 shadowColor_ = dlg.selectedColor();
201 updateShadowColorButton();
202 configSetFloat("shadow-red", shadowColor_.redF());
203 configSetFloat("shadow-green", shadowColor_.greenF());
204 configSetFloat("shadow-blue", shadowColor_.blueF());
205 }
206 }
207
onAboutButtonClicked()208 void MainDialog::onAboutButtonClicked() {
209 QMessageBox::about(this, tr("About ComptonConf"),
210 tr("ComptonConf - configuration tool for compton\n\nCopyright (C) 2013\nAuthor: Hong Jen Yee (PCMan) <pcman.tw@gmail.com>"));
211 }
212
updateShadowColorButton()213 void MainDialog::updateShadowColorButton() {
214 QString qss = QStringLiteral("QPushButton {"
215 "background-color:%1;"
216 "}").arg(shadowColor_.name());
217 ui->shadow_color->setStyleSheet(qss);
218 }
219
configSetInt(const char * key,int val)220 void MainDialog::configSetInt(const char* key, int val) {
221 config_setting_t* setting = config_lookup(&config_, key);
222 if(!setting) { // setting not found
223 // add a new setting for it
224 config_setting_t* root = config_root_setting(&config_);
225 setting = config_setting_add(root, key, CONFIG_TYPE_INT);
226 }
227 config_setting_set_int(setting, val);
228 }
229
configSetFloat(const char * key,double val)230 void MainDialog::configSetFloat(const char* key, double val) {
231 config_setting_t* setting = config_lookup(&config_, key);
232 if(!setting) { // setting not found
233 // add a new setting for it
234 config_setting_t* root = config_root_setting(&config_);
235 setting = config_setting_add(root, key, CONFIG_TYPE_FLOAT);
236 }
237 config_setting_set_float(setting, val);
238 }
239
configSetBool(const char * key,bool val)240 void MainDialog::configSetBool(const char* key, bool val) {
241 config_setting_t* setting = config_lookup(&config_, key);
242 if(!setting) { // setting not found
243 // add a new setting for it
244 config_setting_t* root = config_root_setting(&config_);
245 setting = config_setting_add(root, key, CONFIG_TYPE_BOOL);
246 }
247 config_setting_set_bool(setting, val);
248 }
249
configSetString(const char * key,const char * val)250 void MainDialog::configSetString(const char *key, const char *val)
251 {
252 config_setting_t* setting = config_lookup(&config_, key);
253 if(!setting) { // setting not found
254 // add a new setting for it
255 config_setting_t* root = config_root_setting(&config_);
256 setting = config_setting_add(root, key, CONFIG_TYPE_STRING);
257 }
258 config_setting_set_string(setting, val);
259 }
260