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