1/*
2 * SPDX-FileCopyrightText: 2017 by Marco Martin <mart@kde.org>
3 * SPDX-FileCopyrightText: 2021 Arjen Hiemstra <ahiemstra@heimr.nl>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "basictheme_p.h"
9#include "styleselector.h"
10
11#include <QFile>
12#include <QGuiApplication>
13
14#include "kirigamiplatform_logging.h"
15
16namespace Kirigami
17{
18namespace Platform
19{
20
21BasicThemeDefinition::BasicThemeDefinition(QObject *parent)
22 : QObject(parent)
23{
24 defaultFont = qGuiApp->font();
25
26 smallFont = qGuiApp->font();
27 smallFont.setPointSize(smallFont.pointSize() - 2);
28}
29
30void BasicThemeDefinition::syncToQml(PlatformTheme *object)
31{
32 auto item = qobject_cast<QQuickItem *>(o: object->parent());
33 if (item && qmlAttachedPropertiesObject<PlatformTheme>(obj: item, create: false) == object) {
34 Q_EMIT sync(object: item);
35 }
36}
37
38BasicThemeInstance::BasicThemeInstance(QObject *parent)
39 : QObject(parent)
40{
41}
42
43BasicThemeDefinition &BasicThemeInstance::themeDefinition(QQmlEngine *engine)
44{
45 if (m_themeDefinition) {
46 return *m_themeDefinition;
47 }
48
49 auto themeUrl = StyleSelector::componentUrl(QStringLiteral("Theme.qml"));
50 QQmlComponent component(engine);
51 component.loadUrl(url: themeUrl);
52
53 if (!component.isError()) {
54 auto result = component.create();
55 if (auto themeDefinition = qobject_cast<BasicThemeDefinition *>(object: result)) {
56 m_themeDefinition.reset(p: themeDefinition);
57 } else {
58 const auto errors = component.errors();
59 for (auto error : errors) {
60 qCWarning(KirigamiPlatform) << error.toString();
61 }
62
63 qCWarning(KirigamiPlatform) << "Invalid Theme file, using default Basic theme.";
64 m_themeDefinition = std::make_unique<BasicThemeDefinition>();
65 }
66 } else {
67 qCDebug(KirigamiPlatform) << "No Theme file found, using default Basic theme";
68 m_themeDefinition = std::make_unique<BasicThemeDefinition>();
69 }
70
71 connect(sender: m_themeDefinition.get(), signal: &BasicThemeDefinition::changed, context: this, slot: &BasicThemeInstance::onDefinitionChanged);
72
73 return *m_themeDefinition;
74}
75
76void BasicThemeInstance::onDefinitionChanged()
77{
78 for (auto watcher : std::as_const(t&: watchers)) {
79 watcher->sync();
80 }
81}
82
83Q_GLOBAL_STATIC(BasicThemeInstance, basicThemeInstance)
84
85BasicTheme::BasicTheme(QObject *parent)
86 : PlatformTheme(parent)
87{
88 basicThemeInstance()->watchers.append(t: this);
89
90 sync();
91}
92
93BasicTheme::~BasicTheme()
94{
95 basicThemeInstance()->watchers.removeOne(t: this);
96}
97
98void BasicTheme::sync()
99{
100 auto &definition = basicThemeInstance()->themeDefinition(engine: qmlEngine(parent()));
101
102 switch (colorSet()) {
103 case BasicTheme::Button:
104 setTextColor(tint(color: definition.buttonTextColor));
105 setBackgroundColor(tint(color: definition.buttonBackgroundColor));
106 setAlternateBackgroundColor(tint(color: definition.buttonAlternateBackgroundColor));
107 setHoverColor(tint(color: definition.buttonHoverColor));
108 setFocusColor(tint(color: definition.buttonFocusColor));
109 break;
110 case BasicTheme::View:
111 setTextColor(tint(color: definition.viewTextColor));
112 setBackgroundColor(tint(color: definition.viewBackgroundColor));
113 setAlternateBackgroundColor(tint(color: definition.viewAlternateBackgroundColor));
114 setHoverColor(tint(color: definition.viewHoverColor));
115 setFocusColor(tint(color: definition.viewFocusColor));
116 break;
117 case BasicTheme::Selection:
118 setTextColor(tint(color: definition.selectionTextColor));
119 setBackgroundColor(tint(color: definition.selectionBackgroundColor));
120 setAlternateBackgroundColor(tint(color: definition.selectionAlternateBackgroundColor));
121 setHoverColor(tint(color: definition.selectionHoverColor));
122 setFocusColor(tint(color: definition.selectionFocusColor));
123 break;
124 case BasicTheme::Tooltip:
125 setTextColor(tint(color: definition.tooltipTextColor));
126 setBackgroundColor(tint(color: definition.tooltipBackgroundColor));
127 setAlternateBackgroundColor(tint(color: definition.tooltipAlternateBackgroundColor));
128 setHoverColor(tint(color: definition.tooltipHoverColor));
129 setFocusColor(tint(color: definition.tooltipFocusColor));
130 break;
131 case BasicTheme::Complementary:
132 setTextColor(tint(color: definition.complementaryTextColor));
133 setBackgroundColor(tint(color: definition.complementaryBackgroundColor));
134 setAlternateBackgroundColor(tint(color: definition.complementaryAlternateBackgroundColor));
135 setHoverColor(tint(color: definition.complementaryHoverColor));
136 setFocusColor(tint(color: definition.complementaryFocusColor));
137 break;
138 case BasicTheme::Window:
139 default:
140 setTextColor(tint(color: definition.textColor));
141 setBackgroundColor(tint(color: definition.backgroundColor));
142 setAlternateBackgroundColor(tint(color: definition.alternateBackgroundColor));
143 setHoverColor(tint(color: definition.hoverColor));
144 setFocusColor(tint(color: definition.focusColor));
145 break;
146 }
147
148 setDisabledTextColor(tint(color: definition.disabledTextColor));
149 setHighlightColor(tint(color: definition.highlightColor));
150 setHighlightedTextColor(tint(color: definition.highlightedTextColor));
151 setActiveTextColor(tint(color: definition.activeTextColor));
152 setActiveBackgroundColor(tint(color: definition.activeBackgroundColor));
153 setLinkColor(tint(color: definition.linkColor));
154 setLinkBackgroundColor(tint(color: definition.linkBackgroundColor));
155 setVisitedLinkColor(tint(color: definition.visitedLinkColor));
156 setVisitedLinkBackgroundColor(tint(color: definition.visitedLinkBackgroundColor));
157 setNegativeTextColor(tint(color: definition.negativeTextColor));
158 setNegativeBackgroundColor(tint(color: definition.negativeBackgroundColor));
159 setNeutralTextColor(tint(color: definition.neutralTextColor));
160 setNeutralBackgroundColor(tint(color: definition.neutralBackgroundColor));
161 setPositiveTextColor(tint(color: definition.positiveTextColor));
162 setPositiveBackgroundColor(tint(color: definition.positiveBackgroundColor));
163
164 setDefaultFont(definition.defaultFont);
165 setSmallFont(definition.smallFont);
166}
167
168bool BasicTheme::event(QEvent *event)
169{
170 if (event->type() == PlatformThemeEvents::DataChangedEvent::type) {
171 sync();
172 }
173
174 if (event->type() == PlatformThemeEvents::ColorSetChangedEvent::type) {
175 sync();
176 }
177
178 if (event->type() == PlatformThemeEvents::ColorGroupChangedEvent::type) {
179 sync();
180 }
181
182 if (event->type() == PlatformThemeEvents::ColorChangedEvent::type) {
183 basicThemeInstance()->themeDefinition(engine: qmlEngine(parent())).syncToQml(object: this);
184 }
185
186 if (event->type() == PlatformThemeEvents::FontChangedEvent::type) {
187 basicThemeInstance()->themeDefinition(engine: qmlEngine(parent())).syncToQml(object: this);
188 }
189
190 return PlatformTheme::event(event);
191}
192
193QColor BasicTheme::tint(const QColor &color)
194{
195 switch (colorGroup()) {
196 case PlatformTheme::Inactive:
197 return QColor::fromHsvF(h: color.hueF(), s: color.saturationF() * 0.5, v: color.valueF());
198 case PlatformTheme::Disabled:
199 return QColor::fromHsvF(h: color.hueF(), s: color.saturationF() * 0.5, v: color.valueF() * 0.8);
200 default:
201 return color;
202 }
203}
204
205}
206}
207
208#include "moc_basictheme_p.cpp"
209

source code of kirigami/src/platform/basictheme.cpp