Libplasma

theme.cpp
1/*
2 SPDX-FileCopyrightText: 2006-2007 Aaron Seigo <aseigo@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "theme.h"
8#include "private/theme_p.h"
9
10#include <QFile>
11#include <QFileInfo>
12#include <QFontDatabase>
13#include <QFontMetrics>
14#include <QMutableListIterator>
15#include <QPair>
16#include <QStringBuilder>
17#include <QThread>
18#include <QTimer>
19
20#include "config-plasma.h"
21
22#include <KColorScheme>
23#include <KConfigGroup>
24#include <KWindowEffects>
25#include <QDebug>
26#include <QStandardPaths>
27
28#include "debug_p.h"
29
30namespace Plasma
31{
34{
35 if (!ThemePrivate::globalTheme) {
36 ThemePrivate::globalTheme = new ThemePrivate;
37 ThemePrivate::globalTheme->settingsChanged(false);
38 }
39 ThemePrivate::globalTheme->ref.ref();
40 d = ThemePrivate::globalTheme;
41
42 connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged);
43 connect(d, &ThemePrivate::defaultFontChanged, this, &Theme::defaultFontChanged);
44 connect(d, &ThemePrivate::smallestFontChanged, this, &Theme::smallestFontChanged);
45}
46
49{
50 auto &priv = ThemePrivate::themes[themeName];
51 if (!priv) {
52 priv = new ThemePrivate;
53 }
54
55 priv->ref.ref();
56 d = priv;
57
58 d->setThemeName(themeName, false, false);
59 d->fixedName = true;
60 connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged);
61}
62
63Theme::~Theme()
64{
65 if (d == ThemePrivate::globalTheme) {
66 if (!d->ref.deref()) {
67 disconnect(ThemePrivate::globalTheme, nullptr, this, nullptr);
68 delete ThemePrivate::globalTheme;
69 ThemePrivate::globalTheme = nullptr;
70 d = nullptr;
71 }
72 } else {
73 if (!d->ref.deref()) {
74 delete ThemePrivate::themes.take(d->themeName);
75 }
76 }
77}
78
79void Theme::setThemeName(const QString &themeName)
80{
81 if (d->themeName == themeName) {
82 return;
83 }
84
85 if (d != ThemePrivate::globalTheme) {
86 disconnect(QCoreApplication::instance(), nullptr, d, nullptr);
87 if (!d->ref.deref()) {
88 delete ThemePrivate::themes.take(d->themeName);
89 }
90
91 auto &priv = ThemePrivate::themes[themeName];
92 if (!priv) {
93 priv = new ThemePrivate;
94 }
95 priv->ref.ref();
96 d = priv;
97 connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged);
98 }
99
100 d->setThemeName(themeName, true, true);
101}
102
103QString Theme::themeName() const
104{
105 return d->themeName;
106}
107
109{
110 // look for a compressed svg file in the theme
111 if (name.contains(QLatin1String("../")) || name.isEmpty()) {
112 // we don't support relative paths
113 // qCDebug(LOG_PLASMA) << "Theme says: bad image path " << name;
114 return QString();
115 }
116
117 const QString svgzName = name % QLatin1String(".svgz");
118 QString path = d->findInTheme(svgzName, d->themeName);
119
120 if (path.isEmpty()) {
121 // try for an uncompressed svg file
122 const QString svgName = name % QLatin1String(".svg");
123 path = d->findInTheme(svgName, d->themeName);
124
125 // search in fallback themes if necessary
126 for (int i = 0; path.isEmpty() && i < d->fallbackThemes.count(); ++i) {
127 if (d->themeName == d->fallbackThemes[i]) {
128 continue;
129 }
130
131 // try a compressed svg file in the fallback theme
132 path = d->findInTheme(svgzName, d->fallbackThemes[i]);
133
134 if (path.isEmpty()) {
135 // try an uncompressed svg file in the fallback theme
136 path = d->findInTheme(svgName, d->fallbackThemes[i]);
137 }
138 }
139 }
140
141 return path;
142}
143
144QString Theme::backgroundPath(const QString &image) const
145{
146 return d->imagePath(themeName(), QStringLiteral("/appbackgrounds/"), image);
147}
148
149QPalette Theme::palette() const
150{
151 return d->palette;
152}
153
154QPalette Theme::globalPalette()
155{
156 if (!ThemePrivate::globalTheme) {
157 ThemePrivate::globalTheme = new ThemePrivate;
158 ThemePrivate::globalTheme->settingsChanged(false);
159 }
160 return ThemePrivate::globalTheme->palette;
161}
162
163KSharedConfigPtr Theme::globalColorScheme()
164{
165 if (!ThemePrivate::globalTheme) {
166 ThemePrivate::globalTheme = new ThemePrivate;
167 ThemePrivate::globalTheme->settingsChanged(false);
168 }
169 return ThemePrivate::globalTheme->colors;
170}
171
172QString Theme::wallpaperPath(const QSize &size) const
173{
174 QString fullPath;
175 QString image = d->defaultWallpaperTheme + QStringLiteral("/contents/images/%1x%2") + d->defaultWallpaperSuffix;
176 QString defaultImage = image.arg(d->defaultWallpaperWidth).arg(d->defaultWallpaperHeight);
177
178 if (size.isValid()) {
179 // try to customize the paper to the size requested
180 // TODO: this should do better than just fallback to the default size.
181 // a "best fit" matching would be far better, so we don't end
182 // up returning a 1920x1200 wallpaper for a 640x480 request ;)
183 image = image.arg(size.width()).arg(size.height());
184 } else {
185 image = defaultImage;
186 }
187
188 // TODO: the theme's wallpaper overrides regularly installed wallpapers.
189 // should it be possible for user installed (e.g. locateLocal) wallpapers
190 // to override the theme?
191 if (d->hasWallpapers) {
192 // check in the theme first
193 fullPath = d->findInTheme(QLatin1String("wallpapers/") % image, d->themeName);
194
195 if (fullPath.isEmpty()) {
196 fullPath = d->findInTheme(QLatin1String("wallpapers/") % defaultImage, d->themeName);
197 }
198 }
199
200 if (fullPath.isEmpty()) {
201 // we failed to find it in the theme, so look in the standard directories
202 // qCDebug(LOG_PLASMA) << "looking for" << image;
204 }
205
206 if (fullPath.isEmpty()) {
207 // we still failed to find it in the theme, so look for the default in
208 // the standard directories
209 // qCDebug(LOG_PLASMA) << "looking for" << defaultImage;
210 fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("wallpapers/") + defaultImage);
211 }
212
213 return fullPath;
214}
215
216QString Theme::wallpaperPathForSize(int width, int height) const
217{
218 return Plasma::Theme::wallpaperPath(QSize(width, height));
219}
220
222{
223 if (name.contains(QLatin1String("../"))) {
224 // we don't support relative paths
225 return false;
226 }
227
228 QString path = d->findInTheme(name % QLatin1String(".svgz"), d->themeName);
229 if (path.isEmpty()) {
230 path = d->findInTheme(name % QLatin1String(".svg"), d->themeName);
231 }
232 return path.contains(QLatin1String("/" PLASMA_RELATIVE_DATA_INSTALL_DIR "/desktoptheme/") % d->themeName);
233}
234
235KSharedConfigPtr Theme::colorScheme() const
236{
237 return d->colors;
238}
239
240QColor Theme::color(ColorRole role, ColorGroup group) const
241{
242 return d->color(role, group);
243}
244
245void Theme::setUseGlobalSettings(bool useGlobal)
246{
247 if (d->useGlobal == useGlobal) {
248 return;
249 }
250
251 d->useGlobal = useGlobal;
252 d->cfg = KConfigGroup();
253 d->themeName.clear();
254 d->settingsChanged(true);
255}
256
257bool Theme::useGlobalSettings() const
258{
259 return d->useGlobal;
260}
261
263{
264 return d->pluginMetaData;
265}
266
267QFont Theme::defaultFont() const
268{
269 return QGuiApplication::font();
270}
271
272QFont Theme::smallestFont() const
273{
275}
276
277QSizeF Theme::mSize(const QFont &font) const
278{
279 return QFontMetrics(font).boundingRect(QStringLiteral("M")).size();
280}
281
283{
284 return d->backgroundContrastEnabled;
285}
286
288{
289 return d->adaptiveTransparencyEnabled;
290}
291
292qreal Theme::backgroundContrast() const
293{
294 if (qIsNaN(d->backgroundContrast)) {
295 // Make up sensible default values, based on the background color
296 // If we're using a dark background color, darken the background
297 if (qGray(color(Plasma::Theme::BackgroundColor).rgb()) < 127) {
298 return 0.45;
299 // for a light theme lighten up the background
300 } else {
301 return 0.3;
302 }
303 }
304 return d->backgroundContrast;
305}
306
307qreal Theme::backgroundIntensity() const
308{
309 if (qIsNaN(d->backgroundIntensity)) {
310 if (qGray(color(Plasma::Theme::BackgroundColor).rgb()) < 127) {
311 return 0.6;
312 } else {
313 return 1.4;
314 }
315 }
316 return d->backgroundIntensity;
317}
318
319qreal Theme::backgroundSaturation() const
320{
321 if (qIsNaN(d->backgroundSaturation)) {
322 return 1.7;
323 }
324 return d->backgroundSaturation;
325}
326
328{
329 return d->blurBehindEnabled;
330}
331
332}
333
334#include "moc_theme.cpp"
void defaultFontChanged()
Notifier for change of defaultFont property.
void smallestFontChanged()
Notifier for change of smallestFont property.
bool backgroundContrastEnabled() const
This method allows Plasma to enable and disable the background contrast effect for a given theme,...
Definition theme.cpp:282
Q_INVOKABLE QSizeF mSize(const QFont &font=QGuiApplication::font()) const
Returns the size of the letter "M" as rendered on the screen with the given font.
Definition theme.cpp:277
void setThemeName(const QString &themeName)
Sets the current theme being used.
Definition theme.cpp:79
QString imagePath(const QString &name) const
Retrieve the path for an SVG image in the current theme.
Definition theme.cpp:108
bool blurBehindEnabled() const
This method allows Plasma to enable and disable the blurring of what is behind the background for a g...
Definition theme.cpp:327
Theme(QObject *parent=nullptr)
Default constructor.
Definition theme.cpp:32
void themeChanged()
Emitted when the user changes the theme.
void setUseGlobalSettings(bool useGlobal)
Tells the theme whether to follow the global settings or use application specific settings.
Definition theme.cpp:245
QColor color(ColorRole role, ColorGroup group=NormalColorGroup) const
Returns the text color to be used by items resting on the background.
Definition theme.cpp:240
bool adaptiveTransparencyEnabled() const
This method allows Plasma to enable and disable the adaptive transparency option of the panel,...
Definition theme.cpp:287
KPluginMetaData metadata() const
Definition theme.cpp:262
KSharedConfigPtr colorScheme() const
Returns the color scheme configurationthat goes along this theme.
Definition theme.cpp:235
@ BackgroundColor
the default background color
Definition theme.h:60
bool currentThemeHasImage(const QString &name) const
Checks if this theme has an image named in a certain way.
Definition theme.cpp:221
Namespace for everything in libplasma.
QCoreApplication * instance()
QFont systemFont(SystemFont type)
QRect boundingRect(QChar ch) const const
QObject(QObject *parent)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
QSize size() const const
int height() const const
bool isValid() const const
int width() const const
QString locate(StandardLocation type, const QString &fileName, LocateOptions options)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 14 2025 11:57:27 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.