File indexing completed on 2025-01-05 03:57:56

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2005-04-02
0007  * Description : setup Misc tab.
0008  *
0009  * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText:      2008 by Arnd Baecker <arnd dot baecker at web dot de>
0011  * SPDX-FileCopyrightText:      2014 by Mohamed_Anwer <m_dot_anwer at gmx dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "showfotosetupmisc.h"
0018 
0019 // Qt includes
0020 
0021 #include <QCheckBox>
0022 #include <QColor>
0023 #include <QGroupBox>
0024 #include <QLabel>
0025 #include <QVBoxLayout>
0026 #include <QStyleFactory>
0027 #include <QApplication>
0028 #include <QDirIterator>
0029 #include <QStyle>
0030 #include <QComboBox>
0031 #include <QFile>
0032 #include <QTabWidget>
0033 #include <QMessageBox>
0034 #include <QPushButton>
0035 
0036 // KDE includes
0037 
0038 #include <klocalizedstring.h>
0039 
0040 // Local includes
0041 
0042 #include "digikam_config.h"
0043 #include "dlayoutbox.h"
0044 #include "dfontselect.h"
0045 #include "showfotosettings.h"
0046 #include "systemsettingswidget.h"
0047 #include "onlineversionchecker.h"
0048 #include "showfotosetup.h"
0049 #include "localizeconfig.h"
0050 
0051 #ifdef HAVE_SONNET
0052 #   include "spellcheckconfig.h"
0053 #endif
0054 
0055 using namespace Digikam;
0056 
0057 namespace ShowFoto
0058 {
0059 
0060 class Q_DECL_HIDDEN ShowfotoSetupMisc::Private
0061 {
0062 public:
0063 
0064     explicit Private()
0065       : tab                     (nullptr),
0066         updateTypeLabel         (nullptr),
0067         sidebarTypeLabel        (nullptr),
0068         applicationStyleLabel   (nullptr),
0069         applicationIconLabel    (nullptr),
0070         showSplash              (nullptr),
0071         nativeFileDialog        (nullptr),
0072         itemCenter              (nullptr),
0073         showMimeOverImage       (nullptr),
0074         showCoordinates         (nullptr),
0075         sortReverse             (nullptr),
0076         updateType              (nullptr),
0077         updateWithDebug         (nullptr),
0078         sidebarType             (nullptr),
0079         sortOrderComboBox       (nullptr),
0080         applicationStyle        (nullptr),
0081         applicationIcon         (nullptr),
0082         applicationFont         (nullptr),
0083         systemSettingsWidget    (nullptr),
0084 
0085 #ifdef HAVE_SONNET
0086 
0087         spellCheckWidget        (nullptr),
0088 
0089 #endif
0090 
0091         localizeWidget          (nullptr),
0092         settings                (ShowfotoSettings::instance())
0093     {
0094     }
0095 
0096     QTabWidget*           tab;
0097 
0098     QLabel*               updateTypeLabel;
0099     QLabel*               sidebarTypeLabel;
0100     QLabel*               applicationStyleLabel;
0101     QLabel*               applicationIconLabel;
0102 
0103     QCheckBox*            showSplash;
0104     QCheckBox*            nativeFileDialog;
0105     QCheckBox*            itemCenter;
0106     QCheckBox*            showMimeOverImage;
0107     QCheckBox*            showCoordinates;
0108     QCheckBox*            sortReverse;
0109 
0110     QComboBox*            updateType;
0111     QCheckBox*            updateWithDebug;
0112 
0113     QComboBox*            sidebarType;
0114     QComboBox*            sortOrderComboBox;
0115     QComboBox*            applicationStyle;
0116     QComboBox*            applicationIcon;
0117     DFontSelect*          applicationFont;
0118 
0119     SystemSettingsWidget* systemSettingsWidget;
0120 
0121 #ifdef HAVE_SONNET
0122 
0123     SpellCheckConfig*     spellCheckWidget;
0124 
0125 #endif
0126 
0127     LocalizeConfig*       localizeWidget;
0128     ShowfotoSettings*     settings;
0129 };
0130 
0131 // --------------------------------------------------------
0132 
0133 ShowfotoSetupMisc::ShowfotoSetupMisc(QWidget* const parent)
0134     : QScrollArea(parent),
0135       d          (new Private)
0136 {
0137     d->tab            = new QTabWidget(viewport());
0138     setWidget(d->tab);
0139     setWidgetResizable(true);
0140 
0141     const int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0142                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0143 
0144     // -- Application Behavior Options --------------------------------------------------------
0145 
0146     QWidget* const behaviourPanel = new QWidget(d->tab);
0147     QVBoxLayout* const layout     = new QVBoxLayout(behaviourPanel);
0148 
0149     // -- Sort Order Options ----------------------------------
0150 
0151     QGroupBox* const sortOptionsGroup = new QGroupBox(i18n("Thumbbar, Folder-View, and Stack-View Items Sort Order"), behaviourPanel);
0152     QVBoxLayout* const gLayout4       = new QVBoxLayout();
0153 
0154     DHBox* const sortBox = new DHBox(sortOptionsGroup);
0155     new QLabel(i18n("Sort images by:"), sortBox);
0156     d->sortOrderComboBox = new QComboBox(sortBox);
0157     d->sortOrderComboBox->insertItem(SortByDate,     i18nc("sort images by date", "Date"));
0158     d->sortOrderComboBox->insertItem(SortByName,     i18nc("sort images by name", "Name"));
0159     d->sortOrderComboBox->insertItem(SortByFileSize, i18nc("sort images by size", "File Size"));
0160     d->sortOrderComboBox->setWhatsThis(i18n("Here, select whether newly-loaded "
0161                                             "images are sorted by their date, name, or size on disk."));
0162 
0163     d->sortReverse = new QCheckBox(i18n("Reverse ordering"), sortOptionsGroup);
0164     d->sortReverse->setWhatsThis(i18n("If this option is enabled, newly-loaded "
0165                                       "images will be sorted in descending order."));
0166 
0167     gLayout4->addWidget(sortBox);
0168     gLayout4->addWidget(d->sortReverse);
0169     sortOptionsGroup->setLayout(gLayout4);
0170 
0171     // Thumbnails Options -------------------------------------
0172 
0173     QGroupBox* const thOptionsGroup = new QGroupBox(i18n("Thumbbar Items"), behaviourPanel);
0174     QVBoxLayout* const gLayout3     = new QVBoxLayout();
0175 
0176     d->showMimeOverImage = new QCheckBox(i18n("&Show image Format"),          thOptionsGroup);
0177     d->showMimeOverImage->setWhatsThis(i18n("Set this option to show image format over image thumbnail."));
0178     d->showCoordinates   = new QCheckBox(i18n("&Show Geolocation Indicator"), thOptionsGroup);
0179     d->showCoordinates->setWhatsThis(i18n("Set this option to indicate if image has geolocation information."));
0180     d->itemCenter        = new QCheckBox(i18n("Scroll current item to center of thumbbar"), thOptionsGroup);
0181 
0182     gLayout3->addWidget(d->showMimeOverImage);
0183     gLayout3->addWidget(d->showCoordinates);
0184     gLayout3->addWidget(d->itemCenter);
0185     thOptionsGroup->setLayout(gLayout3);
0186 
0187     // Update Options ----------------------------------------
0188 
0189     QGroupBox* const upOptionsGroup = new QGroupBox(i18n("Updates"), behaviourPanel);
0190     QVBoxLayout* const gLayout5     = new QVBoxLayout();
0191 
0192     DHBox* const updateHbox = new DHBox(upOptionsGroup);
0193     d->updateTypeLabel      = new QLabel(i18n("Check for new version:"), updateHbox);
0194     d->updateType           = new QComboBox(updateHbox);
0195     d->updateType->addItem(i18n("Only For Stable Releases"), 0);
0196     d->updateType->addItem(i18n("Weekly Pre-Releases"),      1);
0197     d->updateType->setToolTip(i18n("Set this option to configure which kind of new versions must be check for updates.\n"
0198                                    "\"Stable\" releases are official versions safe to use in production.\n"
0199                                    "\"Pre-releases\" are proposed weekly to tests quickly new features\n"
0200                                    "and are not recommended to use in production as bugs can remain."));
0201 
0202     d->updateWithDebug = new QCheckBox(i18n("Use Version With Debug Symbols"), upOptionsGroup);
0203     d->updateWithDebug->setWhatsThis(i18n("If this option is enabled, a version including debug symbols will be used for updates.\n"
0204                                           "This version is more heavy but can help developers to trace dysfunctions in debugger."));
0205 
0206     DHBox* const updateHbox2     = new DHBox(upOptionsGroup);
0207     QLabel* const lastCheckLabel = new QLabel(updateHbox2);
0208     lastCheckLabel->setText(i18n("Last check: %1", OnlineVersionChecker::lastCheckDate()));
0209     QPushButton* const updateNow = new QPushButton(i18n("Check now..."), updateHbox2);
0210 
0211     connect(updateNow, &QPushButton::pressed,
0212             this, [=]()
0213         {
0214             if (parent)
0215             {
0216                 parent->close();
0217             }
0218 
0219             ShowfotoSetup::onlineVersionCheck();
0220         }
0221     );
0222 
0223     gLayout5->addWidget(updateHbox);
0224     gLayout5->addWidget(d->updateWithDebug);
0225     gLayout5->addWidget(updateHbox2);
0226     upOptionsGroup->setLayout(gLayout5);
0227 
0228     // ---------------------------------------------------------
0229 
0230     layout->setContentsMargins(spacing, spacing, spacing, spacing);
0231     layout->setSpacing(spacing);
0232     layout->addWidget(sortOptionsGroup);
0233     layout->addWidget(thOptionsGroup);
0234     layout->addWidget(upOptionsGroup);
0235     layout->addStretch();
0236 
0237     d->tab->insertTab(Behaviour, behaviourPanel, i18nc("@title:tab", "Behaviour"));
0238 
0239     // -- Application Appearance Options --------------------------------------------------------
0240 
0241     QWidget* const appearancePanel = new QWidget(d->tab);
0242     QVBoxLayout* const layout2     = new QVBoxLayout(appearancePanel);
0243 
0244     d->showSplash       = new QCheckBox(i18n("&Show splash screen at startup"),            appearancePanel);
0245     d->nativeFileDialog = new QCheckBox(i18n("Use native file dialogs from the system"),   appearancePanel);
0246 
0247     DHBox* const tabStyleHbox = new DHBox(appearancePanel);
0248     d->sidebarTypeLabel       = new QLabel(i18n("Sidebar tab title:"), tabStyleHbox);
0249     d->sidebarType            = new QComboBox(tabStyleHbox);
0250     d->sidebarType->addItem(i18n("Only For Active Tab"), 0);
0251     d->sidebarType->addItem(i18n("For All Tabs"),        1);
0252     d->sidebarType->setToolTip(i18n("Set this option to configure how sidebars tab title are visible."));
0253 
0254     DHBox* const appStyleHbox = new DHBox(appearancePanel);
0255     d->applicationStyleLabel  = new QLabel(i18n("Widget style:"), appStyleHbox);
0256     d->applicationStyle       = new QComboBox(appStyleHbox);
0257     d->applicationStyle->setToolTip(i18n("Set this option to choose the default window decoration and looks."));
0258 
0259     Q_FOREACH (const QString& style, QStyleFactory::keys())
0260     {
0261         QString sitem = style;
0262         sitem[0]      = sitem[0].toUpper();
0263 
0264         if (sitem != QLatin1String("Macintosh"))        // See bug #475572
0265         {
0266             d->applicationStyle->addItem(sitem, sitem.toLower());
0267         }
0268     }
0269 
0270 #ifndef HAVE_APPSTYLE_SUPPORT
0271 
0272     // See Bug #365262
0273 
0274     appStyleHbox->setVisible(false);
0275 
0276 #endif
0277 
0278     DHBox* const iconThemeHbox = new DHBox(appearancePanel);
0279     d->applicationIconLabel    = new QLabel(i18n("Icon theme (changes after restart):"), iconThemeHbox);
0280     d->applicationIcon         = new QComboBox(iconThemeHbox);
0281     d->applicationIcon->setToolTip(i18n("Set this option to choose the default icon theme."));
0282 
0283     QMap<QString, QString> iconThemes;
0284     QMap<QString, QString> themeWhiteList;
0285     themeWhiteList.insert(QLatin1String("adwaita"),         i18nc("icon theme", "Adwaita"));
0286     themeWhiteList.insert(QLatin1String("breeze"),          i18nc("icon theme", "Breeze"));
0287     themeWhiteList.insert(QLatin1String("breeze-dark"),     i18nc("icon theme", "Breeze Dark"));
0288     themeWhiteList.insert(QLatin1String("faenza"),          i18nc("icon theme", "Faenza"));
0289     themeWhiteList.insert(QLatin1String("faenza-ambiance"), i18nc("icon theme", "Ambiance"));
0290     themeWhiteList.insert(QLatin1String("humanity"),        i18nc("icon theme", "Humanity"));
0291     themeWhiteList.insert(QLatin1String("oxygen"),          i18nc("icon theme", "Oxygen"));
0292 
0293     Q_FOREACH (const QString& path, QIcon::themeSearchPaths())
0294     {
0295         QDirIterator it(path, QDir::Dirs       |
0296                               QDir::NoSymLinks |
0297                               QDir::NoDotAndDotDot);
0298 
0299         while (it.hasNext())
0300         {
0301             if (QFile::exists(it.next() + QLatin1String("/index.theme")))
0302             {
0303                 QString iconKey = it.fileInfo().fileName().toLower();
0304 
0305                 if (themeWhiteList.contains(iconKey))
0306                 {
0307                     iconThemes[themeWhiteList.value(iconKey)] = it.fileInfo().fileName();
0308                 }
0309             }
0310         }
0311     }
0312 
0313     QMap<QString, QString>::const_iterator it = iconThemes.constBegin();
0314     d->applicationIcon->addItem(i18n("Use Icon Theme From System"), QString());
0315 
0316     for ( ; it != iconThemes.constEnd() ; ++it)
0317     {
0318         d->applicationIcon->addItem(it.key(), it.value());
0319     }
0320 
0321     d->applicationFont = new DFontSelect(i18n("Application font:"), appearancePanel);
0322     d->applicationFont->setToolTip(i18n("Select here the font used to display text in whole application."));
0323 
0324     // --------------------------------------------------------
0325 
0326     layout2->setContentsMargins(spacing, spacing, spacing, spacing);
0327     layout2->setSpacing(spacing);
0328     layout2->addWidget(d->showSplash);
0329     layout2->addWidget(d->nativeFileDialog);
0330     layout2->addWidget(tabStyleHbox);
0331     layout2->addWidget(appStyleHbox);
0332     layout2->addWidget(iconThemeHbox);
0333     layout2->addWidget(d->applicationFont);
0334     layout2->addStretch();
0335 
0336     d->tab->insertTab(Appearance, appearancePanel, i18nc("@title:tab", "Appearance"));
0337 
0338     // -- Spell Check and Localize Options --------------------------------------
0339 
0340 #ifdef HAVE_SONNET
0341 
0342     d->spellCheckWidget = new SpellCheckConfig(d->tab);
0343 
0344     d->tab->insertTab(SpellCheck, d->spellCheckWidget, i18nc("@title:tab", "Spellcheck"));
0345 
0346 #endif
0347 
0348     d->localizeWidget = new LocalizeConfig(d->tab);
0349 
0350     d->tab->insertTab(Localize, d->localizeWidget, i18nc("@title:tab", "Localize"));
0351 
0352     // -- System Options --------------------------------------------------------
0353 
0354     d->systemSettingsWidget = new SystemSettingsWidget(d->tab);
0355 
0356     d->tab->insertTab(System, d->systemSettingsWidget, i18nc("@title:tab", "System"));
0357 
0358     // --------------------------------------------------------
0359 
0360     readSettings();
0361 }
0362 
0363 ShowfotoSetupMisc::~ShowfotoSetupMisc()
0364 {
0365     delete d;
0366 }
0367 
0368 void ShowfotoSetupMisc::setActiveTab(MiscTab tab)
0369 {
0370     d->tab->setCurrentIndex(tab);
0371 }
0372 
0373 ShowfotoSetupMisc::MiscTab ShowfotoSetupMisc::activeTab() const
0374 {
0375     return (MiscTab)d->tab->currentIndex();
0376 }
0377 
0378 bool ShowfotoSetupMisc::checkSettings()
0379 {
0380     // If check for new version use weekly pre-releases, warn end-user.
0381 
0382     if ((d->updateType->currentIndex()                    == 1) &&
0383         (ShowfotoSettings::instance()->getUpdateType() == 0))
0384     {
0385         d->tab->setCurrentIndex(0);
0386 
0387         int result = QMessageBox::warning(this, qApp->applicationName(),
0388                                           i18n("Check for new version option will verify the pre-releases.\n"
0389                                                "\"Pre-releases\" are proposed weekly to tests quickly new features.\n"
0390                                                "It's not recommended to use pre-release in production as bugs can remain,\n"
0391                                                "unless you know what you are doing.\n"
0392                                                "Do you want to continue?"),
0393                                                 QMessageBox::Yes | QMessageBox::No);
0394         if (result == QMessageBox::Yes)
0395         {
0396             return true;
0397         }
0398 
0399         return false;
0400     }
0401 
0402     return true;
0403 }
0404 
0405 void ShowfotoSetupMisc::readSettings()
0406 {
0407     d->systemSettingsWidget->readSettings();
0408 
0409     d->showSplash->setChecked(d->settings->getShowSplash());
0410     d->nativeFileDialog->setChecked(d->settings->getNativeFileDialog());
0411     d->itemCenter->setChecked(d->settings->getItemCenter());
0412     d->showMimeOverImage->setChecked(d->settings->getShowFormatOverThumbnail());
0413     d->showCoordinates->setChecked(d->settings->getShowCoordinates());
0414     d->sidebarType->setCurrentIndex(d->settings->getRightSideBarStyle());
0415     d->updateType->setCurrentIndex(d->settings->getUpdateType());
0416     d->updateWithDebug->setChecked(d->settings->getUpdateWithDebug());
0417     d->sortOrderComboBox->setCurrentIndex(d->settings->getSortRole());
0418     d->sortReverse->setChecked(d->settings->getReverseSort());
0419 
0420 #ifdef HAVE_APPSTYLE_SUPPORT
0421 
0422     d->applicationStyle->setCurrentIndex(d->applicationStyle->findData(d->settings->getApplicationStyle().toLower()));
0423 
0424 #endif
0425 
0426     d->applicationIcon->setCurrentIndex(d->applicationIcon->findData(d->settings->getIconTheme()));
0427     d->applicationFont->setFont(d->settings->getApplicationFont());
0428 
0429     // NOTE: Spellcheck and Localize read settings is done in widget constructor.
0430 }
0431 
0432 void ShowfotoSetupMisc::applySettings()
0433 {
0434     d->systemSettingsWidget->saveSettings();
0435 
0436     d->settings->setShowSplash(d->showSplash->isChecked());
0437     d->settings->setNativeFileDialog(d->nativeFileDialog->isChecked());
0438     d->settings->setItemCenter(d->itemCenter->isChecked());
0439     d->settings->setShowFormatOverThumbnail(d->showMimeOverImage->isChecked());
0440     d->settings->setShowCoordinates(d->showCoordinates->isChecked());
0441     d->settings->setRightSideBarStyle(d->sidebarType->currentIndex());
0442     d->settings->setUpdateType(d->updateType->currentIndex());
0443     d->settings->setUpdateWithDebug(d->updateWithDebug->isChecked());
0444     d->settings->setSortRole(d->sortOrderComboBox->currentIndex());
0445     d->settings->setReverseSort(d->sortReverse->isChecked());
0446 
0447 #ifdef HAVE_APPSTYLE_SUPPORT
0448 
0449     d->settings->setApplicationStyle(d->applicationStyle->currentText());
0450 
0451 #endif
0452 
0453     d->settings->setIconTheme(d->applicationIcon->currentData().toString());
0454     d->settings->setApplicationFont(d->applicationFont->font());
0455     d->settings->syncConfig();
0456 
0457 #ifdef HAVE_SONNET
0458 
0459     d->spellCheckWidget->applySettings();
0460 
0461 #endif
0462 
0463     d->localizeWidget->applySettings();
0464 }
0465 
0466 } // namespace ShowFoto
0467 
0468 #include "moc_showfotosetupmisc.cpp"