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

KDE's Doxygen guidelines are available online.