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>
38 #include <kdirwatch.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"
50 #include "private/packages_p.h"
57 #define DEFAULT_WALLPAPER_THEME "default"
58 #define DEFAULT_WALLPAPER_SUFFIX ".png"
73 Q_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();
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;
214 const char *ThemePrivate::defaultTheme =
"default";
216 const char *ThemePrivate::themeRcFile =
"plasmarc";
219 const char *ThemePrivate::systemColorsTheme =
"internal-system-colors";
221 EffectWatcher *ThemePrivate::s_blurEffectWatcher = 0;
224 bool 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);
323 void ThemePrivate::onAppExitCleanup()
325 pixmapsToCache.clear();
331 QString 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);
363 void ThemePrivate::compositingChanged(
bool active)
366 if (compositingActive != active) {
367 compositingActive = active;
374 void ThemePrivate::discardCache(CacheTypes caches)
377 pixmapsToCache.clear();
380 pixmapCache->clear();
388 cachedStyleSheets.clear();
392 invalidElements.clear();
393 svgElementsCache = 0;
397 void ThemePrivate::scheduledCacheUpdate()
400 QHashIterator<QString, QPixmap> it(pixmapsToCache);
401 while (it.hasNext()) {
403 pixmapCache->insertPixmap(idsToCache[it.key()], it.value());
407 pixmapsToCache.clear();
412 void 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);
417 scheduleThemeChangeNotification(PixmapCache);
420 void ThemePrivate::blurBehindChanged(
bool blur)
422 if (blurActive != blur) {
424 scheduleThemeChangeNotification(PixmapCache | SvgElementsCache);
428 void ThemePrivate::scheduleThemeChangeNotification(CacheTypes caches)
430 cachesToDiscard |= caches;
431 updateNotificationTimer->start();
434 void ThemePrivate::notifyOfChanged()
437 discardCache(cachesToDiscard);
439 emit q->themeChanged();
442 const 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);
542 K_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()));
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();
601 const QStringList themes = KGlobal::dirs()->findAllResources(
"data",
"desktoptheme/*/metadata.desktop",
602 KStandardDirs::NoDuplicates);
603 return KPluginInfo::fromFiles(themes);
606 void ThemePrivate::settingsFileChanged(
const QString &file)
608 if (file == themeMetadataPath) {
609 const KPluginInfo pluginInfo(themeMetadataPath);
610 if (themeVersion != pluginInfo.version()) {
611 scheduleThemeChangeNotification(SvgElementsCache);
613 }
else if (file.endsWith(themeRcFile)) {
614 config().config()->reparseConfiguration();
615 q->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);
629 d->setThemeName(themeName,
true);
632 void ThemePrivate::processWallpaperSettings(KConfigBase *metadata)
639 if (metadata->hasGroup(
"Wallpaper")) {
642 cg = KConfigGroup(metadata,
"Wallpaper");
655 void 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";
677 void 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);
786 scheduleThemeChangeNotification(SvgElementsCache);
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]);
838 return d->processStyleSheet(css);
843 const QString path = d->animationMapping.value(name);
844 if (path.isEmpty()) {
849 return KStandardDirs::locate(
"data", path);
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.";
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());
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();
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;
995 return QFontMetrics(d->generalFont);
1000 return d->compositingActive;
1005 if (d->useGlobal == useGlobal) {
1009 d->useGlobal = useGlobal;
1010 d->cfg = KConfigGroup();
1011 d->themeName.clear();
1017 return d->useGlobal;
1022 return d->useNativeWidgetStyle;
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()) {
1047 if (d->useCache() && lastModified > uint(d->pixmapCache->lastModifiedTime())) {
1056 if (d->useCache()) {
1057 d->pixmapCache->insertPixmap(key, pix);
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();
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);
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);
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);
1157 if (d->useCache()) {
1158 KConfigGroup imageGroup(d->svgElementsCache, image);
1159 imageGroup.deleteGroup();
1162 d->invalidElements.remove(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);
1181 if (d->useCache()) {
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"));
1198 return d->toolTipDelay;
1203 #include <theme.moc>
Q_INVOKABLE QString imagePath(const QString &name) const
Retrieve the path for an SVG image in the current theme.
void insertIntoRectsCache(const QString &image, const QString &element, const QRectF &rect)
Inserts a rectangle of a sub element of an image into a disk cache.
the text higlight color to be used by items resting on the background
bool findInCache(const QString &key, QPixmap &pix)
Tries to load pixmap with the specified key from cache.
void setThemeName(const QString &themeName)
Sets the current theme being used.
bool useNativeWidgetStyle() const
void settingsChanged()
Notifies the Theme object that the theme settings have changed and should be read from the config fil...
Q_INVOKABLE QString animationPath(const QString &name) const
Retrieves the path for the script file that contains a given Javascript animation.
Q_INVOKABLE KSharedConfigPtr colorScheme() const
Returns the color scheme configurationthat goes along this theme.
Q_INVOKABLE QFont font(FontRole role) const
Returns the font to be used by themed items.
the text color to be used by items resting on the background
color for focus effect on buttons
void setCacheLimit(int kbytes)
Sets the maximum size of the cache (in kilobytes).
static PackageStructure::Ptr packageStructure()
Theme(QObject *parent=0)
Default constructor.
static KPluginInfo::List listThemeInfo()
Q_INVOKABLE void setFont(const QFont &font, FontRole role=DefaultFont)
Sets the default font to be used with themed items.
bool cacheTheme() const
Get Whether or not to create an on-disk cache for the theme.
color for clickable links
static const int DEFAULT_WALLPAPER_WIDTH
KSharedPtr< PackageStructure > Ptr
background color for views
Q_INVOKABLE bool currentThemeHasImage(const QString &name) const
Checks if this theme has an image named in a certain way.
void releaseRectsCache(const QString &image)
Frees up memory used by cached information for a given image without removing the permenant record of...
int themeCacheKb() const
Get The maximum size of the on-disk Theme cache in kilobytes.
static const int DEFAULT_WALLPAPER_HEIGHT
Q_INVOKABLE bool windowTranslucencyEnabled() const
bool isEffectAvailable(Effect effect)
Q_INVOKABLE QString styleSheet(const QString &css=QString()) const
Provides a Plasma::Theme-themed stylesheet for hybrid (web / native Plasma) widgets.
The smallest readable font.
void setUseGlobalSettings(bool useGlobal)
Tells the theme whether to follow the global settings or use application specific settings...
Q_INVOKABLE QString wallpaperPath(const QSize &size=QSize()) const
Retrieves the default wallpaper associated with this theme.
color for hover effect on buttons
#define DEFAULT_WALLPAPER_SUFFIX
Interface to the Plasma theme.
Q_INVOKABLE QFontMetrics fontMetrics() const
void invalidateRectsCache(const QString &image)
Discards all the information about a given image from the rectangle disk cache.
QStringList listCachedRectKeys(const QString &image) const
Returns a list of all keys of cached rects for the given image.
bool findInRectsCache(const QString &image, const QString &element, QRectF &rect) const
Tries to load the rect of a sub element from a disk cache.
void insertIntoCache(const QString &key, const QPixmap &pix)
Insert specified pixmap into the cache.
Q_INVOKABLE QColor color(ColorRole role) const
Returns the text color to be used by items resting on the background.
#define DEFAULT_WALLPAPER_THEME
the default background color
background color for buttons
color for hover effect on view
color visited clickable links
PackageStructure::Ptr packageStructure(const QString &language, ComponentType type)
Loads an appropriate PackageStructure for the given language and type.
bool useGlobalSettings() const
QString themeName() const