2008-11-04 00:08:39 +01:00
|
|
|
/*
|
2020-08-13 21:08:54 +02:00
|
|
|
SPDX-FileCopyrightText: 2006-2007 Aaron Seigo <aseigo@kde.org>
|
|
|
|
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later
|
|
|
|
*/
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
#include "theme.h"
|
2013-03-11 19:24:07 +01:00
|
|
|
#include "private/theme_p.h"
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
#include <QFile>
|
2013-03-13 10:47:10 +01:00
|
|
|
#include <QFont>
|
2014-01-12 19:33:56 +01:00
|
|
|
#include <QFontDatabase>
|
2008-11-09 21:41:27 +01:00
|
|
|
#include <QFileInfo>
|
2010-10-30 00:14:18 +02:00
|
|
|
#include <QMutableListIterator>
|
2009-07-20 22:30:07 +02:00
|
|
|
#include <QPair>
|
2010-09-22 09:46:09 +02:00
|
|
|
#include <QStringBuilder>
|
|
|
|
#include <QTimer>
|
2015-03-12 15:15:45 +01:00
|
|
|
#include <QThread>
|
2017-11-07 21:16:08 +01:00
|
|
|
#include <QFontMetrics>
|
2012-08-03 12:19:50 +02:00
|
|
|
|
2012-08-25 03:00:36 +02:00
|
|
|
#include "config-plasma.h"
|
2012-08-03 12:19:50 +02:00
|
|
|
|
2020-07-08 07:44:43 +02:00
|
|
|
#include <KColorScheme>
|
|
|
|
#include <KConfigGroup>
|
2013-07-29 19:05:59 +02:00
|
|
|
#include <QDebug>
|
2020-07-08 07:44:43 +02:00
|
|
|
#include <KDirWatch>
|
|
|
|
#include <KImageCache>
|
|
|
|
#include <KSharedConfig>
|
|
|
|
#include <KWindowEffects>
|
|
|
|
#include <KWindowSystem>
|
|
|
|
#include <QStandardPaths>
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2015-12-15 22:56:40 +01:00
|
|
|
#include "debug_p.h"
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
namespace Plasma
|
|
|
|
{
|
|
|
|
|
|
|
|
Theme::Theme(QObject *parent)
|
2013-03-12 13:03:06 +01:00
|
|
|
: QObject(parent)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2013-03-11 22:26:15 +01:00
|
|
|
if (!ThemePrivate::globalTheme) {
|
|
|
|
ThemePrivate::globalTheme = new ThemePrivate;
|
|
|
|
}
|
2019-06-30 12:48:02 +02:00
|
|
|
ThemePrivate::globalTheme->ref.ref();
|
2013-03-11 22:26:15 +01:00
|
|
|
d = ThemePrivate::globalTheme;
|
|
|
|
|
2014-05-26 19:03:46 +02:00
|
|
|
d->settingsChanged(false);
|
2010-03-04 23:28:39 +01:00
|
|
|
if (QCoreApplication::instance()) {
|
2019-01-18 12:34:06 +01:00
|
|
|
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
|
|
|
|
d, &ThemePrivate::onAppExitCleanup);
|
2010-03-04 23:28:39 +01:00
|
|
|
}
|
2013-03-11 20:20:50 +01:00
|
|
|
connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged);
|
2014-01-12 19:33:56 +01:00
|
|
|
connect(d, &ThemePrivate::defaultFontChanged, this, &Theme::defaultFontChanged);
|
|
|
|
connect(d, &ThemePrivate::smallestFontChanged, this, &Theme::smallestFontChanged);
|
2009-05-18 14:28:19 +02:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-05-18 14:28:19 +02:00
|
|
|
Theme::Theme(const QString &themeName, QObject *parent)
|
2013-03-11 22:26:15 +01:00
|
|
|
: QObject(parent)
|
2009-05-18 14:28:19 +02:00
|
|
|
{
|
2019-06-30 12:48:02 +02:00
|
|
|
auto& priv = ThemePrivate::themes[themeName];
|
|
|
|
if (!priv) {
|
|
|
|
priv = new ThemePrivate;
|
2013-03-11 22:26:15 +01:00
|
|
|
}
|
|
|
|
|
2019-06-30 12:48:02 +02:00
|
|
|
priv->ref.ref();
|
|
|
|
d = priv;
|
2013-03-11 22:26:15 +01:00
|
|
|
|
2018-10-22 20:05:29 +02:00
|
|
|
// turn off caching so we don't accidentally trigger unnecessary disk activity at this point
|
2009-05-18 14:28:19 +02:00
|
|
|
bool useCache = d->cacheTheme;
|
|
|
|
d->cacheTheme = false;
|
2014-05-26 19:03:46 +02:00
|
|
|
d->setThemeName(themeName, false, false);
|
2009-05-18 14:28:19 +02:00
|
|
|
d->cacheTheme = useCache;
|
2014-05-20 18:24:26 +02:00
|
|
|
d->fixedName = true;
|
2010-03-04 23:28:39 +01:00
|
|
|
if (QCoreApplication::instance()) {
|
2019-01-18 12:34:06 +01:00
|
|
|
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
|
|
|
|
d, &ThemePrivate::onAppExitCleanup);
|
2010-03-04 23:28:39 +01:00
|
|
|
}
|
2013-03-11 22:39:15 +01:00
|
|
|
connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Theme::~Theme()
|
|
|
|
{
|
2013-03-11 22:26:15 +01:00
|
|
|
if (d == ThemePrivate::globalTheme) {
|
2019-06-30 12:48:02 +02:00
|
|
|
if (!d->ref.deref()) {
|
2018-07-02 00:16:21 +02:00
|
|
|
disconnect(ThemePrivate::globalTheme, nullptr, this, nullptr);
|
2013-03-11 22:26:15 +01:00
|
|
|
delete ThemePrivate::globalTheme;
|
2018-04-13 13:58:44 +02:00
|
|
|
ThemePrivate::globalTheme = nullptr;
|
|
|
|
d = nullptr;
|
2013-03-11 22:26:15 +01:00
|
|
|
}
|
|
|
|
} else {
|
2019-06-30 12:48:02 +02:00
|
|
|
if (!d->ref.deref()) {
|
|
|
|
delete ThemePrivate::themes.take(d->themeName);
|
2013-03-11 22:26:15 +01:00
|
|
|
}
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Theme::setThemeName(const QString &themeName)
|
2009-02-24 21:49:46 +01:00
|
|
|
{
|
2013-03-11 22:26:15 +01:00
|
|
|
if (d->themeName == themeName) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d != ThemePrivate::globalTheme) {
|
2018-07-02 00:16:21 +02:00
|
|
|
disconnect(QCoreApplication::instance(), nullptr, d, nullptr);
|
2019-06-30 12:48:02 +02:00
|
|
|
if (!d->ref.deref()) {
|
|
|
|
delete ThemePrivate::themes.take(d->themeName);
|
2013-03-11 22:26:15 +01:00
|
|
|
}
|
2019-06-30 12:48:02 +02:00
|
|
|
|
|
|
|
auto& priv = ThemePrivate::themes[themeName];
|
|
|
|
if (!priv) {
|
|
|
|
priv = new ThemePrivate;
|
2013-03-12 16:29:04 +01:00
|
|
|
}
|
2019-06-30 12:48:02 +02:00
|
|
|
priv->ref.ref();
|
|
|
|
d = priv;
|
2013-03-12 16:29:04 +01:00
|
|
|
if (QCoreApplication::instance()) {
|
2019-01-18 12:34:06 +01:00
|
|
|
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
|
|
|
|
d, &ThemePrivate::onAppExitCleanup);
|
2013-03-11 22:39:15 +01:00
|
|
|
}
|
2014-01-31 03:39:10 +01:00
|
|
|
connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged);
|
2013-03-11 22:26:15 +01:00
|
|
|
}
|
|
|
|
|
2014-05-26 19:03:46 +02:00
|
|
|
d->setThemeName(themeName, true, true);
|
2009-02-24 21:49:46 +01:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
QString Theme::themeName() const
|
|
|
|
{
|
|
|
|
return d->themeName;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Theme::imagePath(const QString &name) const
|
|
|
|
{
|
|
|
|
// look for a compressed svg file in the theme
|
2015-11-27 21:03:48 +01:00
|
|
|
if (name.contains(QLatin1String("../")) || name.isEmpty()) {
|
2008-11-04 00:08:39 +01:00
|
|
|
// we don't support relative paths
|
2015-12-15 22:56:40 +01:00
|
|
|
//qCDebug(LOG_PLASMA) << "Theme says: bad image path " << name;
|
2008-11-04 00:08:39 +01:00
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2019-08-29 07:23:49 +02:00
|
|
|
const QString svgzName = name % QLatin1String(".svgz");
|
2010-10-04 23:50:42 +02:00
|
|
|
QString path = d->findInTheme(svgzName, d->themeName);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
if (path.isEmpty()) {
|
|
|
|
// try for an uncompressed svg file
|
2019-08-29 07:23:49 +02:00
|
|
|
const QString svgName = name % QLatin1String(".svg");
|
2010-10-04 23:50:42 +02:00
|
|
|
path = d->findInTheme(svgName, d->themeName);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-06-26 12:02:32 +02:00
|
|
|
// search in fallback themes if necessary
|
|
|
|
for (int i = 0; path.isEmpty() && i < d->fallbackThemes.count(); ++i) {
|
|
|
|
if (d->themeName == d->fallbackThemes[i]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// try a compressed svg file in the fallback theme
|
2010-10-07 15:51:31 +02:00
|
|
|
path = d->findInTheme(svgzName, d->fallbackThemes[i]);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
if (path.isEmpty()) {
|
2009-06-26 12:02:32 +02:00
|
|
|
// try an uncompressed svg file in the fallback theme
|
2010-10-04 23:50:42 +02:00
|
|
|
path = d->findInTheme(svgName, d->fallbackThemes[i]);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-28 19:40:29 +02:00
|
|
|
/*
|
2008-11-04 00:08:39 +01:00
|
|
|
if (path.isEmpty()) {
|
2014-04-26 01:45:47 +02:00
|
|
|
#ifndef NDEBUG
|
2015-12-15 22:56:40 +01:00
|
|
|
// qCDebug(LOG_PLASMA) << "Theme says: bad image path " << name;
|
2014-04-26 01:45:47 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2010-04-28 19:40:29 +02:00
|
|
|
*/
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2014-04-27 17:14:22 +02:00
|
|
|
QString Theme::backgroundPath(const QString& image) const
|
|
|
|
{
|
2015-11-27 21:03:48 +01:00
|
|
|
return d->imagePath(themeName(), QStringLiteral("/appbackgrounds/"), image);
|
2014-04-27 17:14:22 +02:00
|
|
|
}
|
|
|
|
|
2010-05-11 10:23:41 +02:00
|
|
|
QString Theme::styleSheet(const QString &css) const
|
|
|
|
{
|
2016-06-01 14:47:56 +02:00
|
|
|
return d->processStyleSheet(css, Svg::Status::Normal);
|
2010-05-11 10:23:41 +02:00
|
|
|
}
|
|
|
|
|
Try to apply the colorscheme of the current theme to QIcons
Summary:
Before icons loaded internally with QIcon::fromTheme were being colored with the
colors from the current global color scheme instead of the ones from the current
Plasma Theme. Leading to visual bugs when the two differ. This happened because
KIconLoader uses the global color scheme by default.
A prominent case is the notification send by the network plasmoid when one
successfully connected to a wireless network. It sets the icon
"network-wireless-on" which is not included in Breeze icons (but is included in
Breeze Plasma Theme). If the current icon theme is indeed Breeze, IconItem
resorts to using QIcon::fromTheme and we end up with a wrong colored
"network-wireless" icon.
BUG: 417780
Test Plan:
{F8125752}
{F8125753}
Reviewers: #plasma, cblack, ngraham, mart
Reviewed By: #plasma, cblack, ngraham, mart
Subscribers: mart, wbauer, cblack, kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D27589
2020-02-24 14:34:23 +01:00
|
|
|
|
|
|
|
QPalette Theme::palette() const
|
|
|
|
{
|
|
|
|
return d->palette;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
QString Theme::wallpaperPath(const QSize &size) const
|
|
|
|
{
|
|
|
|
QString fullPath;
|
2017-12-02 15:12:40 +01:00
|
|
|
QString image = d->defaultWallpaperTheme + QStringLiteral("/contents/images/%1x%2") + d->defaultWallpaperSuffix;
|
2008-11-04 00:08:39 +01:00
|
|
|
QString defaultImage = image.arg(d->defaultWallpaperWidth).arg(d->defaultWallpaperHeight);
|
|
|
|
|
|
|
|
if (size.isValid()) {
|
|
|
|
// try to customize the paper to the size requested
|
|
|
|
//TODO: this should do better than just fallback to the default size.
|
|
|
|
// a "best fit" matching would be far better, so we don't end
|
|
|
|
// up returning a 1920x1200 wallpaper for a 640x480 request ;)
|
|
|
|
image = image.arg(size.width()).arg(size.height());
|
|
|
|
} else {
|
|
|
|
image = defaultImage;
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: the theme's wallpaper overrides regularly installed wallpapers.
|
|
|
|
// should it be possible for user installed (e.g. locateLocal) wallpapers
|
|
|
|
// to override the theme?
|
|
|
|
if (d->hasWallpapers) {
|
|
|
|
// check in the theme first
|
2019-08-29 07:23:49 +02:00
|
|
|
fullPath = d->findInTheme(QLatin1String("wallpapers/") % image, d->themeName);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
if (fullPath.isEmpty()) {
|
2019-08-29 07:23:49 +02:00
|
|
|
fullPath = d->findInTheme(QLatin1String("wallpapers/") % defaultImage, d->themeName);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fullPath.isEmpty()) {
|
|
|
|
// we failed to find it in the theme, so look in the standard directories
|
2015-12-15 22:56:40 +01:00
|
|
|
//qCDebug(LOG_PLASMA) << "looking for" << image;
|
2012-06-12 12:59:34 +02:00
|
|
|
fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("wallpapers/") + image);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fullPath.isEmpty()) {
|
|
|
|
// we still failed to find it in the theme, so look for the default in
|
|
|
|
// the standard directories
|
2015-12-15 22:56:40 +01:00
|
|
|
//qCDebug(LOG_PLASMA) << "looking for" << defaultImage;
|
2012-06-12 12:59:34 +02:00
|
|
|
fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("wallpapers/") + defaultImage);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
if (fullPath.isEmpty()) {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2015-12-15 22:56:40 +01:00
|
|
|
// qCDebug(LOG_PLASMA) << "exhausted every effort to find a wallpaper.";
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullPath;
|
|
|
|
}
|
|
|
|
|
2014-01-13 02:11:37 +01:00
|
|
|
QString Theme::wallpaperPathForSize(int width, int height) const
|
|
|
|
{
|
|
|
|
return Plasma::Theme::wallpaperPath(QSize(width, height));
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
bool Theme::currentThemeHasImage(const QString &name) const
|
|
|
|
{
|
2015-11-27 21:03:48 +01:00
|
|
|
if (name.contains(QLatin1String("../"))) {
|
2008-11-04 00:08:39 +01:00
|
|
|
// we don't support relative paths
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-08-29 07:23:49 +02:00
|
|
|
return !(d->findInTheme(name % QLatin1String(".svgz"), d->themeName, false).isEmpty()) ||
|
|
|
|
!(d->findInTheme(name % QLatin1String(".svg"), d->themeName, false).isEmpty());
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
KSharedConfigPtr Theme::colorScheme() const
|
|
|
|
{
|
|
|
|
return d->colors;
|
|
|
|
}
|
|
|
|
|
2014-06-19 17:38:31 +02:00
|
|
|
QColor Theme::color(ColorRole role, ColorGroup group) const
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2014-06-19 17:38:31 +02:00
|
|
|
return d->color(role, group);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Theme::setUseGlobalSettings(bool useGlobal)
|
|
|
|
{
|
|
|
|
if (d->useGlobal == useGlobal) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->useGlobal = useGlobal;
|
|
|
|
d->cfg = KConfigGroup();
|
|
|
|
d->themeName.clear();
|
2014-05-26 19:03:46 +02:00
|
|
|
d->settingsChanged(true);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Theme::useGlobalSettings() const
|
|
|
|
{
|
|
|
|
return d->useGlobal;
|
|
|
|
}
|
|
|
|
|
2011-05-20 08:23:43 +02:00
|
|
|
bool Theme::findInCache(const QString &key, QPixmap &pix, unsigned int lastModified)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2020-09-22 14:41:26 +02:00
|
|
|
//TODO KF6: Make lastModified non-optional.
|
|
|
|
if (lastModified == 0) {
|
|
|
|
qCWarning(LOG_PLASMA) << "findInCache with a lastModified timestamp of 0 is deprecated";
|
2011-05-20 08:23:43 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-09-22 14:41:26 +02:00
|
|
|
if (!d->useCache()) {
|
|
|
|
return false;
|
|
|
|
}
|
2009-05-30 05:08:33 +02:00
|
|
|
|
2020-09-22 14:41:26 +02:00
|
|
|
if (lastModified > uint(d->pixmapCache->lastModifiedTime().toSecsSinceEpoch())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString id = d->keysToCache.value(key);
|
|
|
|
const auto it = d->pixmapsToCache.constFind(id);
|
|
|
|
if (it != d->pixmapsToCache.constEnd()) {
|
|
|
|
pix = *it;
|
|
|
|
return !pix.isNull();
|
|
|
|
}
|
|
|
|
|
|
|
|
QPixmap temp;
|
|
|
|
if (d->pixmapCache->findPixmap(key, &temp) && !temp.isNull()) {
|
|
|
|
pix = temp;
|
|
|
|
return true;
|
2009-05-30 05:08:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
void Theme::insertIntoCache(const QString &key, const QPixmap &pix)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2008-12-04 21:13:50 +01:00
|
|
|
if (d->useCache()) {
|
2010-05-04 05:59:35 +02:00
|
|
|
d->pixmapCache->insertPixmap(key, pix);
|
2009-07-20 22:30:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
void Theme::insertIntoCache(const QString &key, const QPixmap &pix, const QString &id)
|
2009-07-20 22:30:07 +02:00
|
|
|
{
|
|
|
|
if (d->useCache()) {
|
2019-06-30 12:48:02 +02:00
|
|
|
d->pixmapsToCache[id] = pix;
|
|
|
|
d->keysToCache[key] = id;
|
|
|
|
d->idsToCache[id] = key;
|
2013-12-10 16:06:37 +01:00
|
|
|
|
2014-05-26 20:32:22 +02:00
|
|
|
//always start timer in d->pixmapSaveTimer's thread
|
|
|
|
QMetaObject::invokeMethod(d->pixmapSaveTimer, "start", Qt::QueuedConnection);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Theme::findInRectsCache(const QString &image, const QString &element, QRectF &rect) const
|
|
|
|
{
|
2014-02-04 12:06:09 +01:00
|
|
|
if (!d->useCache()) {
|
2008-11-04 00:08:39 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
KConfigGroup imageGroup(d->svgElementsCache, image);
|
2019-08-29 07:23:49 +02:00
|
|
|
rect = imageGroup.readEntry(element % QLatin1String("Size"), QRectF());
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2008-12-11 00:17:12 +01:00
|
|
|
if (rect.isValid()) {
|
|
|
|
return true;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-07-31 20:47:20 +02:00
|
|
|
//Name starting by _ means the element is empty and we're asked for the size of
|
2009-01-22 20:59:25 +01:00
|
|
|
//the whole image, so the whole image is never invalid
|
2017-12-02 15:12:40 +01:00
|
|
|
if (element.indexOf(QLatin1Char('_')) <= 0) {
|
2009-01-22 20:59:25 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-12-11 00:17:12 +01:00
|
|
|
bool invalid = false;
|
|
|
|
|
|
|
|
QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
|
|
|
|
if (it == d->invalidElements.end()) {
|
2020-06-26 05:59:48 +02:00
|
|
|
const QStringList elementList = imageGroup.readEntry("invalidElements", QStringList());
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
|
|
|
const QSet<QString> elements(elementList.begin(), elementList.end());
|
|
|
|
#else
|
|
|
|
const QSet<QString> elements = elementList.toSet();
|
|
|
|
#endif
|
2008-12-11 00:17:12 +01:00
|
|
|
d->invalidElements.insert(image, elements);
|
|
|
|
invalid = elements.contains(element);
|
|
|
|
} else {
|
|
|
|
invalid = it.value().contains(element);
|
|
|
|
}
|
|
|
|
|
|
|
|
return invalid;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2010-10-30 00:14:18 +02:00
|
|
|
QStringList Theme::listCachedRectKeys(const QString &image) const
|
|
|
|
{
|
2014-02-04 12:06:09 +01:00
|
|
|
if (!d->useCache()) {
|
2011-01-30 22:47:29 +01:00
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
2010-10-30 00:14:18 +02:00
|
|
|
KConfigGroup imageGroup(d->svgElementsCache, image);
|
|
|
|
QStringList keys = imageGroup.keyList();
|
|
|
|
|
|
|
|
QMutableListIterator<QString> i(keys);
|
|
|
|
while (i.hasNext()) {
|
2010-10-30 00:30:10 +02:00
|
|
|
QString key = i.next();
|
2015-11-27 21:03:48 +01:00
|
|
|
if (key.endsWith(QLatin1String("Size"))) {
|
2010-10-30 00:14:18 +02:00
|
|
|
// The actual cache id used from outside doesn't end on "Size".
|
2010-10-30 00:30:10 +02:00
|
|
|
key.resize(key.size() - 4);
|
|
|
|
i.setValue(key);
|
2010-10-30 00:14:18 +02:00
|
|
|
} else {
|
|
|
|
i.remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return keys;
|
|
|
|
}
|
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
void Theme::insertIntoRectsCache(const QString &image, const QString &element, const QRectF &rect)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2014-02-04 12:06:09 +01:00
|
|
|
if (!d->useCache()) {
|
2008-11-04 00:08:39 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rect.isValid()) {
|
2008-12-11 00:17:12 +01:00
|
|
|
KConfigGroup imageGroup(d->svgElementsCache, image);
|
2019-08-29 07:23:49 +02:00
|
|
|
imageGroup.writeEntry(element % QLatin1String("Size"), rect);
|
2008-12-11 00:17:12 +01:00
|
|
|
} else {
|
|
|
|
QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
|
|
|
|
if (it == d->invalidElements.end()) {
|
|
|
|
d->invalidElements[image].insert(element);
|
|
|
|
} else if (!it.value().contains(element)) {
|
|
|
|
if (it.value().count() > 1000) {
|
|
|
|
it.value().erase(it.value().begin());
|
|
|
|
}
|
|
|
|
|
|
|
|
it.value().insert(element);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
2014-05-26 20:32:22 +02:00
|
|
|
|
2015-03-12 15:15:45 +01:00
|
|
|
QMetaObject::invokeMethod(d->rectSaveTimer, "start");
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2014-04-26 01:45:47 +02:00
|
|
|
void Theme::invalidateRectsCache(const QString &image)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2014-02-04 12:06:09 +01:00
|
|
|
if (d->useCache()) {
|
2011-01-30 22:47:29 +01:00
|
|
|
KConfigGroup imageGroup(d->svgElementsCache, image);
|
|
|
|
imageGroup.deleteGroup();
|
|
|
|
}
|
2008-12-11 03:45:45 +01:00
|
|
|
|
2011-01-30 22:47:29 +01:00
|
|
|
d->invalidElements.remove(image);
|
2008-12-11 03:45:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Theme::releaseRectsCache(const QString &image)
|
|
|
|
{
|
|
|
|
QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
|
|
|
|
if (it != d->invalidElements.end()) {
|
2014-02-04 12:06:09 +01:00
|
|
|
if (d->useCache()) {
|
2011-01-30 22:47:29 +01:00
|
|
|
KConfigGroup imageGroup(d->svgElementsCache, it.key());
|
2019-12-19 13:55:07 +01:00
|
|
|
imageGroup.writeEntry("invalidElements", it.value().values());
|
2011-01-30 22:47:29 +01:00
|
|
|
}
|
|
|
|
|
2008-12-11 03:45:45 +01:00
|
|
|
d->invalidElements.erase(it);
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Theme::setCacheLimit(int kbytes)
|
|
|
|
{
|
2013-03-11 14:34:48 +01:00
|
|
|
d->cacheSize = kbytes;
|
|
|
|
delete d->pixmapCache;
|
2018-04-13 13:58:44 +02:00
|
|
|
d->pixmapCache = nullptr;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2013-03-11 18:01:22 +01:00
|
|
|
KPluginInfo Theme::pluginInfo() const
|
2010-12-27 01:46:17 +01:00
|
|
|
{
|
2020-01-12 02:28:31 +01:00
|
|
|
return KPluginInfo(d->pluginMetaData);
|
2010-12-27 01:46:17 +01:00
|
|
|
}
|
|
|
|
|
2014-01-12 19:33:56 +01:00
|
|
|
QFont Theme::defaultFont() const
|
|
|
|
{
|
2014-05-19 16:58:37 +02:00
|
|
|
return QGuiApplication::font();
|
2014-01-12 19:33:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QFont Theme::smallestFont() const
|
|
|
|
{
|
|
|
|
return QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);
|
|
|
|
}
|
|
|
|
|
2014-01-13 01:31:46 +01:00
|
|
|
QSizeF Theme::mSize(const QFont &font) const
|
|
|
|
{
|
2016-02-29 00:08:05 +01:00
|
|
|
return QFontMetrics(font).boundingRect(QStringLiteral("M")).size();
|
2014-01-13 01:31:46 +01:00
|
|
|
}
|
|
|
|
|
2014-02-06 00:56:50 +01:00
|
|
|
bool Theme::backgroundContrastEnabled() const
|
|
|
|
{
|
|
|
|
return d->backgroundContrastEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal Theme::backgroundContrast() const
|
|
|
|
{
|
2019-02-07 16:37:55 +01:00
|
|
|
if (qIsNaN(d->backgroundContrast)) {
|
|
|
|
// Make up sensible default values, based on the background color
|
|
|
|
// If we're using a dark background color, darken the background
|
|
|
|
if (qGray(color(Plasma::Theme::BackgroundColor).rgb()) < 127) {
|
|
|
|
return 0.45;
|
|
|
|
// for a light theme lighten up the background
|
|
|
|
} else {
|
|
|
|
return 0.3;
|
|
|
|
}
|
|
|
|
}
|
2014-02-06 00:56:50 +01:00
|
|
|
return d->backgroundContrast;
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal Theme::backgroundIntensity() const
|
|
|
|
{
|
2019-02-07 16:37:55 +01:00
|
|
|
if (qIsNaN(d->backgroundIntensity)) {
|
|
|
|
if (qGray(color(Plasma::Theme::BackgroundColor).rgb()) < 127) {
|
|
|
|
return 0.45;
|
|
|
|
} else {
|
|
|
|
return 1.9;
|
|
|
|
}
|
|
|
|
}
|
2014-02-06 00:56:50 +01:00
|
|
|
return d->backgroundIntensity;
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal Theme::backgroundSaturation() const
|
|
|
|
{
|
2019-02-07 16:37:55 +01:00
|
|
|
if (qIsNaN(d->backgroundSaturation)) {
|
|
|
|
return 1.7;
|
|
|
|
}
|
2014-02-06 00:56:50 +01:00
|
|
|
return d->backgroundSaturation;
|
|
|
|
}
|
|
|
|
|
2019-03-20 11:01:27 +01:00
|
|
|
bool Theme::blurBehindEnabled() const
|
|
|
|
{
|
|
|
|
return d->blurBehindEnabled;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2012-02-08 23:33:03 +01:00
|
|
|
#include "moc_theme.cpp"
|