diff --git a/src/declarativeimports/core/theme.cpp b/src/declarativeimports/core/theme.cpp index 8058640fb..0dc6f43a7 100644 --- a/src/declarativeimports/core/theme.cpp +++ b/src/declarativeimports/core/theme.cpp @@ -41,7 +41,8 @@ ThemeProxy::ThemeProxy(QObject *parent) m_iconSizes->insert("small", KIconLoader::global()->currentSize(KIconLoader::Small)); m_iconSizes->insert("dialog", KIconLoader::global()->currentSize(KIconLoader::Dialog)); - connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SIGNAL(themeChanged())); + m_theme = new Plasma::Theme(this); + connect(m_theme, SIGNAL(themeChanged()), this, SIGNAL(themeChanged())); connect(KIconLoader::global(), SIGNAL(iconLoaderSettingsChanged()), this, SLOT(iconLoaderSettingsChanged())); connect(KGlobalSettings::self(), &KGlobalSettings::kdisplayFontChanged, this, &ThemeProxy::defaultFontChanged); @@ -54,7 +55,7 @@ ThemeProxy::~ThemeProxy() QString ThemeProxy::themeName() const { - return Plasma::Theme::defaultTheme()->themeName(); + return m_theme->themeName(); } QFont ThemeProxy::defaultFont() const @@ -75,87 +76,87 @@ QSizeF ThemeProxy::mSize(const QFont &font) const bool ThemeProxy::useGlobalSettings() const { - return Plasma::Theme::defaultTheme()->useGlobalSettings(); + return m_theme->useGlobalSettings(); } QString ThemeProxy::wallpaperPath() const { - return Plasma::Theme::defaultTheme()->wallpaperPath(); + return m_theme->wallpaperPath(); } QString ThemeProxy::wallpaperPathForSize(int width, int height) const { - return Plasma::Theme::defaultTheme()->wallpaperPath(QSize(width, height)); + return m_theme->wallpaperPath(QSize(width, height)); } QColor ThemeProxy::textColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor); + return m_theme->color(Plasma::Theme::TextColor); } QColor ThemeProxy::highlightColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::HighlightColor); + return m_theme->color(Plasma::Theme::HighlightColor); } QColor ThemeProxy::backgroundColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor); + return m_theme->color(Plasma::Theme::BackgroundColor); } QColor ThemeProxy::buttonTextColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonTextColor); + return m_theme->color(Plasma::Theme::ButtonTextColor); } QColor ThemeProxy::buttonBackgroundColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonBackgroundColor); + return m_theme->color(Plasma::Theme::ButtonBackgroundColor); } QColor ThemeProxy::linkColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::LinkColor); + return m_theme->color(Plasma::Theme::LinkColor); } QColor ThemeProxy::visitedLinkColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::VisitedLinkColor); + return m_theme->color(Plasma::Theme::VisitedLinkColor); } QColor ThemeProxy::buttonHoverColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonHoverColor); + return m_theme->color(Plasma::Theme::ButtonHoverColor); } QColor ThemeProxy::buttonFocusColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonFocusColor); + return m_theme->color(Plasma::Theme::ButtonFocusColor); } QColor ThemeProxy::viewTextColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ViewTextColor); + return m_theme->color(Plasma::Theme::ViewTextColor); } QColor ThemeProxy::viewBackgroundColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ViewBackgroundColor); + return m_theme->color(Plasma::Theme::ViewBackgroundColor); } QColor ThemeProxy::viewHoverColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ViewHoverColor); + return m_theme->color(Plasma::Theme::ViewHoverColor); } QColor ThemeProxy::viewFocusColor() const { - return Plasma::Theme::defaultTheme()->color(Plasma::Theme::ViewFocusColor); + return m_theme->color(Plasma::Theme::ViewFocusColor); } QString ThemeProxy::styleSheet() const { - return Plasma::Theme::defaultTheme()->styleSheet(QString()); + return m_theme->styleSheet(QString()); } int ThemeProxy::smallIconSize() const diff --git a/src/declarativeimports/core/theme.h b/src/declarativeimports/core/theme.h index 7a06f206a..b25f76eac 100644 --- a/src/declarativeimports/core/theme.h +++ b/src/declarativeimports/core/theme.h @@ -137,6 +137,7 @@ Q_SIGNALS: private: int m_defaultIconSize; QQmlPropertyMap *m_iconSizes; + Plasma::Theme *m_theme; }; #endif diff --git a/src/declarativeimports/plasmaextracomponents/appbackgroundprovider.cpp b/src/declarativeimports/plasmaextracomponents/appbackgroundprovider.cpp index 11c8f2daf..c25e6cc35 100644 --- a/src/declarativeimports/plasmaextracomponents/appbackgroundprovider.cpp +++ b/src/declarativeimports/plasmaextracomponents/appbackgroundprovider.cpp @@ -29,13 +29,19 @@ AppBackgroundProvider::AppBackgroundProvider() : QQuickImageProvider(QQuickImageProvider::Image) { + m_theme = new Plasma::Theme(); +} + +AppBackgroundProvider::~AppBackgroundProvider() +{ + m_theme->deleteLater(); } QImage AppBackgroundProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { Q_UNUSED(size) Q_UNUSED(requestedSize) - QString search = QLatin1Literal("desktoptheme/") % Plasma::Theme::defaultTheme()->themeName() % QLatin1Literal("/appbackgrounds/") % id % ".png"; + QString search = QLatin1Literal("desktoptheme/") % m_theme->themeName() % QLatin1Literal("/appbackgrounds/") % id % ".png"; search = QStandardPaths::locate(QStandardPaths::GenericDataLocation, search); return QImage(search); } diff --git a/src/declarativeimports/plasmaextracomponents/appbackgroundprovider_p.h b/src/declarativeimports/plasmaextracomponents/appbackgroundprovider_p.h index b30eb0f48..ff466994b 100644 --- a/src/declarativeimports/plasmaextracomponents/appbackgroundprovider_p.h +++ b/src/declarativeimports/plasmaextracomponents/appbackgroundprovider_p.h @@ -22,13 +22,20 @@ #include +namespace Plasma +{ + class Theme; +} class AppBackgroundProvider : public QQuickImageProvider { public: AppBackgroundProvider(); + ~AppBackgroundProvider(); virtual QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize); +private: + Plasma::Theme *m_theme; }; #endif diff --git a/src/plasma/applet.cpp b/src/plasma/applet.cpp index 8870bf221..a96f42b70 100644 --- a/src/plasma/applet.cpp +++ b/src/plasma/applet.cpp @@ -58,7 +58,6 @@ #include "package.h" #include "plasma.h" #include "scripting/appletscript.h" -#include "paintutils.h" #include "pluginloader.h" #include "private/associatedapplicationmanager_p.h" diff --git a/src/plasma/framesvg.cpp b/src/plasma/framesvg.cpp index bdb9748d5..862fa7bef 100644 --- a/src/plasma/framesvg.cpp +++ b/src/plasma/framesvg.cpp @@ -679,7 +679,6 @@ void FrameSvgPrivate::generateBackground(FrameData *frame) const QString id = cacheId(frame, prefix); - Theme *theme = Theme::defaultTheme(); bool frameCached = !frame->cachedBackground.isNull(); bool overlayCached = false; const bool overlayAvailable = !prefix.startsWith(QLatin1String("mask-")) && q->hasElement(prefix % "overlay"); @@ -958,11 +957,11 @@ void FrameSvgPrivate::cacheFrame(const QString &prefixToSave, const QPixmap &bac //kDebug()<<"Saving to cache frame"<insertIntoCache(id, background, QString::number((qint64)q, 16) % prefixToSave); + theme->insertIntoCache(id, background, QString::number((qint64)q, 16) % prefixToSave); if (!overlay.isNull()) { //insert overlay - Theme::defaultTheme()->insertIntoCache("overlay_" % id, overlay, QString::number((qint64)q, 16) % prefixToSave % "overlay"); + theme->insertIntoCache("overlay_" % id, overlay, QString::number((qint64)q, 16) % prefixToSave % "overlay"); } } diff --git a/src/plasma/paintutils.cpp b/src/plasma/paintutils.cpp index 2e95e67f7..14000578c 100644 --- a/src/plasma/paintutils.cpp +++ b/src/plasma/paintutils.cpp @@ -52,58 +52,6 @@ void shadowBlur(QImage &image, int radius, const QColor &color) p.end(); } -//TODO: we should have shadowText methods that paint the results directly into a QPainter passed in -QPixmap shadowText(QString text, QColor textColor, QColor shadowColor, QPoint offset, int radius) -{ - return shadowText(text, qApp->font(), textColor, shadowColor, offset, radius); -} - -QPixmap shadowText(QString text, const QFont &font, QColor textColor, QColor shadowColor, QPoint offset, int radius) -{ - //don't try to paint stuff on a future null pixmap because the text is empty - if (text.isEmpty()) { - return QPixmap(); - } - - // Draw text - QFontMetrics fm(font); - QRect textRect = fm.boundingRect(text); - QPixmap textPixmap(textRect.width(), fm.height()); - textPixmap.fill(Qt::transparent); - QPainter p(&textPixmap); - p.setPen(textColor); - p.setFont(font); - // FIXME: the center alignment here is odd: the rect should be the size needed by - // the text, but for some fonts and configurations this is off by a pixel or so - // and "centering" the text painting 'fixes' that. Need to research why - // this is the case and determine if we should be painting it differently here, - // doing soething different with the boundingRect call or if it's a problem - // in Qt itself - p.drawText(textPixmap.rect(), Qt::AlignCenter, text); - p.end(); - - //Draw blurred shadow - QImage img(textRect.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied); - img.fill(0); - p.begin(&img); - p.drawImage(QPoint(radius, radius), textPixmap.toImage()); - p.end(); - shadowBlur(img, radius, shadowColor); - - //Compose text and shadow - int addSizeX = qMax(0, qAbs(offset.x()) - radius); - int addSizeY = qMax(0, qAbs(offset.y()) - radius); - - QPixmap finalPixmap(img.size() + QSize(addSizeX, addSizeY)); - finalPixmap.fill(Qt::transparent); - p.begin(&finalPixmap); - p.drawImage(qMax(0, offset.x()), qMax(0, offset.y()), img); - p.drawPixmap(radius + qMax(0, -offset.x()), radius + qMax(0, -offset.y()), textPixmap); - p.end(); - - return finalPixmap; -} - QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture) { QFontMetrics fm(font); diff --git a/src/plasma/paintutils.h b/src/plasma/paintutils.h index 1b4272f06..bda57c562 100644 --- a/src/plasma/paintutils.h +++ b/src/plasma/paintutils.h @@ -46,23 +46,6 @@ namespace PaintUtils */ PLASMA_EXPORT void shadowBlur(QImage &image, int radius, const QColor &color); -/** - * Returns a pixmap containing text with blurred shadow. - * Text and shadow colors default to Plasma::Theme colors. - */ -PLASMA_EXPORT QPixmap shadowText(QString text, - const QFont &font, - QColor textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor), - QColor shadowColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor), - QPoint offset = QPoint(1,1), - int radius = 2); - -PLASMA_EXPORT QPixmap shadowText(QString text, - QColor textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor), - QColor shadowColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor), - QPoint offset = QPoint(1,1), - int radius = 2); - PLASMA_EXPORT QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture); PLASMA_EXPORT void drawHalo(QPainter *painter, const QRectF &rect); diff --git a/src/plasma/private/framesvg_p.h b/src/plasma/private/framesvg_p.h index 567ff085d..fdc84422a 100644 --- a/src/plasma/private/framesvg_p.h +++ b/src/plasma/private/framesvg_p.h @@ -26,6 +26,8 @@ #include +#include + namespace Plasma { class FrameData @@ -113,6 +115,7 @@ class FrameSvgPrivate public: FrameSvgPrivate(FrameSvg *psvg) : q(psvg), + theme(new Plasma::Theme(q)), cacheAll(false), overlayPos(0,0) { @@ -135,6 +138,7 @@ public: QString prefix; FrameSvg *q; + Plasma::Theme *theme; bool cacheAll : 1; QPoint overlayPos; diff --git a/src/plasma/private/theme_p.cpp b/src/plasma/private/theme_p.cpp index 1111870bf..f171abc6d 100644 --- a/src/plasma/private/theme_p.cpp +++ b/src/plasma/private/theme_p.cpp @@ -41,9 +41,9 @@ EffectWatcher *ThemePrivate::s_blurEffectWatcher = 0; #endif ThemePrivate *ThemePrivate::globalTheme = 0; -int ThemePrivate::globalThemeRefCount = 0; +QAtomicInt ThemePrivate::globalThemeRefCount = QAtomicInt(); QHash ThemePrivate::themes = QHash(); -QHash ThemePrivate::themesRefCount = QHash(); +QHash ThemePrivate::themesRefCount = QHash(); ThemePrivate::ThemePrivate(QObject *parent) diff --git a/src/plasma/private/theme_p.h b/src/plasma/private/theme_p.h index a5c9cef95..aaf040bcf 100644 --- a/src/plasma/private/theme_p.h +++ b/src/plasma/private/theme_p.h @@ -100,10 +100,11 @@ public: #if HAVE_X11 static EffectWatcher *s_blurEffectWatcher; #endif +//Ref counting of ThemePrivate instances static ThemePrivate *globalTheme; - static int globalThemeRefCount; + static QAtomicInt globalThemeRefCount; static QHash themes; - static QHash themesRefCount; + static QHash themesRefCount; QString themeName; KPluginInfo pluginInfo; diff --git a/src/plasma/svg.cpp b/src/plasma/svg.cpp index a692813d7..dc61937a7 100644 --- a/src/plasma/svg.cpp +++ b/src/plasma/svg.cpp @@ -240,7 +240,7 @@ bool SvgPrivate::setImagePath(const QString &imagePath) Theme *SvgPrivate::actualTheme() { if (!theme) { - theme = Plasma::Theme::defaultTheme(); + theme = new Plasma::Theme(q); } return theme.data(); @@ -820,7 +820,7 @@ void Svg::setTheme(Plasma::Theme *theme) Theme *Svg::theme() const { - return d->theme ? d->theme.data() : Theme::defaultTheme(); + return d->theme.data(); } } // Plasma namespace diff --git a/src/plasma/theme.cpp b/src/plasma/theme.cpp index 60c57074a..7df9bbcbc 100644 --- a/src/plasma/theme.cpp +++ b/src/plasma/theme.cpp @@ -49,43 +49,19 @@ namespace Plasma { -class ThemeSingleton -{ -public: - ThemeSingleton() - { - self.d->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))); - } - - Theme self; -}; - -Q_GLOBAL_STATIC(ThemeSingleton, privateThemeSelf) - -Theme *Theme::defaultTheme() -{ - return &privateThemeSelf()->self; -} - Theme::Theme(QObject *parent) : QObject(parent) { if (!ThemePrivate::globalTheme) { ThemePrivate::globalTheme = new ThemePrivate; - ++ThemePrivate::globalThemeRefCount; } - + ThemePrivate::globalThemeRefCount.ref(); d = ThemePrivate::globalTheme; d->settingsChanged(); if (QCoreApplication::instance()) { connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), - this, SLOT(onAppExitCleanup())); + d, SLOT(onAppExitCleanup())); } connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged); } @@ -95,10 +71,10 @@ Theme::Theme(const QString &themeName, QObject *parent) { if (!ThemePrivate::themes.contains(themeName)) { ThemePrivate::themes[themeName] = new ThemePrivate; - ThemePrivate::themesRefCount[themeName] = 0; + ThemePrivate::themesRefCount[themeName] = QAtomicInt(); } - ++ThemePrivate::themesRefCount[themeName]; + ThemePrivate::themesRefCount[themeName].ref(); d = ThemePrivate::themes[themeName]; // turn off caching so we don't accidently trigger unnecessary disk activity at this point @@ -108,7 +84,7 @@ Theme::Theme(const QString &themeName, QObject *parent) d->cacheTheme = useCache; if (QCoreApplication::instance()) { connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), - this, SLOT(onAppExitCleanup())); + d, SLOT(onAppExitCleanup())); } connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged); } @@ -127,20 +103,20 @@ Theme::~Theme() d->onAppExitCleanup(); if (d == ThemePrivate::globalTheme) { - --ThemePrivate::globalThemeRefCount; - if (ThemePrivate::globalThemeRefCount == 0) { + if (!ThemePrivate::globalThemeRefCount.deref()) { + disconnect(ThemePrivate::globalTheme, 0, this, 0); delete ThemePrivate::globalTheme; + ThemePrivate::globalTheme = 0; + d = 0; } } else { - --ThemePrivate::themesRefCount[d->themeName]; - if (ThemePrivate::themesRefCount[d->themeName] == 0) { + if (!ThemePrivate::themesRefCount[d->themeName].deref()) { 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) @@ -150,24 +126,26 @@ void Theme::setThemeName(const QString &themeName) } if (d != ThemePrivate::globalTheme) { - --ThemePrivate::themesRefCount[d->themeName]; - if (ThemePrivate::themesRefCount[d->themeName] == 0) { + disconnect(QCoreApplication::instance(), 0, d, 0); + if (!ThemePrivate::themesRefCount[d->themeName].deref()) { 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] = QAtomicInt(); + } + ThemePrivate::themesRefCount[themeName].ref(); + d = ThemePrivate::themes[themeName]; + if (QCoreApplication::instance()) { + connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), + d, SLOT(onAppExitCleanup())); } connect(d, &ThemePrivate::themeChanged, this, &Theme::themeChanged); } - ++ThemePrivate::themesRefCount[themeName]; - d = ThemePrivate::themes[themeName]; - d->setThemeName(themeName, true); } diff --git a/src/plasma/theme.h b/src/plasma/theme.h index 81cd2a56f..e1c294d2b 100644 --- a/src/plasma/theme.h +++ b/src/plasma/theme.h @@ -40,10 +40,6 @@ class ThemePrivate; * * @short Interface to the Plasma theme * - * Accessed via Plasma::Theme::defaultTheme() e.g: - * \code - * QString imagePath = Plasma::Theme::defaultTheme()->imagePath("widgets/clock") - * \endcode * * Plasma::Theme provides access to a common and standardized set of graphic * elements stored in SVG format. This allows artists to create single packages @@ -76,20 +72,13 @@ class PLASMA_EXPORT Theme : public QObject }; /** - * Singleton pattern accessor - **/ - static Theme *defaultTheme(); - - /** - * Default constructor. Usually you want to use the singleton instead. - * @see defaultTheme + * Default constructor. It will be the global theme configured in plasmarc * @param parent the parent object */ explicit Theme(QObject *parent = 0); /** - * Construct a theme. Usually you want to use the singleton instead. - * @see defaultTheme + * Construct a theme. It will be a custom theme instance of themeName. * @param themeName the name of the theme to create * @param parent the parent object * @since 4.3 diff --git a/src/shell/scripting/appinterface.cpp b/src/shell/scripting/appinterface.cpp index 846656105..fb904c4ed 100644 --- a/src/shell/scripting/appinterface.cpp +++ b/src/shell/scripting/appinterface.cpp @@ -47,7 +47,7 @@ AppInterface::AppInterface(ScriptEngine *env) : QObject(env), m_env(env) { - + m_theme = new Plasma::Theme(this); } int AppInterface::screenCount() const @@ -108,12 +108,12 @@ int AppInterface::scriptingVersion() const QString AppInterface::theme() const { - return Plasma::Theme::defaultTheme()->themeName(); + return m_theme->themeName(); } void AppInterface::setTheme(const QString &name) { - Plasma::Theme::defaultTheme()->setThemeName(name); + m_theme->setThemeName(name); } bool AppInterface::multihead() const diff --git a/src/shell/scripting/appinterface.h b/src/shell/scripting/appinterface.h index 786529c54..e54ff5a23 100644 --- a/src/shell/scripting/appinterface.h +++ b/src/shell/scripting/appinterface.h @@ -29,6 +29,7 @@ namespace Plasma class Applet; class Containment; class Corona; + class Theme; } // namespace Plasma namespace WorkspaceScripting @@ -90,6 +91,7 @@ Q_SIGNALS: private: ScriptEngine *m_env; QStringList m_knownWidgets; + Plasma::Theme *m_theme; }; }