| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2024 Christoph Cullmann <cullmann@kde.org> |
| 3 | |
| 4 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 5 | */ |
| 6 | |
| 7 | #include "kstylemanager.h" |
| 8 | |
| 9 | #include <KActionMenu> |
| 10 | #include <KConfigGroup> |
| 11 | #include <KLocalizedString> |
| 12 | #include <KSharedConfig> |
| 13 | |
| 14 | #include <QAction> |
| 15 | #include <QActionGroup> |
| 16 | #include <QApplication> |
| 17 | #include <QStyle> |
| 18 | #include <QStyleFactory> |
| 19 | |
| 20 | #include <private/qguiapplication_p.h> |
| 21 | #include <qpa/qplatformtheme.h> |
| 22 | |
| 23 | static bool supported() |
| 24 | { |
| 25 | // do nothing if an explicit style has been requested |
| 26 | if (!QGuiApplicationPrivate::styleOverride.isEmpty()) { |
| 27 | return false; |
| 28 | } |
| 29 | |
| 30 | // do nothing if we have the proper platform theme already |
| 31 | if (QGuiApplicationPrivate::platformTheme() && QGuiApplicationPrivate::platformTheme()->name() == QLatin1String("kde" )) { |
| 32 | return false; |
| 33 | } |
| 34 | |
| 35 | return true; |
| 36 | } |
| 37 | |
| 38 | void KStyleManager::initStyle() |
| 39 | { |
| 40 | if (!supported()) { |
| 41 | return; |
| 42 | } |
| 43 | |
| 44 | // get config, with fallback to kdeglobals |
| 45 | const auto config = KSharedConfig::openConfig(); |
| 46 | |
| 47 | // enforce the style configured by the user, with kdeglobals fallback |
| 48 | // if not set or the style is not there, use Breeze |
| 49 | QString styleToUse = KConfigGroup(config, QStringLiteral("KDE" )).readEntry(key: "widgetStyle" , aDefault: QString()); |
| 50 | if (styleToUse.isEmpty() || !QApplication::setStyle(styleToUse)) { |
| 51 | styleToUse = QStringLiteral("breeze" ); |
| 52 | QApplication::setStyle(styleToUse); |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | QAction *KStyleManager::createConfigureAction(QObject *parent) |
| 57 | { |
| 58 | // if we are running with our application theme, just return a disabled & hidden action |
| 59 | // there we just follow the Plasma theme |
| 60 | if (!supported()) { |
| 61 | QAction *a = new QAction(parent); |
| 62 | a->setEnabled(false); |
| 63 | a->setVisible(false); |
| 64 | return a; |
| 65 | } |
| 66 | |
| 67 | // else: provide style chooser |
| 68 | |
| 69 | // get config, without fallback to kdeglobals |
| 70 | const auto config = KSharedConfig::openConfig(fileName: QString(), mode: KConfig::NoGlobals); |
| 71 | const QString styleWeUse = KConfigGroup(config, QStringLiteral("KDE" )).readEntry(key: "widgetStyle" , aDefault: QString()); |
| 72 | |
| 73 | // build menu with default to reset setting and all known styles |
| 74 | KActionMenu * = new KActionMenu(QIcon::fromTheme(QStringLiteral("preferences-desktop-theme-applications" )), i18n("Application Style" ), parent); |
| 75 | QActionGroup *group = new QActionGroup(menu); |
| 76 | const QStringList styles = QStringList() << QString() << QStyleFactory::keys(); |
| 77 | for (const QString &style : styles) { |
| 78 | QAction *action = new QAction(style.isEmpty() ? i18n("Default" ) : style, menu); |
| 79 | action->setData(style); |
| 80 | action->setActionGroup(group); |
| 81 | action->setCheckable(true); |
| 82 | if (style.toLower() == styleWeUse.toLower()) { |
| 83 | action->setChecked(true); |
| 84 | } |
| 85 | menu->addAction(action); |
| 86 | } |
| 87 | |
| 88 | // toggle style change |
| 89 | QObject::connect(sender: group, signal: &QActionGroup::triggered, context: group, slot: [](QAction *action) { |
| 90 | const QString styleToUse = action->data().toString(); |
| 91 | const auto config = KSharedConfig::openConfig(); |
| 92 | if (styleToUse.isEmpty()) { |
| 93 | KConfigGroup(config, QStringLiteral("KDE" )).deleteEntry(key: "widgetStyle" ); |
| 94 | } else { |
| 95 | KConfigGroup(config, QStringLiteral("KDE" )).writeEntry(key: "widgetStyle" , value: styleToUse); |
| 96 | } |
| 97 | initStyle(); |
| 98 | }); |
| 99 | |
| 100 | return menu; |
| 101 | } |
| 102 | |