• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Plasma

theme.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
00003  *
00004  *   This program is free software; you can redistribute it and/or modify
00005  *   it under the terms of the GNU Library General Public License as
00006  *   published by the Free Software Foundation; either version 2, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Library General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 #include "theme.h"
00021 
00022 #include <QApplication>
00023 #include <QFile>
00024 #include <QFileInfo>
00025 #include <QTimer>
00026 #include <QPair>
00027 #ifdef Q_WS_X11
00028 #include <QX11Info>
00029 #endif
00030 
00031 #include <kcolorscheme.h>
00032 #include <kcomponentdata.h>
00033 #include <kconfiggroup.h>
00034 #include <kdebug.h>
00035 #include <kdirwatch.h>
00036 #include <kglobal.h>
00037 #include <kglobalsettings.h>
00038 #include <kmanagerselection.h>
00039 #include <kpixmapcache.h>
00040 #include <ksharedconfig.h>
00041 #include <kstandarddirs.h>
00042 #include <kwindowsystem.h>
00043 
00044 #include "private/packages_p.h"
00045 
00046 namespace Plasma
00047 {
00048 
00049 #define DEFAULT_WALLPAPER_THEME "Air"
00050 #define DEFAULT_WALLPAPER_SUFFIX ".jpg"
00051 static const int DEFAULT_WALLPAPER_WIDTH = 1920;
00052 static const int DEFAULT_WALLPAPER_HEIGHT = 1200;
00053 
00054 class ThemePrivate
00055 {
00056 public:
00057     ThemePrivate(Theme *theme)
00058         : q(theme),
00059           colorScheme(QPalette::Active, KColorScheme::Window, KSharedConfigPtr(0)),
00060           buttonColorScheme(QPalette::Active, KColorScheme::Button, KSharedConfigPtr(0)),
00061           defaultWallpaperTheme(DEFAULT_WALLPAPER_THEME),
00062           defaultWallpaperSuffix(DEFAULT_WALLPAPER_SUFFIX),
00063           defaultWallpaperWidth(DEFAULT_WALLPAPER_WIDTH),
00064           defaultWallpaperHeight(DEFAULT_WALLPAPER_HEIGHT),
00065           pixmapCache(0),
00066           locolor(false),
00067           compositingActive(KWindowSystem::compositingActive()),
00068           isDefault(false),
00069           useGlobal(true),
00070           hasWallpapers(false),
00071           useNativeWidgetStyle(false)
00072     {
00073         generalFont = QApplication::font();
00074         cacheTheme = cacheConfig().readEntry("CacheTheme", true);
00075 
00076 #ifdef Q_WS_X11
00077         Display *dpy = QX11Info::display();
00078         int screen = DefaultScreen(dpy);
00079         locolor = DefaultDepth(dpy, screen) < 16;
00080 
00081         if (!locolor) {
00082             char net_wm_cm_name[100];
00083             sprintf(net_wm_cm_name, "_NET_WM_CM_S%d", screen);
00084             compositeWatch = new KSelectionWatcher(net_wm_cm_name, -1, q);
00085             QObject::connect(compositeWatch, SIGNAL(newOwner(Window)), q, SLOT(compositingChanged()));
00086             QObject::connect(compositeWatch, SIGNAL(lostOwner()), q, SLOT(compositingChanged()));
00087         }
00088 #endif
00089 
00090         saveTimer = new QTimer(q);
00091         saveTimer->setSingleShot(true);
00092         QObject::connect(saveTimer, SIGNAL(timeout()), q, SLOT(scheduledCacheUpdate()));
00093     }
00094 
00095     ~ThemePrivate()
00096     {
00097        delete pixmapCache;
00098     }
00099 
00100     KConfigGroup cacheConfig()
00101     {
00102         return KConfigGroup(KSharedConfig::openConfig(themeRcFile), "CachePolicies");
00103     }
00104 
00105     KConfigGroup &config()
00106     {
00107         if (!cfg.isValid()) {
00108             QString groupName = "Theme";
00109 
00110             if (!useGlobal) {
00111                 QString app = KGlobal::mainComponent().componentName();
00112 
00113                 if (!app.isEmpty() && app != "plasma") {
00114                     kDebug() << "using theme for app" << app;
00115                     groupName.append("-").append(app);
00116                 }
00117             }
00118 
00119             cfg = KConfigGroup(KSharedConfig::openConfig(themeRcFile), groupName);
00120         }
00121 
00122         return cfg;
00123     }
00124 
00125     QString findInTheme(const QString &image, const QString &theme) const;
00126     void compositingChanged();
00127     void discardCache(bool recreateElementsCache);
00128     void scheduledCacheUpdate();
00129     void colorsChanged();
00130     bool useCache();
00131     void settingsFileChanged(const QString &);
00132     void setThemeName(const QString &themeName, bool writeSettings);
00133 
00134     static const char *defaultTheme;
00135     static const char *themeRcFile;
00136     static PackageStructure::Ptr packageStructure;
00137 
00138     Theme *q;
00139     QString themeName;
00140     QList<QString> fallbackThemes;
00141     KSharedConfigPtr colors;
00142     KColorScheme colorScheme;
00143     KColorScheme buttonColorScheme;
00144     KConfigGroup cfg;
00145     QFont generalFont;
00146     QString defaultWallpaperTheme;
00147     QString defaultWallpaperSuffix;
00148     int defaultWallpaperWidth;
00149     int defaultWallpaperHeight;
00150     KPixmapCache *pixmapCache;
00151     KSharedConfigPtr svgElementsCache;
00152     QHash<QString, QSet<QString> > invalidElements;
00153     QHash<QString, QPixmap> pixmapsToCache;
00154     QHash<QString, QString> keysToCache;
00155     QHash<QString, QString> idsToCache;
00156     QTimer *saveTimer;
00157 
00158 #ifdef Q_WS_X11
00159     KSelectionWatcher *compositeWatch;
00160 #endif
00161     bool locolor : 1;
00162     bool compositingActive : 1;
00163     bool isDefault : 1;
00164     bool useGlobal : 1;
00165     bool hasWallpapers : 1;
00166     bool cacheTheme : 1;
00167     bool useNativeWidgetStyle :1;
00168 };
00169 
00170 PackageStructure::Ptr ThemePrivate::packageStructure(0);
00171 const char *ThemePrivate::defaultTheme = "default";
00172 const char *ThemePrivate::themeRcFile = "plasmarc";
00173 
00174 bool ThemePrivate::useCache()
00175 {
00176     if (cacheTheme && !pixmapCache) {
00177         pixmapCache = new KPixmapCache("plasma_theme_" + themeName);
00178         pixmapCache->setCacheLimit(cacheConfig().readEntry("ThemeCacheKb", 80 * 1024));
00179     }
00180 
00181     return cacheTheme;
00182 }
00183 
00184 QString ThemePrivate::findInTheme(const QString &image, const QString &theme) const
00185 {
00186     //TODO: this should be using Package
00187     QString search;
00188 
00189     if (locolor) {
00190         search = "desktoptheme/" + theme + "/locolor/" + image;
00191         search =  KStandardDirs::locate("data", search);
00192     } else if (!compositingActive) {
00193         search = "desktoptheme/" + theme + "/opaque/" + image;
00194         search =  KStandardDirs::locate("data", search);
00195     }
00196 
00197     //not found or compositing enabled
00198     if (search.isEmpty()) {
00199         search = "desktoptheme/" + theme + '/' + image;
00200         search =  KStandardDirs::locate("data", search);
00201     }
00202 
00203     return search;
00204 }
00205 
00206 void ThemePrivate::compositingChanged()
00207 {
00208 #ifdef Q_WS_X11
00209     bool nowCompositingActive = compositeWatch->owner() != None;
00210 
00211     if (compositingActive != nowCompositingActive) {
00212         compositingActive = nowCompositingActive;
00213         discardCache(true);
00214         emit q->themeChanged();
00215     }
00216 #endif
00217 }
00218 
00219 void ThemePrivate::discardCache(bool recreateElementsCache)
00220 {
00221     KPixmapCache::deleteCache("plasma_theme_" + themeName);
00222     delete pixmapCache;
00223     pixmapCache = 0;
00224     invalidElements.clear();
00225     pixmapsToCache.clear();
00226     saveTimer->stop();
00227 
00228     svgElementsCache = 0;
00229     QString svgElementsFile = KStandardDirs::locateLocal("cache", "plasma-svgelements-" + themeName);
00230     if (!svgElementsFile.isEmpty()) {
00231         QFile f(svgElementsFile);
00232         f.remove();
00233     }
00234 
00235     if (recreateElementsCache) {
00236         svgElementsCache = KSharedConfig::openConfig(svgElementsFile);
00237     }
00238 }
00239 
00240 void ThemePrivate::scheduledCacheUpdate()
00241 {
00242     QHashIterator<QString, QPixmap> it(pixmapsToCache);
00243     while (it.hasNext()) {
00244         it.next();
00245         pixmapCache->insert(idsToCache[it.key()], it.value());
00246     }
00247 
00248     pixmapsToCache.clear();
00249     keysToCache.clear();
00250     idsToCache.clear();
00251 }
00252 
00253 void ThemePrivate::colorsChanged()
00254 {
00255     discardCache(true);
00256     colorScheme = KColorScheme(QPalette::Active, KColorScheme::Window, colors);
00257     buttonColorScheme = KColorScheme(QPalette::Active, KColorScheme::Button, colors);
00258     emit q->themeChanged();
00259 }
00260 
00261 class ThemeSingleton
00262 {
00263 public:
00264     ThemeSingleton()
00265     {
00266         self.d->isDefault = true;
00267 
00268         //FIXME: if/when kconfig gets change notification, this will be unecessary
00269         KDirWatch::self()->addFile(KStandardDirs::locateLocal("config", ThemePrivate::themeRcFile));
00270         QObject::connect(KDirWatch::self(), SIGNAL(created(QString)), &self, SLOT(settingsFileChanged(QString)));
00271         QObject::connect(KDirWatch::self(), SIGNAL(dirty(QString)), &self, SLOT(settingsFileChanged(QString)));
00272     }
00273 
00274    Theme self;
00275 };
00276 
00277 K_GLOBAL_STATIC(ThemeSingleton, privateThemeSelf)
00278 
00279 Theme *Theme::defaultTheme()
00280 {
00281     return &privateThemeSelf->self;
00282 }
00283 
00284 Theme::Theme(QObject *parent)
00285     : QObject(parent),
00286       d(new ThemePrivate(this))
00287 {
00288     settingsChanged();
00289 }
00290 
00291 Theme::Theme(const QString &themeName, QObject *parent)
00292     : QObject(parent),
00293       d(new ThemePrivate(this))
00294 {
00295     // turn off caching so we don't accidently trigger unnecessary disk activity at this point
00296     bool useCache = d->cacheTheme;
00297     d->cacheTheme = false;
00298     setThemeName(themeName);
00299     d->cacheTheme = useCache;
00300 }
00301 
00302 Theme::~Theme()
00303 {
00304     QHashIterator<QString, QSet<QString> > it(d->invalidElements);
00305     while (it.hasNext()) {
00306         it.next();
00307         KConfigGroup imageGroup(d->svgElementsCache, it.key());
00308         imageGroup.writeEntry("invalidElements", it.value().toList()); //FIXME: add QSet support to KConfig
00309     }
00310 
00311     delete d;
00312 }
00313 
00314 PackageStructure::Ptr Theme::packageStructure()
00315 {
00316     if (!ThemePrivate::packageStructure) {
00317         ThemePrivate::packageStructure = new ThemePackage();
00318     }
00319 
00320     return ThemePrivate::packageStructure;
00321 }
00322 
00323 KPluginInfo::List Theme::listThemeInfo()
00324 {
00325     QStringList themes = KGlobal::dirs()->findAllResources("data", "desktoptheme/*/metadata.desktop",
00326                                                            KStandardDirs::NoDuplicates);
00327     return KPluginInfo::fromFiles(themes);
00328 }
00329 
00330 void ThemePrivate::settingsFileChanged(const QString &file)
00331 {
00332     if (file.endsWith(themeRcFile)) {
00333         config().config()->reparseConfiguration();
00334         q->settingsChanged();
00335     }
00336 }
00337 
00338 void Theme::settingsChanged()
00339 {
00340     d->setThemeName(d->config().readEntry("name", ThemePrivate::defaultTheme), false);
00341 }
00342 
00343 void Theme::setThemeName(const QString &themeName)
00344 {
00345     d->setThemeName(themeName, true);
00346 }
00347 
00348 void ThemePrivate::setThemeName(const QString &tempThemeName, bool writeSettings)
00349 {
00350     //kDebug() << tempThemeName;
00351     QString theme = tempThemeName;
00352     if (theme.isEmpty() || theme == themeName) {
00353         // let's try and get the default theme at least
00354         if (themeName.isEmpty()) {
00355             theme = ThemePrivate::defaultTheme;
00356         } else {
00357             return;
00358         }
00359     }
00360 
00361     //TODO: should we care about names with relative paths in them?
00362     QString themePath = KStandardDirs::locate("data", "desktoptheme/" + theme + '/');
00363     if (themePath.isEmpty() && themeName.isEmpty()) {
00364         themePath = KStandardDirs::locate("data", "desktoptheme/default/");
00365 
00366         if (themePath.isEmpty()) {
00367             return;
00368         }
00369 
00370         theme = ThemePrivate::defaultTheme;
00371     }
00372 
00373     if (themeName == theme) {
00374         return;
00375     }
00376 
00377     //discard the old theme cache
00378     if (!themeName.isEmpty() && pixmapCache) {
00379         discardCache(false);
00380     }
00381 
00382     themeName = theme;
00383 
00384     // load the color scheme config
00385     QString colorsFile = KStandardDirs::locate("data", "desktoptheme/" + theme + "/colors");
00386     //kDebug() << "we're going for..." << colorsFile << "*******************";
00387 
00388     // load the wallpaper settings, if any
00389     QString metadataPath(KStandardDirs::locate("data", "desktoptheme/" + theme + "/metadata.desktop"));
00390     KConfig metadata(metadataPath);
00391     KConfigGroup cg;
00392     if (metadata.hasGroup("Wallpaper")) {
00393         // we have a theme color config, so let's also check to see if
00394         // there is a wallpaper defined in there.
00395         cg = KConfigGroup(&metadata, "Wallpaper");
00396     } else {
00397         // since we didn't find an entry in the theme, let's look in the main
00398         // theme config
00399         cg = config();
00400     }
00401 
00402     defaultWallpaperTheme = cg.readEntry("defaultWallpaperTheme", DEFAULT_WALLPAPER_THEME);
00403     defaultWallpaperSuffix = cg.readEntry("defaultFileSuffix", DEFAULT_WALLPAPER_SUFFIX);
00404     defaultWallpaperWidth = cg.readEntry("defaultWidth", DEFAULT_WALLPAPER_WIDTH);
00405     defaultWallpaperHeight = cg.readEntry("defaultHeight", DEFAULT_WALLPAPER_HEIGHT);
00406 
00407     cg = KConfigGroup(&metadata, "Settings");
00408     useNativeWidgetStyle = cg.readEntry("UseNativeWidgetStyle", false);
00409     QString fallback = cg.readEntry("FallbackTheme", QString());
00410 
00411     fallbackThemes.clear();
00412     while (!fallback.isEmpty() && !fallbackThemes.contains(fallback)) {
00413         fallbackThemes.append(fallback);
00414 
00415         QString metadataPath(KStandardDirs::locate("data", "desktoptheme/" + theme + "/metadata.desktop"));
00416         KConfig metadata(metadataPath);
00417         cg = KConfigGroup(&metadata, "Settings");
00418         fallback = cg.readEntry("FallbackTheme", QString());
00419 
00420         //TODO: grab the fallback's wallpaper defaults?
00421     }
00422 
00423     if (!fallbackThemes.contains("oxygen")) {
00424         fallbackThemes.append("oxygen");
00425     }
00426 
00427     if (!fallbackThemes.contains(ThemePrivate::defaultTheme)) {
00428         fallbackThemes.append(ThemePrivate::defaultTheme);
00429     }
00430 
00431     QObject::disconnect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
00432                         q, SLOT(colorsChanged()));
00433 
00434     if (colorsFile.isEmpty()) {
00435         colors = 0;
00436         QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
00437                          q, SLOT(colorsChanged()));
00438     } else {
00439         colors = KSharedConfig::openConfig(colorsFile);
00440     }
00441 
00442     colorScheme = KColorScheme(QPalette::Active, KColorScheme::Window, colors);
00443     buttonColorScheme = KColorScheme(QPalette::Active, KColorScheme::Button, colors);
00444     hasWallpapers = KStandardDirs::exists(KStandardDirs::locateLocal("data", "desktoptheme/" + theme + "/wallpapers/"));
00445 
00446     if (isDefault && writeSettings) {
00447         // we're the default theme, let's save our state
00448         KConfigGroup &cg = config();
00449         if (ThemePrivate::defaultTheme == themeName) {
00450             cg.deleteEntry("name");
00451         } else {
00452             cg.writeEntry("name", themeName);
00453         }
00454         cg.sync();
00455     }
00456 
00457     //check for expired cache
00458     QFile f(metadataPath);
00459     QFileInfo info(f);
00460 
00461     if (useCache() && info.lastModified().toTime_t() > pixmapCache->timestamp()) {
00462         discardCache(false);
00463     }
00464 
00465     invalidElements.clear();
00466     QString svgElementsFile = KStandardDirs::locateLocal("cache", "plasma-svgelements-" + themeName);
00467     svgElementsCache = KSharedConfig::openConfig(svgElementsFile);
00468 
00469     emit q->themeChanged();
00470 }
00471 
00472 QString Theme::themeName() const
00473 {
00474     return d->themeName;
00475 }
00476 
00477 QString Theme::imagePath(const QString &name) const
00478 {
00479     // look for a compressed svg file in the theme
00480     if (name.contains("../") || name.isEmpty()) {
00481         // we don't support relative paths
00482         kDebug() << "Theme says: bad image path " << name;
00483         return QString();
00484     }
00485 
00486     QString path = d->findInTheme(name + ".svgz", d->themeName);
00487 
00488     if (path.isEmpty()) {
00489         // try for an uncompressed svg file
00490         path = d->findInTheme(name + ".svg", d->themeName);
00491 
00492         // search in fallback themes if necessary
00493         for (int i = 0; path.isEmpty() && i < d->fallbackThemes.count(); ++i) {
00494             if (d->themeName == d->fallbackThemes[i]) {
00495                 continue;
00496             }
00497 
00498             // try a compressed svg file in the fallback theme
00499             path = d->findInTheme(name + ".svgz", d->fallbackThemes[i]);
00500 
00501             if (path.isEmpty()) {
00502                 // try an uncompressed svg file in the fallback theme
00503                 path = d->findInTheme(name + ".svg", d->fallbackThemes[i]);
00504             }
00505         }
00506     }
00507 
00508     if (path.isEmpty()) {
00509         kDebug() << "Theme says: bad image path " << name;
00510     }
00511 
00512     return path;
00513 }
00514 
00515 QString Theme::wallpaperPath(const QSize &size) const
00516 {
00517     QString fullPath;
00518     QString image = d->defaultWallpaperTheme;
00519 
00520     image.append("/contents/images/%1x%2").append(d->defaultWallpaperSuffix);
00521     QString defaultImage = image.arg(d->defaultWallpaperWidth).arg(d->defaultWallpaperHeight);
00522 
00523     if (size.isValid()) {
00524         // try to customize the paper to the size requested
00525         //TODO: this should do better than just fallback to the default size.
00526         //      a "best fit" matching would be far better, so we don't end
00527         //      up returning a 1920x1200 wallpaper for a 640x480 request ;)
00528         image = image.arg(size.width()).arg(size.height());
00529     } else {
00530         image = defaultImage;
00531     }
00532 
00533     //TODO: the theme's wallpaper overrides regularly installed wallpapers.
00534     //      should it be possible for user installed (e.g. locateLocal) wallpapers
00535     //      to override the theme?
00536     if (d->hasWallpapers) {
00537         // check in the theme first
00538         fullPath = d->findInTheme("wallpapers/" + image, d->themeName);
00539 
00540         if (fullPath.isEmpty()) {
00541             fullPath = d->findInTheme("wallpapers/" + defaultImage, d->themeName);
00542         }
00543     }
00544 
00545     if (fullPath.isEmpty()) {
00546         // we failed to find it in the theme, so look in the standard directories
00547         //kDebug() << "looking for" << image;
00548         fullPath = KStandardDirs::locate("wallpaper", image);
00549     }
00550 
00551     if (fullPath.isEmpty()) {
00552         // we still failed to find it in the theme, so look for the default in
00553         // the standard directories
00554         //kDebug() << "looking for" << defaultImage;
00555         fullPath = KStandardDirs::locate("wallpaper", defaultImage);
00556 
00557         if (fullPath.isEmpty()) {
00558             kDebug() << "exhausted every effort to find a wallpaper.";
00559         }
00560     }
00561 
00562     return fullPath;
00563 }
00564 
00565 bool Theme::currentThemeHasImage(const QString &name) const
00566 {
00567     if (name.contains("../")) {
00568         // we don't support relative paths
00569         return false;
00570     }
00571 
00572     return !(d->findInTheme(name + ".svgz", d->themeName).isEmpty()) ||
00573            !(d->findInTheme(name + ".svg", d->themeName).isEmpty());
00574 }
00575 
00576 KSharedConfigPtr Theme::colorScheme() const
00577 {
00578     return d->colors;
00579 }
00580 
00581 QColor Theme::color(ColorRole role) const
00582 {
00583     switch (role) {
00584         case TextColor:
00585             return d->colorScheme.foreground(KColorScheme::NormalText).color();
00586             break;
00587 
00588         case HighlightColor:
00589             return d->colorScheme.decoration(KColorScheme::HoverColor).color();
00590             break;
00591 
00592         case BackgroundColor:
00593             return d->colorScheme.background().color();
00594             break;
00595 
00596         case ButtonTextColor:
00597             return d->buttonColorScheme.foreground(KColorScheme::NormalText).color();
00598             break;
00599 
00600         case ButtonBackgroundColor:
00601             return d->buttonColorScheme.background(KColorScheme::ActiveBackground).color();
00602             break;
00603     }
00604 
00605     return QColor();
00606 }
00607 
00608 void Theme::setFont(const QFont &font, FontRole role)
00609 {
00610     Q_UNUSED(role)
00611     d->generalFont = font;
00612 }
00613 
00614 QFont Theme::font(FontRole role) const
00615 {
00616     Q_UNUSED(role)
00617     switch (role) {
00618     case DesktopFont:
00619     {
00620         KConfigGroup cg(KGlobal::config(), "General");
00621         return cg.readEntry("desktopFont", QFont("Sans Serif", 10));
00622     }
00623     break;
00624     case DefaultFont:
00625     default:
00626         return d->generalFont;
00627         break;
00628     }
00629 
00630     return d->generalFont;
00631 }
00632 
00633 QFontMetrics Theme::fontMetrics() const
00634 {
00635     //TODO: allow this to be overridden with a plasma specific font?
00636     return QFontMetrics(d->generalFont);
00637 }
00638 
00639 bool Theme::windowTranslucencyEnabled() const
00640 {
00641     return d->compositingActive;
00642 }
00643 
00644 void Theme::setUseGlobalSettings(bool useGlobal)
00645 {
00646     if (d->useGlobal == useGlobal) {
00647         return;
00648     }
00649 
00650     d->useGlobal = useGlobal;
00651     d->cfg = KConfigGroup();
00652     d->themeName.clear();
00653     settingsChanged();
00654 }
00655 
00656 bool Theme::useGlobalSettings() const
00657 {
00658     return d->useGlobal;
00659 }
00660 
00661 bool Theme::useNativeWidgetStyle() const
00662 {
00663     return d->useNativeWidgetStyle;
00664 }
00665 
00666 bool Theme::findInCache(const QString &key, QPixmap &pix)
00667 {
00668     if (d->useCache()) {
00669         const QString id = d->keysToCache.value(key);
00670         if (d->pixmapsToCache.contains(id)) {
00671             pix = d->pixmapsToCache.value(id);
00672             return true;
00673         }
00674 
00675         return d->pixmapCache->find(key, pix);
00676     }
00677 
00678     return false;
00679 }
00680 
00681 // BIC FIXME: Should be merged with the other findInCache method above when we break BC
00682 bool Theme::findInCache(const QString &key, QPixmap &pix, unsigned int lastModified)
00683 {
00684     if (d->useCache() && lastModified > d->pixmapCache->timestamp()) {
00685         return false;
00686     }
00687 
00688     return findInCache(key, pix);
00689 }
00690 
00691 void Theme::insertIntoCache(const QString& key, const QPixmap& pix)
00692 {
00693     if (d->useCache()) {
00694         d->pixmapCache->insert(key, pix);
00695     }
00696 }
00697 
00698 void Theme::insertIntoCache(const QString& key, const QPixmap& pix, const QString& id)
00699 {
00700     if (d->useCache()) {
00701         d->pixmapsToCache.insert(id, pix);
00702 
00703         if (d->idsToCache.contains(id)) {
00704             d->keysToCache.remove(d->idsToCache[id]);
00705         }
00706 
00707         d->keysToCache.insert(key, id);
00708         d->idsToCache.insert(id, key);
00709         d->saveTimer->start(600);
00710     }
00711 }
00712 
00713 bool Theme::findInRectsCache(const QString &image, const QString &element, QRectF &rect) const
00714 {
00715     if (!d->pixmapCache) {
00716         return false;
00717     }
00718 
00719     KConfigGroup imageGroup(d->svgElementsCache, image);
00720     rect = imageGroup.readEntry(element + "Size", QRectF());
00721 
00722     if (rect.isValid()) {
00723         return true;
00724     }
00725 
00726     //Name starting by _ means the element is empty and we're asked for the size of
00727     //the whole image, so the whole image is never invalid
00728     if (element.indexOf('_') <= 0) {
00729         return false;
00730     }
00731 
00732     bool invalid = false;
00733 
00734     QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
00735     if (it == d->invalidElements.end()) {
00736         QSet<QString> elements = imageGroup.readEntry("invalidElements", QStringList()).toSet();
00737         d->invalidElements.insert(image, elements);
00738         invalid = elements.contains(element);
00739     } else {
00740         invalid = it.value().contains(element);
00741     }
00742 
00743     return invalid;
00744 }
00745 
00746 void Theme::insertIntoRectsCache(const QString& image, const QString &element, const QRectF &rect)
00747 {
00748     if (!d->pixmapCache) {
00749         return;
00750     }
00751 
00752     if (rect.isValid()) {
00753         KConfigGroup imageGroup(d->svgElementsCache, image);
00754         imageGroup.writeEntry(element + "Size", rect);
00755     } else {
00756         QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
00757         if (it == d->invalidElements.end()) {
00758             d->invalidElements[image].insert(element);
00759         } else if (!it.value().contains(element)) {
00760             if (it.value().count() > 1000) {
00761                 it.value().erase(it.value().begin());
00762             }
00763 
00764             it.value().insert(element);
00765         }
00766     }
00767 }
00768 
00769 void Theme::invalidateRectsCache(const QString& image)
00770 {
00771     KConfigGroup imageGroup(d->svgElementsCache, image);
00772     imageGroup.deleteGroup();
00773 
00774     releaseRectsCache(image);
00775 }
00776 
00777 void Theme::releaseRectsCache(const QString &image)
00778 {
00779     QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
00780     if (it != d->invalidElements.end()) {
00781         KConfigGroup imageGroup(d->svgElementsCache, it.key());
00782         imageGroup.writeEntry("invalidElements", it.value().toList());
00783         d->invalidElements.erase(it);
00784     }
00785 }
00786 
00787 void Theme::setCacheLimit(int kbytes)
00788 {
00789     if (d->useCache()) {
00790         d->pixmapCache->setCacheLimit(kbytes);
00791     }
00792 }
00793 
00794 }
00795 
00796 #include <theme.moc>

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal