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

KDE's Doxygen guidelines are available online.