diff --git a/src/plasma/private/theme_p.cpp b/src/plasma/private/theme_p.cpp index 1fde11347..757c40e5a 100644 --- a/src/plasma/private/theme_p.cpp +++ b/src/plasma/private/theme_p.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -39,23 +40,49 @@ const char *ThemePrivate::systemColorsTheme = "internal-system-colors"; EffectWatcher *ThemePrivate::s_blurEffectWatcher = 0; #endif -ThemePrivate::ThemePrivate(Theme *theme) - : colorScheme(QPalette::Active, KColorScheme::Window, KSharedConfigPtr(0)), - buttonColorScheme(QPalette::Active, KColorScheme::Button, KSharedConfigPtr(0)), - viewColorScheme(QPalette::Active, KColorScheme::View, KSharedConfigPtr(0)), - defaultWallpaperTheme(DEFAULT_WALLPAPER_THEME), - defaultWallpaperSuffix(DEFAULT_WALLPAPER_SUFFIX), - defaultWallpaperWidth(DEFAULT_WALLPAPER_WIDTH), - defaultWallpaperHeight(DEFAULT_WALLPAPER_HEIGHT), - pixmapCache(0), - cacheSize(0), - cachesToDiscard(NoCache), - locolor(false), - compositingActive(KWindowSystem::self()->compositingActive()), - blurActive(false), - isDefault(false), - useGlobal(true), - hasWallpapers(false) +ThemePrivate *ThemePrivate::globalTheme = 0; +int ThemePrivate::globalThemeRefCount = 0; +QHash ThemePrivate::themes = QHash(); +QHash ThemePrivate::themesRefCount = QHash(); + + +class ThemePrivateSingleton +{ +public: + ThemePrivateSingleton() + { + self.isDefault = true; + + //FIXME: if/when kconfig gets change notification, this will be unnecessary + KDirWatch::self()->addFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + ThemePrivate::themeRcFile); + QObject::connect(KDirWatch::self(), SIGNAL(created(QString)), &self, SLOT(settingsFileChanged(QString))); + QObject::connect(KDirWatch::self(), SIGNAL(dirty(QString)), &self, SLOT(settingsFileChanged(QString))); + } + + ThemePrivate self; +}; + +Q_GLOBAL_STATIC(ThemePrivateSingleton, themePrivateSelf) + + +ThemePrivate::ThemePrivate(QObject *parent) + : QObject(parent), + colorScheme(QPalette::Active, KColorScheme::Window, KSharedConfigPtr(0)), + buttonColorScheme(QPalette::Active, KColorScheme::Button, KSharedConfigPtr(0)), + viewColorScheme(QPalette::Active, KColorScheme::View, KSharedConfigPtr(0)), + defaultWallpaperTheme(DEFAULT_WALLPAPER_THEME), + defaultWallpaperSuffix(DEFAULT_WALLPAPER_SUFFIX), + defaultWallpaperWidth(DEFAULT_WALLPAPER_WIDTH), + defaultWallpaperHeight(DEFAULT_WALLPAPER_HEIGHT), + pixmapCache(0), + cacheSize(0), + cachesToDiscard(NoCache), + locolor(false), + compositingActive(KWindowSystem::self()->compositingActive()), + blurActive(false), + isDefault(false), + useGlobal(true), + hasWallpapers(false) { ThemeConfig config; cacheTheme = config.cacheTheme(); @@ -87,6 +114,11 @@ ThemePrivate::~ThemePrivate() delete pixmapCache; } +ThemePrivate *ThemePrivate::self() +{ + return &themePrivateSelf()->self; +} + KConfigGroup &ThemePrivate::config() { if (!cfg.isValid()) { diff --git a/src/plasma/private/theme_p.h b/src/plasma/private/theme_p.h index d4b8ddc18..2e1bebc89 100644 --- a/src/plasma/private/theme_p.h +++ b/src/plasma/private/theme_p.h @@ -65,9 +65,11 @@ class ThemePrivate : public QObject Q_OBJECT public: - ThemePrivate(Theme *theme); + ThemePrivate(QObject *parent = 0); ~ThemePrivate(); + static ThemePrivate *self(); + KConfigGroup &config(); QString findInTheme(const QString &image, const QString &theme, bool cache = true); @@ -100,7 +102,10 @@ public: #if HAVE_X11 static EffectWatcher *s_blurEffectWatcher; #endif - static QHashdAssociations; + static ThemePrivate *globalTheme; + static int globalThemeRefCount; + static QHash themes; + static QHash themesRefCount; QString themeName; KPluginInfo pluginInfo; diff --git a/src/plasma/theme.cpp b/src/plasma/theme.cpp index b51ea0761..e187a87f2 100644 --- a/src/plasma/theme.cpp +++ b/src/plasma/theme.cpp @@ -74,8 +74,15 @@ Theme *Theme::defaultTheme() Theme::Theme(QObject *parent) : QObject(parent), - d(new ThemePrivate(this)) + d(ThemePrivate::self()) { + if (!ThemePrivate::globalTheme) { + ThemePrivate::globalTheme = new ThemePrivate; + ++ThemePrivate::globalThemeRefCount; + } + + d = ThemePrivate::globalTheme; + d->settingsChanged(); if (QCoreApplication::instance()) { connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), @@ -85,13 +92,20 @@ Theme::Theme(QObject *parent) } Theme::Theme(const QString &themeName, QObject *parent) - : QObject(parent), - d(new ThemePrivate(this)) + : QObject(parent) { + if (!ThemePrivate::themes.contains(themeName)) { + ThemePrivate::themes[themeName] = new ThemePrivate; + ThemePrivate::themesRefCount[themeName] = 0; + } + + ++ThemePrivate::themesRefCount[themeName]; + d = ThemePrivate::themes[themeName]; + // turn off caching so we don't accidently trigger unnecessary disk activity at this point bool useCache = d->cacheTheme; d->cacheTheme = false; - setThemeName(themeName); + d->setThemeName(themeName, true); d->cacheTheme = useCache; if (QCoreApplication::instance()) { connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), @@ -111,11 +125,48 @@ Theme::~Theme() } d->onAppExitCleanup(); + + if (d == ThemePrivate::globalTheme) { + --ThemePrivate::globalThemeRefCount; + if (ThemePrivate::globalThemeRefCount == 0) { + delete ThemePrivate::globalTheme; + } + } else { + --ThemePrivate::themesRefCount[d->themeName]; + if (ThemePrivate::themesRefCount[d->themeName] == 0) { + ThemePrivate *themePrivate = ThemePrivate::themes[d->themeName]; + ThemePrivate::themes.remove(d->themeName); + ThemePrivate::themesRefCount.remove(d->themeName); + delete themePrivate; + } + } delete d; } void Theme::setThemeName(const QString &themeName) { + if (d->themeName == themeName) { + return; + } + + if (d != ThemePrivate::globalTheme) { + --ThemePrivate::themesRefCount[d->themeName]; + if (ThemePrivate::themesRefCount[d->themeName] == 0) { + ThemePrivate *themePrivate = ThemePrivate::themes[d->themeName]; + ThemePrivate::themes.remove(d->themeName); + ThemePrivate::themesRefCount.remove(d->themeName); + delete themePrivate; + } + } + + if (!ThemePrivate::themes.contains(themeName)) { + ThemePrivate::themes[themeName] = new ThemePrivate; + ThemePrivate::themesRefCount[themeName] = 0; + } + + ++ThemePrivate::themesRefCount[themeName]; + d = ThemePrivate::themes[themeName]; + d->setThemeName(themeName, true); }