1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2005-04-02
7 * Description : setup Misc tab.
8 *
9 * Copyright (C) 2005-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2008 by Arnd Baecker <arnd dot baecker at web dot de>
11 * Copyright (C) 2014 by Mohamed_Anwer <m_dot_anwer at gmx dot com>
12 *
13 * This program is free software; you can redistribute it
14 * and/or modify it under the terms of the GNU General
15 * Public License as published by the Free Software Foundation;
16 * either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * ============================================================ */
25
26 #include "showfotosetupmisc.h"
27
28 // Qt includes
29
30 #include <QCheckBox>
31 #include <QColor>
32 #include <QGroupBox>
33 #include <QLabel>
34 #include <QVBoxLayout>
35 #include <QStyleFactory>
36 #include <QApplication>
37 #include <QDirIterator>
38 #include <QStyle>
39 #include <QComboBox>
40 #include <QFile>
41 #include <QTabWidget>
42 #include <QMessageBox>
43 #include <QPushButton>
44
45 // KDE includes
46
47 #include <klocalizedstring.h>
48
49 // Local includes
50
51 #include "digikam_config.h"
52 #include "dlayoutbox.h"
53 #include "dfontselect.h"
54 #include "showfotosettings.h"
55 #include "systemsettingswidget.h"
56 #include "onlineversionchecker.h"
57 #include "showfotosetup.h"
58
59 using namespace Digikam;
60
61 namespace ShowFoto
62 {
63
64 class Q_DECL_HIDDEN ShowfotoSetupMisc::Private
65 {
66 public:
67
Private()68 explicit Private()
69 : tab (nullptr),
70 updateTypeLabel (nullptr),
71 sidebarTypeLabel (nullptr),
72 applicationStyleLabel (nullptr),
73 applicationIconLabel (nullptr),
74 showSplash (nullptr),
75 nativeFileDialog (nullptr),
76 itemCenter (nullptr),
77 showMimeOverImage (nullptr),
78 showCoordinates (nullptr),
79 sortReverse (nullptr),
80 updateType (nullptr),
81 updateWithDebug (nullptr),
82 sidebarType (nullptr),
83 sortOrderComboBox (nullptr),
84 applicationStyle (nullptr),
85 applicationIcon (nullptr),
86 applicationFont (nullptr),
87 systemSettingsWidget (nullptr),
88 settings (ShowfotoSettings::instance())
89 {
90 }
91
92 QTabWidget* tab;
93
94 QLabel* updateTypeLabel;
95 QLabel* sidebarTypeLabel;
96 QLabel* applicationStyleLabel;
97 QLabel* applicationIconLabel;
98
99 QCheckBox* showSplash;
100 QCheckBox* nativeFileDialog;
101 QCheckBox* itemCenter;
102 QCheckBox* showMimeOverImage;
103 QCheckBox* showCoordinates;
104 QCheckBox* sortReverse;
105
106 QComboBox* updateType;
107 QCheckBox* updateWithDebug;
108
109 QComboBox* sidebarType;
110 QComboBox* sortOrderComboBox;
111 QComboBox* applicationStyle;
112 QComboBox* applicationIcon;
113 DFontSelect* applicationFont;
114
115 SystemSettingsWidget* systemSettingsWidget;
116
117 ShowfotoSettings* settings;
118 };
119
120 // --------------------------------------------------------
121
ShowfotoSetupMisc(QWidget * const parent)122 ShowfotoSetupMisc::ShowfotoSetupMisc(QWidget* const parent)
123 : QScrollArea(parent),
124 d (new Private)
125 {
126 d->tab = new QTabWidget(viewport());
127 setWidget(d->tab);
128 setWidgetResizable(true);
129
130 const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
131
132 // -- Application Behavior Options --------------------------------------------------------
133
134 QWidget* const behaviourPanel = new QWidget(d->tab);
135 QVBoxLayout* const layout = new QVBoxLayout(behaviourPanel);
136
137 // -- Sort Order Options ----------------------------------
138
139 QGroupBox* const sortOptionsGroup = new QGroupBox(i18n("Thumbbar, Folder-View, and Stack-View Items Sort Order"), behaviourPanel);
140 QVBoxLayout* const gLayout4 = new QVBoxLayout();
141
142 DHBox* const sortBox = new DHBox(sortOptionsGroup);
143 new QLabel(i18n("Sort images by:"), sortBox);
144 d->sortOrderComboBox = new QComboBox(sortBox);
145 d->sortOrderComboBox->insertItem(SortByDate, i18nc("sort images by date", "Date"));
146 d->sortOrderComboBox->insertItem(SortByName, i18nc("sort images by name", "Name"));
147 d->sortOrderComboBox->insertItem(SortByFileSize, i18nc("sort images by size", "File Size"));
148 d->sortOrderComboBox->setWhatsThis(i18n("Here, select whether newly-loaded "
149 "images are sorted by their date, name, or size on disk."));
150
151 d->sortReverse = new QCheckBox(i18n("Reverse ordering"), sortOptionsGroup);
152 d->sortReverse->setWhatsThis(i18n("If this option is enabled, newly-loaded "
153 "images will be sorted in descending order."));
154
155 gLayout4->addWidget(sortBox);
156 gLayout4->addWidget(d->sortReverse);
157 sortOptionsGroup->setLayout(gLayout4);
158
159 // Thumbnails Options -------------------------------------
160
161 QGroupBox* const thOptionsGroup = new QGroupBox(i18n("Thumbbar Items"), behaviourPanel);
162 QVBoxLayout* const gLayout3 = new QVBoxLayout();
163
164 d->showMimeOverImage = new QCheckBox(i18n("&Show image Format"), thOptionsGroup);
165 d->showMimeOverImage->setWhatsThis(i18n("Set this option to show image format over image thumbnail."));
166 d->showCoordinates = new QCheckBox(i18n("&Show Geolocation Indicator"), thOptionsGroup);
167 d->showCoordinates->setWhatsThis(i18n("Set this option to indicate if image has geolocation information."));
168 d->itemCenter = new QCheckBox(i18n("Scroll current item to center of thumbbar"), thOptionsGroup);
169
170 gLayout3->addWidget(d->showMimeOverImage);
171 gLayout3->addWidget(d->showCoordinates);
172 gLayout3->addWidget(d->itemCenter);
173 thOptionsGroup->setLayout(gLayout3);
174
175 // Update Options ----------------------------------------
176
177 QGroupBox* const upOptionsGroup = new QGroupBox(i18n("Updates"), behaviourPanel);
178 QVBoxLayout* const gLayout5 = new QVBoxLayout();
179
180 DHBox* const updateHbox = new DHBox(upOptionsGroup);
181 d->updateTypeLabel = new QLabel(i18n("Check for new version:"), updateHbox);
182 d->updateType = new QComboBox(updateHbox);
183 d->updateType->addItem(i18n("Only For Stable Releases"), 0);
184 d->updateType->addItem(i18n("Weekly Pre-Releases"), 1);
185 d->updateType->setToolTip(i18n("Set this option to configure which kind of new versions must be check for updates.\n"
186 "\"Stable\" releases are official versions safe to use in production.\n"
187 "\"Pre-releases\" are proposed weekly to tests quickly new features\n"
188 "and are not recommended to use in production as bugs can remain."));
189
190 d->updateWithDebug = new QCheckBox(i18n("Use Version With Debug Symbols"), upOptionsGroup);
191 d->updateWithDebug->setWhatsThis(i18n("If this option is enabled, a version including debug symbols will be used for updates.\n"
192 "This version is more heavy but can help developers to trace dysfunctions in debugger."));
193
194 DHBox* const updateHbox2 = new DHBox(upOptionsGroup);
195 QLabel* const lastCheckLabel = new QLabel(updateHbox2);
196 lastCheckLabel->setText(i18n("Last check: %1", OnlineVersionChecker::lastCheckDate()));
197 QPushButton* const updateNow = new QPushButton(i18n("Check now..."), updateHbox2);
198
199 connect(updateNow, &QPushButton::pressed,
200 this, [=]()
201 {
202 if (parent)
203 {
204 parent->close();
205 }
206
207 ShowfotoSetup::onlineVersionCheck();
208 }
209 );
210
211 gLayout5->addWidget(updateHbox);
212 gLayout5->addWidget(d->updateWithDebug);
213 gLayout5->addWidget(updateHbox2);
214 upOptionsGroup->setLayout(gLayout5);
215
216 // ---------------------------------------------------------
217
218 layout->setContentsMargins(spacing, spacing, spacing, spacing);
219 layout->setSpacing(spacing);
220 layout->addWidget(sortOptionsGroup);
221 layout->addWidget(thOptionsGroup);
222 layout->addWidget(upOptionsGroup);
223 layout->addStretch();
224
225 d->tab->insertTab(Behaviour, behaviourPanel, i18nc("@title:tab", "Behaviour"));
226
227 // -- Application Appearance Options --------------------------------------------------------
228
229 QWidget* const appearancePanel = new QWidget(d->tab);
230 QVBoxLayout* const layout2 = new QVBoxLayout(appearancePanel);
231
232 d->showSplash = new QCheckBox(i18n("&Show splash screen at startup"), appearancePanel);
233 d->nativeFileDialog = new QCheckBox(i18n("Use native file dialogs from the system"), appearancePanel);
234
235 DHBox* const tabStyleHbox = new DHBox(appearancePanel);
236 d->sidebarTypeLabel = new QLabel(i18n("Sidebar tab title:"), tabStyleHbox);
237 d->sidebarType = new QComboBox(tabStyleHbox);
238 d->sidebarType->addItem(i18n("Only For Active Tab"), 0);
239 d->sidebarType->addItem(i18n("For All Tabs"), 1);
240 d->sidebarType->setToolTip(i18n("Set this option to configure how sidebars tab title are visible."));
241
242 DHBox* const appStyleHbox = new DHBox(appearancePanel);
243 d->applicationStyleLabel = new QLabel(i18n("Widget style:"), appStyleHbox);
244 d->applicationStyle = new QComboBox(appStyleHbox);
245 d->applicationStyle->setToolTip(i18n("Set this option to choose the default window decoration and looks."));
246
247 foreach (const QString& style, QStyleFactory::keys())
248 {
249 QString sitem = style;
250 sitem[0] = sitem[0].toUpper();
251 d->applicationStyle->addItem(sitem, sitem.toLower());
252 }
253
254 #ifndef HAVE_APPSTYLE_SUPPORT
255
256 // See Bug #365262
257
258 appStyleHbox->setVisible(false);
259
260 #endif
261
262 DHBox* const iconThemeHbox = new DHBox(appearancePanel);
263 d->applicationIconLabel = new QLabel(i18n("Icon theme (changes after restart):"), iconThemeHbox);
264 d->applicationIcon = new QComboBox(iconThemeHbox);
265 d->applicationIcon->setToolTip(i18n("Set this option to choose the default icon theme."));
266
267 QMap<QString, QString> iconThemes;
268 QMap<QString, QString> themeWhiteList;
269 themeWhiteList.insert(QLatin1String("adwaita"), i18nc("icon theme", "Adwaita"));
270 themeWhiteList.insert(QLatin1String("breeze"), i18nc("icon theme", "Breeze"));
271 themeWhiteList.insert(QLatin1String("breeze-dark"), i18nc("icon theme", "Breeze Dark"));
272 themeWhiteList.insert(QLatin1String("faenza"), i18nc("icon theme", "Faenza"));
273 themeWhiteList.insert(QLatin1String("faenza-ambiance"), i18nc("icon theme", "Ambiance"));
274 themeWhiteList.insert(QLatin1String("humanity"), i18nc("icon theme", "Humanity"));
275 themeWhiteList.insert(QLatin1String("oxygen"), i18nc("icon theme", "Oxygen"));
276
277 foreach (const QString& path, QIcon::themeSearchPaths())
278 {
279 QDirIterator it(path, QDir::Dirs |
280 QDir::NoSymLinks |
281 QDir::NoDotAndDotDot);
282
283 while (it.hasNext())
284 {
285 if (QFile::exists(it.next() + QLatin1String("/index.theme")))
286 {
287 QString iconKey = it.fileInfo().fileName().toLower();
288
289 if (themeWhiteList.contains(iconKey))
290 {
291 iconThemes[themeWhiteList.value(iconKey)] = it.fileInfo().fileName();
292 }
293 }
294 }
295 }
296
297 QMap<QString, QString>::const_iterator it = iconThemes.constBegin();
298 d->applicationIcon->addItem(i18n("Use Icon Theme From System"), QString());
299
300 for ( ; it != iconThemes.constEnd() ; ++it)
301 {
302 d->applicationIcon->addItem(it.key(), it.value());
303 }
304
305 d->applicationFont = new DFontSelect(i18n("Application font:"), appearancePanel);
306 d->applicationFont->setToolTip(i18n("Select here the font used to display text in whole application."));
307
308 // --------------------------------------------------------
309
310 layout2->setContentsMargins(spacing, spacing, spacing, spacing);
311 layout2->setSpacing(spacing);
312 layout2->addWidget(d->showSplash);
313 layout2->addWidget(d->nativeFileDialog);
314 layout2->addWidget(tabStyleHbox);
315 layout2->addWidget(appStyleHbox);
316 layout2->addWidget(iconThemeHbox);
317 layout2->addWidget(d->applicationFont);
318 layout2->addStretch();
319
320 d->tab->insertTab(Appearance, appearancePanel, i18nc("@title:tab", "Appearance"));
321
322 // -- System Options --------------------------------------------------------
323
324 d->systemSettingsWidget = new SystemSettingsWidget(d->tab);
325
326 d->tab->insertTab(System, d->systemSettingsWidget, i18nc("@title:tab", "System"));
327
328 // --------------------------------------------------------
329
330 readSettings();
331 }
332
~ShowfotoSetupMisc()333 ShowfotoSetupMisc::~ShowfotoSetupMisc()
334 {
335 delete d;
336 }
337
checkSettings()338 bool ShowfotoSetupMisc::checkSettings()
339 {
340 // If check for new version use weekly pre-releases, warn end-user.
341
342 if ((d->updateType->currentIndex() == 1) &&
343 (ShowfotoSettings::instance()->getUpdateType() == 0))
344 {
345 d->tab->setCurrentIndex(0);
346
347 int result = QMessageBox::warning(this, qApp->applicationName(),
348 i18n("Check for new version option will verify the pre-releases.\n"
349 "\"Pre-releases\" are proposed weekly to tests quickly new features.\n"
350 "It's not recommended to use pre-release in production as bugs can remain,\n"
351 "unless you know what you are doing.\n"
352 "Do you want to continue?"),
353 QMessageBox::Yes | QMessageBox::No);
354 if (result == QMessageBox::Yes)
355 {
356 return true;
357 }
358
359 return false;
360 }
361
362 return true;
363 }
364
readSettings()365 void ShowfotoSetupMisc::readSettings()
366 {
367 d->systemSettingsWidget->readSettings();
368
369 d->showSplash->setChecked(d->settings->getShowSplash());
370 d->nativeFileDialog->setChecked(d->settings->getNativeFileDialog());
371 d->itemCenter->setChecked(d->settings->getItemCenter());
372 d->showMimeOverImage->setChecked(d->settings->getShowFormatOverThumbnail());
373 d->showCoordinates->setChecked(d->settings->getShowCoordinates());
374 d->sidebarType->setCurrentIndex(d->settings->getRightSideBarStyle());
375 d->updateType->setCurrentIndex(d->settings->getUpdateType());
376 d->updateWithDebug->setChecked(d->settings->getUpdateWithDebug());
377 d->sortOrderComboBox->setCurrentIndex(d->settings->getSortRole());
378 d->sortReverse->setChecked(d->settings->getReverseSort());
379
380 #ifdef HAVE_APPSTYLE_SUPPORT
381
382 d->applicationStyle->setCurrentIndex(d->applicationStyle->findData(d->settings->getApplicationStyle().toLower()));
383
384 #endif
385
386 d->applicationIcon->setCurrentIndex(d->applicationIcon->findData(d->settings->getIconTheme()));
387 d->applicationFont->setFont(d->settings->getApplicationFont());
388 }
389
applySettings()390 void ShowfotoSetupMisc::applySettings()
391 {
392 d->systemSettingsWidget->saveSettings();
393
394 d->settings->setShowSplash(d->showSplash->isChecked());
395 d->settings->setNativeFileDialog(d->nativeFileDialog->isChecked());
396 d->settings->setItemCenter(d->itemCenter->isChecked());
397 d->settings->setShowFormatOverThumbnail(d->showMimeOverImage->isChecked());
398 d->settings->setShowCoordinates(d->showCoordinates->isChecked());
399 d->settings->setRightSideBarStyle(d->sidebarType->currentIndex());
400 d->settings->setUpdateType(d->updateType->currentIndex());
401 d->settings->setUpdateWithDebug(d->updateWithDebug->isChecked());
402 d->settings->setSortRole(d->sortOrderComboBox->currentIndex());
403 d->settings->setReverseSort(d->sortReverse->isChecked());
404
405 #ifdef HAVE_APPSTYLE_SUPPORT
406
407 d->settings->setApplicationStyle(d->applicationStyle->currentText());
408
409 #endif
410
411 d->settings->setIconTheme(d->applicationIcon->currentData().toString());
412 d->settings->setApplicationFont(d->applicationFont->font());
413 d->settings->syncConfig();
414 }
415
416 } // namespace ShowFoto
417