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 | |