1 /** -*- mode: c++ ; c-basic-offset: 2 -*-
2  *
3  *  @file DialogSettings.cpp
4  *
5  *  Copyright 2017 Sebastien Fourey
6  *
7  *  This file is part of G'MIC-Qt, a generic plug-in for raster graphics
8  *  editors, offering hundreds of filters thanks to the underlying G'MIC
9  *  image processing framework.
10  *
11  *  gmic_qt is free software: you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation, either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  gmic_qt is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with gmic_qt.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25 #include "DialogSettings.h"
26 #include <QCloseEvent>
27 #include <QSettings>
28 #include <limits>
29 #include "Common.h"
30 #include "Globals.h"
31 #include "Host/host.h"
32 #include "IconLoader.h"
33 #include "Logger.h"
34 #include "Updater.h"
35 #include "ui_dialogsettings.h"
36 
37 bool DialogSettings::_darkThemeEnabled;
38 QString DialogSettings::_languageCode;
39 bool DialogSettings::_nativeColorDialogs;
40 bool DialogSettings::_logosAreVisible;
41 MainWindow::PreviewPosition DialogSettings::_previewPosition;
42 int DialogSettings::_updatePeriodicity;
43 GmicQt::OutputMessageMode DialogSettings::_outputMessageMode;
44 bool DialogSettings::_previewZoomAlwaysEnabled = false;
45 bool DialogSettings::_notifyFailedStartupUpdate = true;
46 
47 const QColor DialogSettings::CheckBoxBaseColor(83, 83, 83);
48 const QColor DialogSettings::CheckBoxTextColor(255, 255, 255);
49 QColor DialogSettings::UnselectedFilterTextColor;
50 
51 QString DialogSettings::FolderParameterDefaultValue;
52 QString DialogSettings::FileParameterDefaultPath;
53 int DialogSettings::_previewTimeout = 16;
54 
55 QIcon DialogSettings::AddIcon;
56 QIcon DialogSettings::RemoveIcon;
57 
58 // TODO : Make DialogSetting a view of a Settings class
59 
DialogSettings(QWidget * parent)60 DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::DialogSettings)
61 {
62   ui->setupUi(this);
63 
64   setWindowTitle(tr("Settings"));
65   setWindowIcon(parent->windowIcon());
66   adjustSize();
67 
68   ui->pbUpdate->setIcon(LOAD_ICON("view-refresh"));
69 
70   ui->cbUpdatePeriodicity->addItem(tr("Never"), QVariant(INTERNET_NEVER_UPDATE_PERIODICITY));
71   ui->cbUpdatePeriodicity->addItem(tr("Daily"), QVariant(24));
72   ui->cbUpdatePeriodicity->addItem(tr("Weekly"), QVariant(7 * 24));
73   ui->cbUpdatePeriodicity->addItem(tr("Every 2 weeks"), QVariant(14 * 24));
74   ui->cbUpdatePeriodicity->addItem(tr("Monthly"), QVariant(30 * 24));
75 #ifdef _GMIC_QT_DEBUG_
76   ui->cbUpdatePeriodicity->addItem(tr("At launch (debug)"), QVariant(0));
77 #endif
78   for (int i = 0; i < ui->cbUpdatePeriodicity->count(); ++i) {
79     if (_updatePeriodicity == ui->cbUpdatePeriodicity->itemData(i).toInt()) {
80       ui->cbUpdatePeriodicity->setCurrentIndex(i);
81     }
82   }
83 
84   ui->outputMessages->setToolTip(tr("Output messages"));
85   QString dummy3(tr("Output messages..."));
86   ui->outputMessages->addItem(tr("Quiet (default)"), GmicQt::Quiet);
87   ui->outputMessages->addItem(tr("Verbose (layer name)"), GmicQt::VerboseLayerName);
88   ui->outputMessages->addItem(tr("Verbose (console)"), GmicQt::VerboseConsole);
89   ui->outputMessages->addItem(tr("Verbose (log file)"), GmicQt::VerboseLogFile);
90   ui->outputMessages->addItem(tr("Very verbose (console)"), GmicQt::VeryVerboseConsole);
91   ui->outputMessages->addItem(tr("Very verbose (log file)"), GmicQt::VeryVerboseLogFile);
92   ui->outputMessages->addItem(tr("Debug (console)"), GmicQt::DebugConsole);
93   ui->outputMessages->addItem(tr("Debug (log file)"), GmicQt::DebugLogFile);
94   for (int index = 0; index < ui->outputMessages->count(); ++index) {
95     if (ui->outputMessages->itemData(index) == _outputMessageMode) {
96       ui->outputMessages->setCurrentIndex(index);
97       break;
98     }
99   }
100 
101   ui->sbPreviewTimeout->setRange(1, 360);
102 
103   ui->rbLeftPreview->setChecked(_previewPosition == MainWindow::PreviewOnLeft);
104   ui->rbRightPreview->setChecked(_previewPosition == MainWindow::PreviewOnRight);
105   const bool savedDarkTheme = QSettings().value(DARK_THEME_KEY, GmicQt::DarkThemeIsDefault).toBool();
106   ui->rbDarkTheme->setChecked(savedDarkTheme);
107   ui->rbDefaultTheme->setChecked(!savedDarkTheme);
108   ui->cbNativeColorDialogs->setChecked(_nativeColorDialogs);
109   ui->cbNativeColorDialogs->setToolTip(tr("Check to use Native/OS color dialog, uncheck to use Qt's"));
110   ui->cbShowLogos->setChecked(_logosAreVisible);
111   ui->sbPreviewTimeout->setValue(_previewTimeout);
112   ui->cbPreviewZoom->setChecked(_previewZoomAlwaysEnabled);
113   ui->cbNotifyFailedUpdate->setChecked(_notifyFailedStartupUpdate);
114 
115   connect(ui->pbOk, SIGNAL(clicked()), this, SLOT(onOk()));
116   connect(ui->rbLeftPreview, SIGNAL(toggled(bool)), this, SLOT(onRadioLeftPreviewToggled(bool)));
117   connect(ui->pbUpdate, SIGNAL(clicked(bool)), this, SLOT(onUpdateClicked()));
118 
119   connect(ui->cbUpdatePeriodicity, SIGNAL(currentIndexChanged(int)), this, SLOT(onUpdatePeriodicityChanged(int)));
120 
121   connect(ui->labelPreviewLeft, SIGNAL(clicked()), ui->rbLeftPreview, SLOT(click()));
122   connect(ui->labelPreviewRight, SIGNAL(clicked()), ui->rbRightPreview, SLOT(click()));
123 
124   connect(ui->cbNativeColorDialogs, SIGNAL(toggled(bool)), this, SLOT(onColorDialogsToggled(bool)));
125 
126   connect(Updater::getInstance(), SIGNAL(updateIsDone(int)), this, SLOT(enableUpdateButton()));
127 
128   connect(ui->rbDarkTheme, SIGNAL(toggled(bool)), this, SLOT(onDarkThemeToggled(bool)));
129 
130   connect(ui->cbShowLogos, SIGNAL(toggled(bool)), this, SLOT(onLogosVisibleToggled(bool)));
131 
132   connect(ui->cbPreviewZoom, SIGNAL(toggled(bool)), this, SLOT(onPreviewZoomToggled(bool)));
133 
134   connect(ui->sbPreviewTimeout, SIGNAL(valueChanged(int)), this, SLOT(onPreviewTimeoutChange(int)));
135 
136   connect(ui->outputMessages, SIGNAL(currentIndexChanged(int)), this, SLOT(onOutputMessageModeChanged(int)));
137 
138   connect(ui->cbNotifyFailedUpdate, SIGNAL(toggled(bool)), this, SLOT(onNotifyStartupUpdateFailedToggle(bool)));
139 
140   ui->languageSelector->selectLanguage(_languageCode);
141   if (_darkThemeEnabled) {
142     QPalette p = ui->cbNativeColorDialogs->palette();
143     p.setColor(QPalette::Text, DialogSettings::CheckBoxTextColor);
144     p.setColor(QPalette::Base, DialogSettings::CheckBoxBaseColor);
145     ui->cbNativeColorDialogs->setPalette(p);
146     ui->cbPreviewZoom->setPalette(p);
147     ui->cbUpdatePeriodicity->setPalette(p);
148     ui->rbDarkTheme->setPalette(p);
149     ui->rbDefaultTheme->setPalette(p);
150     ui->rbLeftPreview->setPalette(p);
151     ui->rbRightPreview->setPalette(p);
152     ui->cbShowLogos->setPalette(p);
153     ui->cbNotifyFailedUpdate->setPalette(p);
154   }
155   ui->pbOk->setFocus();
156   ui->tabWidget->setCurrentIndex(0);
157 }
158 
~DialogSettings()159 DialogSettings::~DialogSettings()
160 {
161   delete ui;
162 }
163 
loadSettings(GmicQt::ApplicationType applicationType)164 void DialogSettings::loadSettings(GmicQt::ApplicationType applicationType)
165 {
166   QSettings settings;
167   if (settings.value("Config/PreviewPosition", "Left").toString() == "Left") {
168     _previewPosition = MainWindow::PreviewOnLeft;
169   } else {
170     _previewPosition = MainWindow::PreviewOnRight;
171   }
172   _darkThemeEnabled = settings.value(DARK_THEME_KEY, GmicQt::DarkThemeIsDefault).toBool();
173   _languageCode = settings.value("Config/LanguageCode", QString()).toString();
174   _nativeColorDialogs = settings.value("Config/NativeColorDialogs", false).toBool();
175   _updatePeriodicity = settings.value(INTERNET_UPDATE_PERIODICITY_KEY, INTERNET_DEFAULT_PERIODICITY).toInt();
176   FolderParameterDefaultValue = settings.value("FolderParameterDefaultValue", QDir::homePath()).toString();
177   FileParameterDefaultPath = settings.value("FileParameterDefaultPath", QDir::homePath()).toString();
178   _logosAreVisible = settings.value("LogosAreVisible", true).toBool();
179   _previewTimeout = settings.value("PreviewTimeout", 16).toInt();
180   _previewZoomAlwaysEnabled = settings.value("AlwaysEnablePreviewZoom", false).toBool();
181   _outputMessageMode = static_cast<GmicQt::OutputMessageMode>(settings.value("OutputMessageMode", GmicQt::DefaultOutputMessageMode).toInt());
182   _notifyFailedStartupUpdate = settings.value("Config/NotifyIfStartupUpdateFails", true).toBool();
183   if (applicationType == GmicQt::GuiApplication) {
184     AddIcon = LOAD_ICON("list-add");
185     RemoveIcon = LOAD_ICON("list-remove");
186   }
187 }
188 
previewZoomAlwaysEnabled()189 bool DialogSettings::previewZoomAlwaysEnabled()
190 {
191   return _previewZoomAlwaysEnabled;
192 }
193 
notifyFailedStartupUpdate()194 bool DialogSettings::notifyFailedStartupUpdate()
195 {
196   return _notifyFailedStartupUpdate;
197 }
198 
previewTimeout()199 int DialogSettings::previewTimeout()
200 {
201   return _previewTimeout;
202 }
203 
outputMessageMode()204 GmicQt::OutputMessageMode DialogSettings::outputMessageMode()
205 {
206   return _outputMessageMode;
207 }
208 
saveSettings(QSettings & settings)209 void DialogSettings::saveSettings(QSettings & settings)
210 {
211   settings.setValue("Config/PreviewPosition", (_previewPosition == MainWindow::PreviewOnLeft) ? "Left" : "Right");
212   settings.setValue("Config/NativeColorDialogs", _nativeColorDialogs);
213   settings.setValue(INTERNET_UPDATE_PERIODICITY_KEY, _updatePeriodicity);
214   settings.setValue("FolderParameterDefaultValue", FolderParameterDefaultValue);
215   settings.setValue("FileParameterDefaultPath", FileParameterDefaultPath);
216   settings.setValue("LogosAreVisible", _logosAreVisible);
217   settings.setValue("PreviewTimeout", _previewTimeout);
218   settings.setValue("OutputMessageMode", _outputMessageMode);
219   settings.setValue("AlwaysEnablePreviewZoom", _previewZoomAlwaysEnabled);
220   // Remove obsolete keys (2.0.0 pre-release)
221   settings.remove("Config/UseFaveInputMode");
222   settings.remove("Config/UseFaveOutputMode");
223   settings.remove("Config/UseFaveOutputMessages");
224   settings.remove("Config/UseFavePreviewMode");
225   settings.setValue("Config/NotifyIfStartupUpdateFails", _notifyFailedStartupUpdate);
226 }
227 
previewPosition()228 MainWindow::PreviewPosition DialogSettings::previewPosition()
229 {
230   return _previewPosition;
231 }
232 
logosAreVisible()233 bool DialogSettings::logosAreVisible()
234 {
235   return _logosAreVisible;
236 }
237 
onOk()238 void DialogSettings::onOk()
239 {
240   done(QDialog::Accepted);
241 }
242 
done(int r)243 void DialogSettings::done(int r)
244 {
245   QSettings settings;
246   saveSettings(settings);
247   settings.setValue(DARK_THEME_KEY, ui->rbDarkTheme->isChecked());
248   settings.setValue("Config/LanguageCode", ui->languageSelector->selectedLanguageCode());
249   QDialog::done(r);
250 }
251 
onLogosVisibleToggled(bool on)252 void DialogSettings::onLogosVisibleToggled(bool on)
253 {
254   _logosAreVisible = on;
255 }
256 
onPreviewTimeoutChange(int value)257 void DialogSettings::onPreviewTimeoutChange(int value)
258 {
259   _previewTimeout = value;
260 }
261 
onOutputMessageModeChanged(int)262 void DialogSettings::onOutputMessageModeChanged(int)
263 {
264   _outputMessageMode = static_cast<GmicQt::OutputMessageMode>(ui->outputMessages->currentData().toInt());
265   Logger::setMode(_outputMessageMode);
266 }
267 
onPreviewZoomToggled(bool on)268 void DialogSettings::onPreviewZoomToggled(bool on)
269 {
270   _previewZoomAlwaysEnabled = on;
271 }
272 
onNotifyStartupUpdateFailedToggle(bool on)273 void DialogSettings::onNotifyStartupUpdateFailedToggle(bool on)
274 {
275   _notifyFailedStartupUpdate = on;
276 }
277 
enableUpdateButton()278 void DialogSettings::enableUpdateButton()
279 {
280   ui->pbUpdate->setEnabled(true);
281 }
282 
onRadioLeftPreviewToggled(bool on)283 void DialogSettings::onRadioLeftPreviewToggled(bool on)
284 {
285   if (on) {
286     _previewPosition = MainWindow::PreviewOnLeft;
287   } else {
288     _previewPosition = MainWindow::PreviewOnRight;
289   }
290 }
291 
onUpdateClicked()292 void DialogSettings::onUpdateClicked()
293 {
294   auto mainWindow = dynamic_cast<MainWindow *>(parent());
295   if (mainWindow) {
296     ui->pbUpdate->setEnabled(false);
297     mainWindow->updateFiltersFromSources(0, true);
298   }
299 }
300 
onDarkThemeToggled(bool)301 void DialogSettings::onDarkThemeToggled(bool) {}
302 
onUpdatePeriodicityChanged(int)303 void DialogSettings::onUpdatePeriodicityChanged(int)
304 {
305   _updatePeriodicity = ui->cbUpdatePeriodicity->currentData().toInt();
306 }
307 
onColorDialogsToggled(bool on)308 void DialogSettings::onColorDialogsToggled(bool on)
309 {
310   _nativeColorDialogs = on;
311 }
312 
darkThemeEnabled()313 bool DialogSettings::darkThemeEnabled()
314 {
315   return _darkThemeEnabled;
316 }
317 
languageCode()318 QString DialogSettings::languageCode()
319 {
320   return _languageCode;
321 }
322 
nativeColorDialogs()323 bool DialogSettings::nativeColorDialogs()
324 {
325   return _nativeColorDialogs;
326 }
327