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
23static 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
38void 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
56QAction *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 *menu = 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

source code of kconfigwidgets/src/kstylemanager.cpp