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/GmicQtHost.h"
32 #include "IconLoader.h"
33 #include "Logger.h"
34 #include "Updater.h"
35 #include "ui_dialogsettings.h"
36 
37 namespace
38 {
filterDeprecatedOutputMessageMode(const GmicQt::OutputMessageMode & mode)39 GmicQt::OutputMessageMode filterDeprecatedOutputMessageMode(const GmicQt::OutputMessageMode & mode)
40 {
41   if (mode == GmicQt::OutputMessageMode::VerboseLayerName_DEPRECATED) {
42     return GmicQt::DefaultOutputMessageMode;
43   }
44   return mode;
45 }
46 } // namespace
47 
48 namespace GmicQt
49 {
50 
51 bool DialogSettings::_darkThemeEnabled;
52 QString DialogSettings::_languageCode;
53 bool DialogSettings::_nativeColorDialogs;
54 bool DialogSettings::_logosAreVisible;
55 MainWindow::PreviewPosition DialogSettings::_previewPosition;
56 int DialogSettings::_updatePeriodicity;
57 OutputMessageMode DialogSettings::_outputMessageMode;
58 bool DialogSettings::_previewZoomAlwaysEnabled = false;
59 bool DialogSettings::_notifyFailedStartupUpdate = true;
60 
61 const QColor DialogSettings::CheckBoxBaseColor(83, 83, 83);
62 const QColor DialogSettings::CheckBoxTextColor(255, 255, 255);
63 QColor DialogSettings::UnselectedFilterTextColor;
64 
65 QString DialogSettings::FolderParameterDefaultValue;
66 QString DialogSettings::FileParameterDefaultPath;
67 int DialogSettings::_previewTimeout = 16;
68 
69 QIcon DialogSettings::AddIcon;
70 QIcon DialogSettings::RemoveIcon;
71 
72 QString DialogSettings::GroupSeparator;
73 QString DialogSettings::DecimalPoint('.');
74 QString DialogSettings::NegativeSign('-');
75 
76 // TODO : Make DialogSetting a view of a Settings class
77 
DialogSettings(QWidget * parent)78 DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::DialogSettings)
79 {
80   ui->setupUi(this);
81 
82   setWindowTitle(tr("Settings"));
83   setWindowIcon(parent->windowIcon());
84   adjustSize();
85 
86   ui->pbUpdate->setIcon(LOAD_ICON("view-refresh"));
87 
88   ui->cbUpdatePeriodicity->addItem(tr("Never"), QVariant(INTERNET_NEVER_UPDATE_PERIODICITY));
89   ui->cbUpdatePeriodicity->addItem(tr("Daily"), QVariant(ONE_DAY_HOURS));
90   ui->cbUpdatePeriodicity->addItem(tr("Weekly"), QVariant(ONE_WEEK_HOURS));
91   ui->cbUpdatePeriodicity->addItem(tr("Every 2 weeks"), QVariant(TWO_WEEKS_HOURS));
92   ui->cbUpdatePeriodicity->addItem(tr("Monthly"), QVariant(ONE_MONTH_HOURS));
93 #ifdef _GMIC_QT_DEBUG_
94   ui->cbUpdatePeriodicity->addItem(tr("At launch (debug)"), QVariant(0));
95 #endif
96   for (int i = 0; i < ui->cbUpdatePeriodicity->count(); ++i) {
97     if (_updatePeriodicity == ui->cbUpdatePeriodicity->itemData(i).toInt()) {
98       ui->cbUpdatePeriodicity->setCurrentIndex(i);
99     }
100   }
101 
102   ui->outputMessages->setToolTip(tr("Output messages"));
103   ui->outputMessages->addItem(tr("Quiet (default)"), (int)OutputMessageMode::Quiet);
104   ui->outputMessages->addItem(tr("Verbose (console)"), (int)OutputMessageMode::VerboseConsole);
105   ui->outputMessages->addItem(tr("Verbose (log file)"), (int)OutputMessageMode::VerboseLogFile);
106   ui->outputMessages->addItem(tr("Very verbose (console)"), (int)OutputMessageMode::VeryVerboseConsole);
107   ui->outputMessages->addItem(tr("Very verbose (log file)"), (int)OutputMessageMode::VeryVerboseLogFile);
108   ui->outputMessages->addItem(tr("Debug (console)"), (int)OutputMessageMode::DebugConsole);
109   ui->outputMessages->addItem(tr("Debug (log file)"), (int)OutputMessageMode::DebugLogFile);
110   for (int index = 0; index < ui->outputMessages->count(); ++index) {
111     if (ui->outputMessages->itemData(index) == (int)_outputMessageMode) {
112       ui->outputMessages->setCurrentIndex(index);
113       break;
114     }
115   }
116 
117   ui->sbPreviewTimeout->setRange(0, 999);
118 
119   ui->rbLeftPreview->setChecked(_previewPosition == MainWindow::PreviewPosition::Left);
120   ui->rbRightPreview->setChecked(_previewPosition == MainWindow::PreviewPosition::Right);
121   const bool savedDarkTheme = QSettings().value(DARK_THEME_KEY, GmicQtHost::DarkThemeIsDefault).toBool();
122   ui->rbDarkTheme->setChecked(savedDarkTheme);
123   ui->rbDefaultTheme->setChecked(!savedDarkTheme);
124   ui->cbNativeColorDialogs->setChecked(_nativeColorDialogs);
125   ui->cbNativeColorDialogs->setToolTip(tr("Check to use Native/OS color dialog, uncheck to use Qt's"));
126   ui->cbShowLogos->setChecked(_logosAreVisible);
127   ui->sbPreviewTimeout->setValue(_previewTimeout);
128   ui->cbPreviewZoom->setChecked(_previewZoomAlwaysEnabled);
129   ui->cbNotifyFailedUpdate->setChecked(_notifyFailedStartupUpdate);
130 
131   connect(ui->pbOk, SIGNAL(clicked()), this, SLOT(onOk()));
132   connect(ui->rbLeftPreview, SIGNAL(toggled(bool)), this, SLOT(onRadioLeftPreviewToggled(bool)));
133   connect(ui->pbUpdate, SIGNAL(clicked(bool)), this, SLOT(onUpdateClicked()));
134 
135   connect(ui->cbUpdatePeriodicity, SIGNAL(currentIndexChanged(int)), this, SLOT(onUpdatePeriodicityChanged(int)));
136 
137   connect(ui->labelPreviewLeft, SIGNAL(clicked()), ui->rbLeftPreview, SLOT(click()));
138   connect(ui->labelPreviewRight, SIGNAL(clicked()), ui->rbRightPreview, SLOT(click()));
139 
140   connect(ui->cbNativeColorDialogs, SIGNAL(toggled(bool)), this, SLOT(onColorDialogsToggled(bool)));
141 
142   connect(Updater::getInstance(), SIGNAL(updateIsDone(int)), this, SLOT(enableUpdateButton()));
143 
144   connect(ui->rbDarkTheme, SIGNAL(toggled(bool)), this, SLOT(onDarkThemeToggled(bool)));
145 
146   connect(ui->cbShowLogos, SIGNAL(toggled(bool)), this, SLOT(onLogosVisibleToggled(bool)));
147 
148   connect(ui->cbPreviewZoom, SIGNAL(toggled(bool)), this, SLOT(onPreviewZoomToggled(bool)));
149 
150   connect(ui->sbPreviewTimeout, SIGNAL(valueChanged(int)), this, SLOT(onPreviewTimeoutChange(int)));
151 
152   connect(ui->outputMessages, SIGNAL(currentIndexChanged(int)), this, SLOT(onOutputMessageModeChanged(int)));
153 
154   connect(ui->cbNotifyFailedUpdate, SIGNAL(toggled(bool)), this, SLOT(onNotifyStartupUpdateFailedToggle(bool)));
155 
156   ui->languageSelector->selectLanguage(_languageCode);
157   if (_darkThemeEnabled) {
158     QPalette p = ui->cbNativeColorDialogs->palette();
159     p.setColor(QPalette::Text, DialogSettings::CheckBoxTextColor);
160     p.setColor(QPalette::Base, DialogSettings::CheckBoxBaseColor);
161     ui->cbNativeColorDialogs->setPalette(p);
162     ui->cbPreviewZoom->setPalette(p);
163     ui->cbUpdatePeriodicity->setPalette(p);
164     ui->rbDarkTheme->setPalette(p);
165     ui->rbDefaultTheme->setPalette(p);
166     ui->rbLeftPreview->setPalette(p);
167     ui->rbRightPreview->setPalette(p);
168     ui->cbShowLogos->setPalette(p);
169     ui->cbNotifyFailedUpdate->setPalette(p);
170   }
171   ui->pbOk->setFocus();
172   ui->tabWidget->setCurrentIndex(0);
173 }
174 
~DialogSettings()175 DialogSettings::~DialogSettings()
176 {
177   delete ui;
178 }
179 
loadSettings(UserInterfaceMode userInterfaceMode)180 void DialogSettings::loadSettings(UserInterfaceMode userInterfaceMode)
181 {
182   QSettings settings;
183   if (settings.value("Config/PreviewPosition", "Left").toString() == "Left") {
184     _previewPosition = MainWindow::PreviewPosition::Left;
185   } else {
186     _previewPosition = MainWindow::PreviewPosition::Right;
187   }
188   _darkThemeEnabled = settings.value(DARK_THEME_KEY, GmicQtHost::DarkThemeIsDefault).toBool();
189   _languageCode = settings.value("Config/LanguageCode", QString()).toString();
190   _nativeColorDialogs = settings.value("Config/NativeColorDialogs", false).toBool();
191   _updatePeriodicity = settings.value(INTERNET_UPDATE_PERIODICITY_KEY, INTERNET_DEFAULT_PERIODICITY).toInt();
192   FolderParameterDefaultValue = settings.value("FolderParameterDefaultValue", QDir::homePath()).toString();
193   FileParameterDefaultPath = settings.value("FileParameterDefaultPath", QDir::homePath()).toString();
194   _logosAreVisible = settings.value("LogosAreVisible", true).toBool();
195   _previewTimeout = settings.value("PreviewTimeout", 16).toInt();
196   _previewZoomAlwaysEnabled = settings.value("AlwaysEnablePreviewZoom", false).toBool();
197   _outputMessageMode = filterDeprecatedOutputMessageMode((GmicQt::OutputMessageMode)settings.value("OutputMessageMode", static_cast<int>(GmicQt::DefaultOutputMessageMode)).toInt());
198   _notifyFailedStartupUpdate = settings.value("Config/NotifyIfStartupUpdateFails", true).toBool();
199   if (userInterfaceMode != UserInterfaceMode::Silent) {
200     AddIcon = LOAD_ICON("list-add");
201     RemoveIcon = LOAD_ICON("list-remove");
202   }
203   QLocale locale;
204   GroupSeparator = locale.groupSeparator();
205   DecimalPoint = locale.decimalPoint();
206   NegativeSign = locale.negativeSign();
207 }
208 
previewZoomAlwaysEnabled()209 bool DialogSettings::previewZoomAlwaysEnabled()
210 {
211   return _previewZoomAlwaysEnabled;
212 }
213 
notifyFailedStartupUpdate()214 bool DialogSettings::notifyFailedStartupUpdate()
215 {
216   return _notifyFailedStartupUpdate;
217 }
218 
previewTimeout()219 int DialogSettings::previewTimeout()
220 {
221   return _previewTimeout;
222 }
223 
outputMessageMode()224 OutputMessageMode DialogSettings::outputMessageMode()
225 {
226   return _outputMessageMode;
227 }
228 
saveSettings(QSettings & settings)229 void DialogSettings::saveSettings(QSettings & settings)
230 {
231   removeObsoleteKeys(settings);
232   settings.setValue("Config/PreviewPosition", (_previewPosition == MainWindow::PreviewPosition::Left) ? "Left" : "Right");
233   settings.setValue("Config/NativeColorDialogs", _nativeColorDialogs);
234   settings.setValue(INTERNET_UPDATE_PERIODICITY_KEY, _updatePeriodicity);
235   settings.setValue("FolderParameterDefaultValue", FolderParameterDefaultValue);
236   settings.setValue("FileParameterDefaultPath", FileParameterDefaultPath);
237   settings.setValue("LogosAreVisible", _logosAreVisible);
238   settings.setValue("PreviewTimeout", _previewTimeout);
239   settings.setValue("OutputMessageMode", (int)_outputMessageMode);
240   settings.setValue("AlwaysEnablePreviewZoom", _previewZoomAlwaysEnabled);
241   // Remove obsolete keys (2.0.0 pre-release)
242   settings.remove("Config/UseFaveInputMode");
243   settings.remove("Config/UseFaveOutputMode");
244   settings.remove("Config/UseFaveOutputMessages");
245   settings.remove("Config/UseFavePreviewMode");
246   settings.setValue("Config/NotifyIfStartupUpdateFails", _notifyFailedStartupUpdate);
247 }
248 
previewPosition()249 MainWindow::PreviewPosition DialogSettings::previewPosition()
250 {
251   return _previewPosition;
252 }
253 
logosAreVisible()254 bool DialogSettings::logosAreVisible()
255 {
256   return _logosAreVisible;
257 }
258 
onOk()259 void DialogSettings::onOk()
260 {
261   done(QDialog::Accepted);
262 }
263 
done(int r)264 void DialogSettings::done(int r)
265 {
266   QSettings settings;
267   saveSettings(settings);
268   settings.setValue(DARK_THEME_KEY, ui->rbDarkTheme->isChecked());
269   settings.setValue("Config/LanguageCode", ui->languageSelector->selectedLanguageCode());
270   QDialog::done(r);
271 }
272 
onLogosVisibleToggled(bool on)273 void DialogSettings::onLogosVisibleToggled(bool on)
274 {
275   _logosAreVisible = on;
276 }
277 
onPreviewTimeoutChange(int value)278 void DialogSettings::onPreviewTimeoutChange(int value)
279 {
280   _previewTimeout = value;
281 }
282 
onOutputMessageModeChanged(int)283 void DialogSettings::onOutputMessageModeChanged(int)
284 {
285   _outputMessageMode = static_cast<OutputMessageMode>(ui->outputMessages->currentData().toInt());
286   Logger::setMode(_outputMessageMode);
287 }
288 
onPreviewZoomToggled(bool on)289 void DialogSettings::onPreviewZoomToggled(bool on)
290 {
291   _previewZoomAlwaysEnabled = on;
292 }
293 
onNotifyStartupUpdateFailedToggle(bool on)294 void DialogSettings::onNotifyStartupUpdateFailedToggle(bool on)
295 {
296   _notifyFailedStartupUpdate = on;
297 }
298 
removeObsoleteKeys(QSettings & settings)299 void DialogSettings::removeObsoleteKeys(QSettings & settings)
300 {
301   settings.remove(QString("LastExecution/host_%1/PreviewMode").arg(GmicQtHost::ApplicationShortname));
302   settings.remove(QString("LastExecution/host_%1/GmicEnvironment").arg(GmicQtHost::ApplicationShortname));
303   settings.remove(QString("LastExecution/host_%1/QuotedParameters").arg(GmicQtHost::ApplicationShortname));
304   settings.remove(QString("LastExecution/host_%1/GmicStatus").arg(GmicQtHost::ApplicationShortname));
305 }
306 
enableUpdateButton()307 void DialogSettings::enableUpdateButton()
308 {
309   ui->pbUpdate->setEnabled(true);
310 }
311 
onRadioLeftPreviewToggled(bool on)312 void DialogSettings::onRadioLeftPreviewToggled(bool on)
313 {
314   if (on) {
315     _previewPosition = MainWindow::PreviewPosition::Left;
316   } else {
317     _previewPosition = MainWindow::PreviewPosition::Right;
318   }
319 }
320 
onUpdateClicked()321 void DialogSettings::onUpdateClicked()
322 {
323   auto mainWindow = dynamic_cast<MainWindow *>(parent());
324   if (mainWindow) {
325     ui->pbUpdate->setEnabled(false);
326     mainWindow->updateFiltersFromSources(0, true);
327   }
328 }
329 
onDarkThemeToggled(bool)330 void DialogSettings::onDarkThemeToggled(bool) {}
331 
onUpdatePeriodicityChanged(int)332 void DialogSettings::onUpdatePeriodicityChanged(int)
333 {
334   _updatePeriodicity = ui->cbUpdatePeriodicity->currentData().toInt();
335 }
336 
onColorDialogsToggled(bool on)337 void DialogSettings::onColorDialogsToggled(bool on)
338 {
339   _nativeColorDialogs = on;
340 }
341 
darkThemeEnabled()342 bool DialogSettings::darkThemeEnabled()
343 {
344   return _darkThemeEnabled;
345 }
346 
languageCode()347 QString DialogSettings::languageCode()
348 {
349   return _languageCode;
350 }
351 
nativeColorDialogs()352 bool DialogSettings::nativeColorDialogs()
353 {
354   return _nativeColorDialogs;
355 }
356 
357 } // namespace GmicQt
358