22#include <QApplication>
25#include <QMutableListIterator>
27#include <QStringBuilder>
31#include "private/effectwatcher_p.h"
34#include <kcolorscheme.h>
35#include <kcomponentdata.h>
36#include <kconfiggroup.h>
40#include <kglobalsettings.h>
41#include <kmanagerselection.h>
42#include <kimagecache.h>
43#include <ksharedconfig.h>
44#include <kstandarddirs.h>
45#include <kwindowsystem.h>
48#include "animations/animationscriptengine_p.h"
49#include "libplasma-theme-global.h"
50#include "private/packages_p.h"
57#define DEFAULT_WALLPAPER_THEME "default"
58#define DEFAULT_WALLPAPER_SUFFIX ".png"
72Q_DECLARE_FLAGS(CacheTypes, CacheType)
73Q_DECLARE_OPERATORS_FOR_FLAGS(CacheTypes)
78 ThemePrivate(Theme *theme)
80 colorScheme(QPalette::Active, KColorScheme::Window, KSharedConfigPtr(0)),
81 buttonColorScheme(QPalette::Active, KColorScheme::Button, KSharedConfigPtr(0)),
82 viewColorScheme(QPalette::Active, KColorScheme::View, KSharedConfigPtr(0)),
90 compositingActive(KWindowSystem::self()->compositingActive()),
95 useNativeWidgetStyle(
false)
97 generalFont = QApplication::font();
99 cacheTheme = config.cacheTheme();
101 saveTimer =
new QTimer(q);
102 saveTimer->setSingleShot(
true);
103 saveTimer->setInterval(600);
104 QObject::connect(saveTimer, SIGNAL(timeout()), q, SLOT(scheduledCacheUpdate()));
106 updateNotificationTimer =
new QTimer(q);
107 updateNotificationTimer->setSingleShot(
true);
108 updateNotificationTimer->setInterval(500);
109 QObject::connect(updateNotificationTimer, SIGNAL(timeout()), q, SLOT(notifyOfChanged()));
111 if (QPixmap::defaultDepth() > 8) {
112 QObject::connect(KWindowSystem::self(), SIGNAL(compositingChanged(
bool)), q, SLOT(compositingChanged(
bool)));
115 if (!s_blurEffectWatcher) {
116 s_blurEffectWatcher =
new EffectWatcher(
"_KDE_NET_WM_BLUR_BEHIND_REGION");
119 QObject::connect(s_blurEffectWatcher, SIGNAL(effectChanged(
bool)), q, SLOT(blurBehindChanged(
bool)));
129 KConfigGroup &config()
131 if (!cfg.isValid()) {
132 QString groupName =
"Theme";
135 QString app = KGlobal::mainComponent().componentName();
137 if (!app.isEmpty()) {
138 kDebug() <<
"using theme for app" << app;
139 groupName.append(
"-").append(app);
143 cfg = KConfigGroup(KSharedConfig::openConfig(themeRcFile), groupName);
149 QString findInTheme(
const QString &image,
const QString &theme,
bool cache =
true);
150 void compositingChanged(
bool active);
151 void discardCache(CacheTypes caches);
152 void scheduledCacheUpdate();
153 void scheduleThemeChangeNotification(CacheTypes caches);
154 void notifyOfChanged();
155 void colorsChanged();
156 void blurBehindChanged(
bool blur);
158 void settingsFileChanged(
const QString &);
159 void setThemeName(
const QString &themeName,
bool writeSettings);
160 void onAppExitCleanup();
161 void processWallpaperSettings(KConfigBase *metadata);
162 void processAnimationSettings(
const QString &theme, KConfigBase *metadata);
164 const QString processStyleSheet(
const QString &css);
166 static const char *defaultTheme;
167 static const char *systemColorsTheme;
168 static const char *themeRcFile;
171 static EffectWatcher *s_blurEffectWatcher;
176 QList<QString> fallbackThemes;
177 KSharedConfigPtr colors;
178 KColorScheme colorScheme;
179 KColorScheme buttonColorScheme;
180 KColorScheme viewColorScheme;
183 QString defaultWallpaperTheme;
184 QString defaultWallpaperSuffix;
185 int defaultWallpaperWidth;
186 int defaultWallpaperHeight;
187 KImageCache *pixmapCache;
188 KSharedConfigPtr svgElementsCache;
189 QHash<QString, QSet<QString> > invalidElements;
190 QHash<QString, QPixmap> pixmapsToCache;
191 QHash<QString, QString> keysToCache;
192 QHash<QString, QString> idsToCache;
193 QHash<QString, QString> animationMapping;
194 QHash<styles, QString> cachedStyleSheets;
195 QHash<QString, QString> discoveries;
197 QTimer *updateNotificationTimer;
199 CacheTypes cachesToDiscard;
200 QString themeVersion;
201 QString themeMetadataPath;
204 bool compositingActive : 1;
208 bool hasWallpapers : 1;
210 bool useNativeWidgetStyle :1;
213PackageStructure::Ptr ThemePrivate::packageStructure(0);
214const char *ThemePrivate::defaultTheme =
"default";
216const char *ThemePrivate::themeRcFile =
"plasmarc";
219const char *ThemePrivate::systemColorsTheme =
"internal-system-colors";
221EffectWatcher *ThemePrivate::s_blurEffectWatcher = 0;
224bool ThemePrivate::useCache()
226 bool cachesTooOld =
false;
228 if (cacheTheme && !pixmapCache) {
229 const bool isRegularTheme = themeName != systemColorsTheme;
230 QString cacheFile =
"plasma_theme_" + themeName;
233 themeVersion.clear();
235 if (!themeMetadataPath.isEmpty()) {
236 KDirWatch::self()->removeFile(themeMetadataPath);
238 themeMetadataPath = KStandardDirs::locate(
"data",
"desktoptheme/" + themeName +
"/metadata.desktop");
240 if (isRegularTheme) {
241 const QString cacheFileBase = cacheFile +
"*.kcache";
246 QString currentCacheFileName;
247 if (!themeMetadataPath.isEmpty()) {
249 const KPluginInfo pluginInfo(themeMetadataPath);
250 themeVersion = pluginInfo.version();
251 if (!themeVersion.isEmpty()) {
252 cacheFile +=
"_v" + themeVersion;
253 currentCacheFileName = cacheFile +
".kcache";
257 KDirWatch::self()->addFile(themeMetadataPath);
258 QObject::connect(KDirWatch::self(), SIGNAL(created(QString)),
259 q, SLOT(settingsFileChanged(QString)),
260 Qt::UniqueConnection);
261 QObject::connect(KDirWatch::self(), SIGNAL(dirty(QString)),
262 q, SLOT(settingsFileChanged(QString)),
263 Qt::UniqueConnection);
267 foreach (
const QString &file, KGlobal::dirs()->findAllResources(
"cache", cacheFileBase)) {
268 if (currentCacheFileName.isEmpty() ||
269 !file.endsWith(currentCacheFileName)) {
277 if (isRegularTheme && !themeMetadataPath.isEmpty()) {
286 const QString cacheFilePath = KStandardDirs::locateLocal(
"cache", cacheFile);
287 if (!cacheFilePath.isEmpty()) {
288 const QFileInfo cacheFileInfo(cacheFilePath);
289 const QFileInfo metadataFileInfo(themeMetadataPath);
290 cachesTooOld = cacheFileInfo.lastModified().toTime_t() > metadataFileInfo.lastModified().toTime_t();
295 pixmapCache =
new KImageCache(cacheFile, config.themeCacheKb() * 1024);
302 if (cacheTheme && !svgElementsCache) {
303 const QString svgElementsFileNameBase =
"plasma-svgelements-" + themeName;
304 QString svgElementsFileName = svgElementsFileNameBase;
305 if (!themeVersion.isEmpty()) {
306 svgElementsFileName +=
"_v" + themeVersion;
310 foreach (
const QString &file, KGlobal::dirs()->findAllResources(
"cache", svgElementsFileNameBase +
"*")) {
311 if (cachesTooOld || !file.endsWith(svgElementsFileName)) {
316 const QString svgElementsFile = KStandardDirs::locateLocal(
"cache", svgElementsFileName);
317 svgElementsCache = KSharedConfig::openConfig(svgElementsFile);
323void ThemePrivate::onAppExitCleanup()
325 pixmapsToCache.clear();
331QString ThemePrivate::findInTheme(
const QString &image,
const QString &theme,
bool cache)
333 if (cache && discoveries.contains(image)) {
334 return discoveries[image];
340 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/locolor/") % image;
341 search = KStandardDirs::locate(
"data", search);
342 }
else if (!compositingActive) {
343 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/opaque/") % image;
344 search = KStandardDirs::locate(
"data", search);
346 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/translucent/") % image;
347 search = KStandardDirs::locate(
"data", search);
351 if (search.isEmpty()) {
352 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Char(
'/') % image;
353 search = KStandardDirs::locate(
"data", search);
356 if (cache && !search.isEmpty()) {
357 discoveries.insert(image, search);
363void ThemePrivate::compositingChanged(
bool active)
366 if (compositingActive != active) {
367 compositingActive = active;
374void ThemePrivate::discardCache(CacheTypes caches)
377 pixmapsToCache.clear();
380 pixmapCache->clear();
388 cachedStyleSheets.clear();
392 invalidElements.clear();
393 svgElementsCache = 0;
397void ThemePrivate::scheduledCacheUpdate()
400 QHashIterator<QString, QPixmap> it(pixmapsToCache);
401 while (it.hasNext()) {
403 pixmapCache->insertPixmap(idsToCache[it.key()], it.value());
407 pixmapsToCache.clear();
412void ThemePrivate::colorsChanged()
414 colorScheme = KColorScheme(QPalette::Active, KColorScheme::Window, colors);
415 buttonColorScheme = KColorScheme(QPalette::Active, KColorScheme::Button, colors);
416 viewColorScheme = KColorScheme(QPalette::Active, KColorScheme::View, colors);
420void ThemePrivate::blurBehindChanged(
bool blur)
422 if (blurActive != blur) {
428void ThemePrivate::scheduleThemeChangeNotification(CacheTypes caches)
430 cachesToDiscard |= caches;
431 updateNotificationTimer->start();
434void ThemePrivate::notifyOfChanged()
437 discardCache(cachesToDiscard);
442const QString ThemePrivate::processStyleSheet(
const QString &css)
447 if (stylesheet.isEmpty()) {
448 stylesheet = QString(
"\n\
450 color: %textcolor;\n\
451 font-size: %fontsize;\n\
452 font-family: %fontfamily;\n\
454 a:active { color: %activatedlink; }\n\
455 a:link { color: %link; }\n\
456 a:visited { color: %visitedlink; }\n\
457 a:hover { color: %hoveredlink; text-decoration: none; }\n\
459 stylesheet = processStyleSheet(stylesheet);
464 }
else if (css ==
"SVG") {
465 stylesheet = cachedStyleSheets.value(
SVGSTYLE);
466 if (stylesheet.isEmpty()) {
467 QString skel =
".ColorScheme-%1{color:%2;}";
469 stylesheet += skel.arg(
"Text",
"%textcolor");
470 stylesheet += skel.arg(
"Background",
"%backgroundcolor");
472 stylesheet += skel.arg(
"ButtonText",
"%buttontextcolor");
473 stylesheet += skel.arg(
"ButtonBackground",
"%buttonbackgroundcolor");
474 stylesheet += skel.arg(
"ButtonHover",
"%buttonhovercolor");
475 stylesheet += skel.arg(
"ButtonFocus",
"%buttonfocuscolor");
477 stylesheet += skel.arg(
"ViewText",
"%viewtextcolor");
478 stylesheet += skel.arg(
"ViewBackground",
"%viewbackgroundcolor");
479 stylesheet += skel.arg(
"ViewHover",
"%viewhovercolor");
480 stylesheet += skel.arg(
"ViewFocus",
"%viewfocuscolor");
482 stylesheet = processStyleSheet(stylesheet);
483 cachedStyleSheets.insert(
SVGSTYLE, stylesheet);
491 QHash<QString, QString> elements;
510 elements[
"%fontsize"] = QString(
"%1pt").arg(font.pointSize());
511 elements[
"%fontfamily"] = font.family().split(
'[').first();
512 elements[
"%smallfontsize"] = QString(
"%1pt").arg(KGlobalSettings::smallestReadableFont().pointSize());
514 QHash<QString, QString>::const_iterator it = elements.constBegin();
515 QHash<QString, QString>::const_iterator itEnd = elements.constEnd();
516 for ( ; it != itEnd; ++it) {
517 stylesheet.replace(it.key(), it.value());
527 self.d->isDefault =
true;
530 KDirWatch::self()->addFile(KStandardDirs::locateLocal(
"config", ThemePrivate::themeRcFile));
531 QObject::connect(KDirWatch::self(), SIGNAL(created(QString)),
532 &self, SLOT(settingsFileChanged(QString)),
533 Qt::UniqueConnection);
534 QObject::connect(KDirWatch::self(), SIGNAL(dirty(QString)),
535 &self, SLOT(settingsFileChanged(QString)),
536 Qt::UniqueConnection);
542K_GLOBAL_STATIC(ThemeSingleton, privateThemeSelf)
546 return &privateThemeSelf->self;
551 d(new ThemePrivate(this))
554 if (QCoreApplication::instance()) {
555 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()),
556 this, SLOT(onAppExitCleanup()));
560Theme::Theme(
const QString &themeName,
QObject *parent)
562 d(new ThemePrivate(this))
565 bool useCache = d->cacheTheme;
566 d->cacheTheme =
false;
568 d->cacheTheme = useCache;
569 if (QCoreApplication::instance()) {
570 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()),
571 this, SLOT(onAppExitCleanup()));
577 if (d->svgElementsCache) {
578 QHashIterator<QString, QSet<QString> > it(d->invalidElements);
579 while (it.hasNext()) {
581 KConfigGroup imageGroup(d->svgElementsCache, it.key());
582 imageGroup.writeEntry(
"invalidElements", it.value().toList());
586 d->onAppExitCleanup();
592 if (!ThemePrivate::packageStructure) {
593 ThemePrivate::packageStructure =
new ThemePackage();
596 return ThemePrivate::packageStructure;
599KPluginInfo::List Theme::listThemeInfo()
601 const QStringList themes = KGlobal::dirs()->findAllResources(
"data",
"desktoptheme/*/metadata.desktop",
602 KStandardDirs::NoDuplicates);
603 return KPluginInfo::fromFiles(themes);
606void ThemePrivate::settingsFileChanged(
const QString &file)
608 if (file == themeMetadataPath) {
609 const KPluginInfo pluginInfo(themeMetadataPath);
610 if (themeVersion != pluginInfo.version()) {
613 }
else if (file.endsWith(themeRcFile)) {
614 config().config()->reparseConfiguration();
619void Theme::settingsChanged()
621 KConfigGroup cg = d->config();
622 d->setThemeName(cg.readEntry(
"name", ThemePrivate::defaultTheme),
false);
623 cg = KConfigGroup(cg.config(),
"PlasmaToolTips");
624 d->toolTipDelay = cg.readEntry(
"Delay", 700);
627void Theme::setThemeName(
const QString &themeName)
632void ThemePrivate::processWallpaperSettings(KConfigBase *metadata)
639 if (metadata->hasGroup(
"Wallpaper")) {
642 cg = KConfigGroup(metadata,
"Wallpaper");
655void ThemePrivate::processAnimationSettings(
const QString &theme, KConfigBase *metadata)
657 KConfigGroup cg(metadata,
"Animations");
658 const QString animDir = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/animations/");
659 foreach (
const QString &path, cg.keyList()) {
660 const QStringList anims = cg.readEntry(path, QStringList());
661 foreach (
const QString &anim, anims) {
662 if (!animationMapping.contains(anim)) {
663 kDebug() <<
"Registering animation. animDir: " << animDir
664 <<
"\tanim: " << anim
665 <<
"\tpath: " << path <<
"\t*******\n\n\n";
668 animationMapping.insert(anim, animDir % path);
670 kDebug() <<
"************Animation already registered!\n\n\n";
677void ThemePrivate::setThemeName(
const QString &tempThemeName,
bool writeSettings)
680 QString theme = tempThemeName;
681 if (theme.isEmpty() || theme == themeName) {
683 if (themeName.isEmpty()) {
684 theme = ThemePrivate::defaultTheme;
692 bool realTheme = theme != systemColorsTheme;
694 QString themePath = KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Char(
'/'));
695 if (themePath.isEmpty() && themeName.isEmpty()) {
696 themePath = KStandardDirs::locate(
"data",
"desktoptheme/default/");
698 if (themePath.isEmpty()) {
702 theme = ThemePrivate::defaultTheme;
707 if (themeName == theme) {
714 const QString colorsFile = realTheme ? KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/colors"))
721 const QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/metadata.desktop")));
722 KConfig metadata(metadataPath);
724 processWallpaperSettings(&metadata);
727 animationMapping.clear();
728 processAnimationSettings(themeName, &metadata);
730 KConfigGroup cg(&metadata,
"Settings");
731 useNativeWidgetStyle = cg.readEntry(
"UseNativeWidgetStyle",
false);
732 QString fallback = cg.readEntry(
"FallbackTheme", QString());
734 fallbackThemes.clear();
735 while (!fallback.isEmpty() && !fallbackThemes.contains(fallback)) {
736 fallbackThemes.append(fallback);
738 QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/metadata.desktop")));
739 KConfig metadata(metadataPath);
740 KConfigGroup cg(&metadata,
"Settings");
741 fallback = cg.readEntry(
"FallbackTheme", QString());
744 if (!fallbackThemes.contains(
"oxygen")) {
745 fallbackThemes.append(
"oxygen");
748 if (!fallbackThemes.contains(ThemePrivate::defaultTheme)) {
749 fallbackThemes.append(ThemePrivate::defaultTheme);
752 foreach (
const QString &theme, fallbackThemes) {
753 QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/metadata.desktop")));
754 KConfig metadata(metadataPath);
755 processAnimationSettings(theme, &metadata);
756 processWallpaperSettings(&metadata);
760 if (colorsFile.isEmpty()) {
762 QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
763 q, SLOT(colorsChanged()), Qt::UniqueConnection);
765 QObject::disconnect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
766 q, SLOT(colorsChanged()));
767 colors = KSharedConfig::openConfig(colorsFile);
770 colorScheme = KColorScheme(QPalette::Active, KColorScheme::Window, colors);
771 buttonColorScheme = KColorScheme(QPalette::Active, KColorScheme::Button, colors);
772 viewColorScheme = KColorScheme(QPalette::Active, KColorScheme::View, colors);
773 hasWallpapers = KStandardDirs::exists(KStandardDirs::locateLocal(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/wallpapers/")));
775 if (realTheme && isDefault && writeSettings) {
777 KConfigGroup &cg = config();
778 if (ThemePrivate::defaultTheme == themeName) {
779 cg.deleteEntry(
"name");
781 cg.writeEntry(
"name", themeName);
789QString Theme::themeName()
const
794QString Theme::imagePath(
const QString &name)
const
797 if (name.contains(
"../") || name.isEmpty()) {
803 const QString svgzName = name % QLatin1Literal(
".svgz");
804 QString path = d->findInTheme(svgzName, d->themeName);
806 if (path.isEmpty()) {
808 const QString svgName = name % QLatin1Literal(
".svg");
809 path = d->findInTheme(svgName, d->themeName);
812 for (
int i = 0; path.isEmpty() && i < d->fallbackThemes.count(); ++i) {
813 if (d->themeName == d->fallbackThemes[i]) {
818 path = d->findInTheme(svgzName, d->fallbackThemes[i]);
820 if (path.isEmpty()) {
822 path = d->findInTheme(svgName, d->fallbackThemes[i]);
836QString Theme::styleSheet(
const QString &css)
const
838 return d->processStyleSheet(css);
841QString Theme::animationPath(
const QString &name)
const
843 const QString path = d->animationMapping.value(name);
844 if (path.isEmpty()) {
849 return KStandardDirs::locate(
"data", path);
852QString Theme::wallpaperPath(
const QSize &size)
const
855 QString image = d->defaultWallpaperTheme;
857 image.append(
"/contents/images/%1x%2").append(d->defaultWallpaperSuffix);
858 QString defaultImage = image.arg(d->defaultWallpaperWidth).arg(d->defaultWallpaperHeight);
860 if (size.isValid()) {
865 image = image.arg(size.width()).arg(size.height());
867 image = defaultImage;
873 if (d->hasWallpapers) {
875 fullPath = d->findInTheme(QLatin1Literal(
"wallpapers/") % image, d->themeName);
877 if (fullPath.isEmpty()) {
878 fullPath = d->findInTheme(QLatin1Literal(
"wallpapers/") % defaultImage, d->themeName);
882 if (fullPath.isEmpty()) {
885 fullPath = KStandardDirs::locate(
"wallpaper", image);
888 if (fullPath.isEmpty()) {
892 fullPath = KStandardDirs::locate(
"wallpaper", defaultImage);
894 if (fullPath.isEmpty()) {
895 kDebug() <<
"exhausted every effort to find a wallpaper.";
902bool Theme::currentThemeHasImage(
const QString &name)
const
904 if (name.contains(
"../")) {
909 return !(d->findInTheme(name % QLatin1Literal(
".svgz"), d->themeName,
false).isEmpty()) ||
910 !(d->findInTheme(name % QLatin1Literal(
".svg"), d->themeName,
false).isEmpty());
913KSharedConfigPtr Theme::colorScheme()
const
922 return d->colorScheme.foreground(KColorScheme::NormalText).color();
925 return d->colorScheme.decoration(KColorScheme::HoverColor).color();
928 return d->colorScheme.background(KColorScheme::NormalBackground).color();
931 return d->buttonColorScheme.foreground(KColorScheme::NormalText).color();
934 return d->buttonColorScheme.background(KColorScheme::NormalBackground).color();
937 return d->buttonColorScheme.decoration(KColorScheme::HoverColor).color();
940 return d->buttonColorScheme.decoration(KColorScheme::FocusColor).color();
943 return d->viewColorScheme.foreground(KColorScheme::NormalText).color();
946 return d->viewColorScheme.background(KColorScheme::NormalBackground).color();
949 return d->viewColorScheme.decoration(KColorScheme::HoverColor).color();
952 return d->viewColorScheme.decoration(KColorScheme::FocusColor).color();
955 return d->viewColorScheme.foreground(KColorScheme::LinkText).color();
958 return d->viewColorScheme.foreground(KColorScheme::VisitedText).color();
964void Theme::setFont(
const QFont &font,
FontRole role)
967 d->generalFont =
font;
974 KConfigGroup cg(KGlobal::config(),
"General");
975 return cg.readEntry(
"desktopFont", d->generalFont);
981 return d->generalFont;
985 return KGlobalSettings::smallestReadableFont();
989 return d->generalFont;
992QFontMetrics Theme::fontMetrics()
const
995 return QFontMetrics(d->generalFont);
998bool Theme::windowTranslucencyEnabled()
const
1000 return d->compositingActive;
1003void Theme::setUseGlobalSettings(
bool useGlobal)
1005 if (d->useGlobal == useGlobal) {
1009 d->useGlobal = useGlobal;
1010 d->cfg = KConfigGroup();
1011 d->themeName.clear();
1015bool Theme::useGlobalSettings()
const
1017 return d->useGlobal;
1020bool Theme::useNativeWidgetStyle()
const
1022 return d->useNativeWidgetStyle;
1025bool Theme::findInCache(
const QString &key, QPixmap &pix)
1027 if (d->useCache()) {
1028 const QString
id = d->keysToCache.value(key);
1029 if (d->pixmapsToCache.contains(
id)) {
1030 pix = d->pixmapsToCache.value(
id);
1031 return !pix.isNull();
1035 if (d->pixmapCache->findPixmap(key, &temp) && !temp.isNull()) {
1045bool Theme::findInCache(
const QString &key, QPixmap &pix,
unsigned int lastModified)
1047 if (d->useCache() && lastModified > uint(d->pixmapCache->lastModifiedTime())) {
1054void Theme::insertIntoCache(
const QString& key,
const QPixmap& pix)
1056 if (d->useCache()) {
1057 d->pixmapCache->insertPixmap(key, pix);
1061void Theme::insertIntoCache(
const QString& key,
const QPixmap& pix,
const QString&
id)
1063 if (d->useCache()) {
1064 d->pixmapsToCache.insert(
id, pix);
1066 if (d->idsToCache.contains(
id)) {
1067 d->keysToCache.remove(d->idsToCache[
id]);
1070 d->keysToCache.insert(key,
id);
1071 d->idsToCache.insert(
id, key);
1072 d->saveTimer->start();
1076bool Theme::findInRectsCache(
const QString &image,
const QString &element, QRectF &rect)
const
1078 if (!d->useCache()) {
1082 KConfigGroup imageGroup(d->svgElementsCache, image);
1083 rect = imageGroup.readEntry(element % QLatin1Literal(
"Size"), QRectF());
1085 if (rect.isValid()) {
1091 if (element.indexOf(
'_') <= 0) {
1095 bool invalid =
false;
1097 QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
1098 if (it == d->invalidElements.end()) {
1099 QSet<QString> elements = imageGroup.readEntry(
"invalidElements", QStringList()).toSet();
1100 d->invalidElements.insert(image, elements);
1101 invalid = elements.contains(element);
1103 invalid = it.value().contains(element);
1109QStringList Theme::listCachedRectKeys(
const QString &image)
const
1111 if (!d->useCache()) {
1112 return QStringList();
1115 KConfigGroup imageGroup(d->svgElementsCache, image);
1116 QStringList keys = imageGroup.keyList();
1118 QMutableListIterator<QString> i(keys);
1119 while (i.hasNext()) {
1120 QString key = i.next();
1121 if (key.endsWith(
"Size")) {
1123 key.resize(key.size() - 4);
1132void Theme::insertIntoRectsCache(
const QString& image,
const QString &element,
const QRectF &rect)
1134 if (!d->useCache()) {
1138 if (rect.isValid()) {
1139 KConfigGroup imageGroup(d->svgElementsCache, image);
1140 imageGroup.writeEntry(element % QLatin1Literal(
"Size"), rect);
1142 QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
1143 if (it == d->invalidElements.end()) {
1144 d->invalidElements[image].insert(element);
1145 }
else if (!it.value().contains(element)) {
1146 if (it.value().count() > 1000) {
1147 it.value().erase(it.value().begin());
1150 it.value().insert(element);
1155void Theme::invalidateRectsCache(
const QString& image)
1157 if (d->useCache()) {
1158 KConfigGroup imageGroup(d->svgElementsCache, image);
1159 imageGroup.deleteGroup();
1162 d->invalidElements.remove(image);
1165void Theme::releaseRectsCache(
const QString &image)
1167 QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
1168 if (it != d->invalidElements.end()) {
1169 if (d->useCache()) {
1170 KConfigGroup imageGroup(d->svgElementsCache, it.key());
1171 imageGroup.writeEntry(
"invalidElements", it.value().toList());
1174 d->invalidElements.erase(it);
1178void Theme::setCacheLimit(
int kbytes)
1181 if (d->useCache()) {
1188KUrl Theme::homepage()
const
1190 const QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % d->themeName % QLatin1Literal(
"/metadata.desktop")));
1191 KConfig metadata(metadataPath);
1192 KConfigGroup brandConfig(&metadata,
"Branding");
1193 return brandConfig.readEntry(
"homepage", KUrl(
"http://www.kde.org"));
1196int Theme::toolTipDelay()
const
1198 return d->toolTipDelay;
KSharedPtr< PackageStructure > Ptr
Interface to the Plasma theme.
Q_INVOKABLE QColor color(ColorRole role) const
Returns the text color to be used by items resting on the background.
void setThemeName(const QString &themeName)
Sets the current theme being used.
void settingsChanged()
Notifies the Theme object that the theme settings have changed and should be read from the config fil...
void themeChanged()
Emitted when the user changes the theme.
bool findInCache(const QString &key, QPixmap &pix)
Tries to load pixmap with the specified key from cache.
Q_INVOKABLE QFont font(FontRole role) const
Returns the font to be used by themed items.
@ DefaultFont
The standard text font.
@ DesktopFont
The standard text font.
@ SmallestFont
The smallest readable font.
@ ViewBackgroundColor
text color for views
@ ButtonHoverColor
color visited clickable links
@ ButtonFocusColor
color for hover effect on buttons
@ VisitedLinkColor
color for clickable links
@ HighlightColor
the text higlight color to be used by items resting on the background
@ LinkColor
background color for buttons
@ ButtonBackgroundColor
text color for buttons
@ ViewHoverColor
background color for views
@ BackgroundColor
the default background color
@ ViewFocusColor
color for hover effect on view
@ TextColor
the text color to be used by items resting on the background
@ ViewTextColor
color for focus effect on buttons
bool isEffectAvailable(Effect effect)
Namespace for everything in libplasma.
static const int DEFAULT_WALLPAPER_WIDTH
static const int DEFAULT_WALLPAPER_HEIGHT
#define DEFAULT_WALLPAPER_THEME
#define DEFAULT_WALLPAPER_SUFFIX