[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/plasma
From:       David Nolden <david.nolden.kde () art-master ! de>
Date:       2009-05-01 0:41:42
Message-ID: 1241138502.292655.3510.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 961915 by zwabel:

- Allow painting a background color, or a background pattern behind freely floating \
elements of the theme, to provide a better fallback mechanism for transparent themes \
when composition is not available. The color/pattern is given through the \
configuration file, and updating due to changes of the configuration file works \
perfectly. A simple user-interface to use this will be added to the panel \
configuration. If you want to try this out, put into the [Theme] section of your \
plasmarc file: frameBackgroundColor=#aacc00 (Your picked color)
frameBackgroundColorAlpha=120 (Alpha value for the color, between 0 and 255, \
0=invisible, 255=opaque) frameBackgroundPattern=/path/to/image
frameBackgroundPatternAlpha=255 (Alpha value for the pattern, as above)

The color is painted first, then the pattern. They are painted into the mask defined \
by the theme, so this only works nicely with themes that supply proper masks.



 M  +2 -0      CMakeLists.txt  
 A             framebackgroundprovider.cpp   [License: LGPL (v2+)]
 A             framebackgroundprovider.h   [License: LGPL (v2+)]
 M  +22 -7     framesvg.cpp  
 M  +2 -0      private/framesvg_p.h  
 M  +21 -23    svg.cpp  
 M  +150 -3    theme.cpp  
 M  +13 -1     theme.h  


--- trunk/KDE/kdelibs/plasma/CMakeLists.txt #961914:961915
@@ -72,6 +72,7 @@
     framesvg.cpp
     plasma.cpp
     popupapplet.cpp
+    framebackgroundprovider.cpp
     private/applethandle.cpp
     private/datacontainer_p.cpp
     private/desktoptoolbox.cpp
@@ -223,6 +224,7 @@
     servicejob.h
     svg.h
     theme.h
+    framebackgroundprovider.h
     tooltipcontent.h
     tooltipmanager.h
     tooltipmanager.h
--- trunk/KDE/kdelibs/plasma/framesvg.cpp #961914:961915
@@ -32,6 +32,7 @@
 
 #include <plasma/theme.h>
 #include <plasma/applet.h>
+#include "framebackgroundprovider.h"
 
 namespace Plasma
 {
@@ -384,20 +385,28 @@
     painter->drawPixmap(pos, frame->cachedBackground);
 }
 
+QString FrameSvgPrivate::cacheId(const FrameData* frame) const
+{
+    Theme *theme = Theme::defaultTheme();
+    FrameBackgroundProvider* backgroundProvider = \
theme->frameBackgroundProvider(q->imagePath()); +
+
+    return QString::fromLatin1("%6_%5_%4_%3_%2_%1_").
+                         \
arg(frame->enabledBorders).arg(frame->frameSize.width()).arg(frame->frameSize.height()).arg(prefix)
 +                         .arg(q->imagePath()).arg(backgroundProvider ? \
backgroundProvider->identity() : QString()); +}
+
 void FrameSvgPrivate::generateBackground(FrameData *frame)
 {
     if (!frame->cachedBackground.isNull()) {
         return;
     }
 
+    QString id = cacheId(frame);
 
-    QString id = QString::fromLatin1("%5_%4_%3_%2_%1_").
-                         \
arg(frame->enabledBorders).arg(frame->frameSize.width()).arg(frame->frameSize.height()).arg(prefix).arg(q->imagePath());
                
-
     Theme *theme = Theme::defaultTheme();
-    if (theme->findInCache(id, frame->cachedBackground) && \
!frame->cachedBackground.isNull()) { +    if (theme->findInCache(id, \
frame->cachedBackground) && !frame->cachedBackground.isNull())  return;
-    }
 
     //kDebug() << "generating background";
     const int topWidth = q->elementSize(prefix + "top").width();
@@ -602,6 +611,13 @@
         p.drawPixmap(overlayPos, overlay, QRect(overlayPos, overlaySize));
     }
 
+    if(!prefix.startsWith("mask-")) {
+        if(FrameBackgroundProvider* backgroundProvider = \
theme->frameBackgroundProvider(q->imagePath())) { +            \
p.setClipRegion(q->mask() ); +            backgroundProvider->apply(p);
+        }
+    }
+
     if (!framesToSave.contains(prefix)) {
         framesToSave.append(prefix);
     }
@@ -617,8 +633,7 @@
         FrameData *frame = frames[prefix];
         framesToSave.removeAll(prefixToSave);
 
-        QString id = QString::fromLatin1("%5_%4_%3_%2_%1_").
-                            \
arg(frame->enabledBorders).arg(frame->frameSize.width()).arg(frame->frameSize.height()).arg(prefix).arg(q->imagePath());
 +        QString id = cacheId(frame);
 
         //kDebug()<<"Saving to cache frame"<<id;
 
--- trunk/KDE/kdelibs/plasma/private/framesvg_p.h #961914:961915
@@ -85,6 +85,8 @@
         frames.clear();
     }
 
+    QString cacheId(const FrameData* frame) const;
+
     void generateBackground(FrameData *frame);
     void scheduledCacheUpdate();
     void updateSizes();
--- trunk/KDE/kdelibs/plasma/svg.cpp #961914:961915
@@ -364,31 +364,29 @@
 
             QString newPath = Theme::defaultTheme()->imagePath(themePath);
 
-            if (path == newPath) {
-                return;
-            }
+            if (path != newPath) {
+              path = newPath;
+              //delete d->renderer; we're a KSharedPtr
+              eraseRenderer();
 
-            path = newPath;
-            //delete d->renderer; we're a KSharedPtr
-            eraseRenderer();
-
-            // check if new theme svg wants colorscheme applied
-            bool wasApplyColors = applyColors;
-            checkApplyColorHint();
-            if (applyColors && !Theme::defaultTheme()->colorScheme()) {
-                if (!wasApplyColors) {
-                    QObject::connect(KGlobalSettings::self(), \
                SIGNAL(kdisplayPaletteChanged()),
-                                     q, SLOT(colorsChanged()));
-                }
-            } else {
-                QObject::disconnect(KGlobalSettings::self(), \
                SIGNAL(kdisplayPaletteChanged()),
-                                    q, SLOT(colorsChanged()));
+              // check if new theme svg wants colorscheme applied
+              bool wasApplyColors = applyColors;
+              checkApplyColorHint();
+              if (applyColors && !Theme::defaultTheme()->colorScheme()) {
+                  if (!wasApplyColors) {
+                      QObject::connect(KGlobalSettings::self(), \
SIGNAL(kdisplayPaletteChanged()), +                                      q, \
SLOT(colorsChanged())); +                  }
+              } else {
+                  QObject::disconnect(KGlobalSettings::self(), \
SIGNAL(kdisplayPaletteChanged()), +                                      q, \
SLOT(colorsChanged())); +              }
+              localRectCache.clear();
+              itemsToSave.clear();
+              saveTimer->stop();
             }
-
-            localRectCache.clear();
-            itemsToSave.clear();
-            saveTimer->stop();
-
+            //Even trigger a repaint when the theme path has not changed.
+            //It may be other aspects of the theme rendering that changed \
                (Composition type, background color, ...)
             //kDebug() << themePath << ">>>>>>>>>>>>>>>>>> theme changed";
             emit q->repaintNeeded();
         }
--- trunk/KDE/kdelibs/plasma/theme.cpp #961914:961915
@@ -22,6 +22,7 @@
 #include <QApplication>
 #include <QFile>
 #include <QFileInfo>
+#include <QtGui/QPainter>
 #ifdef Q_WS_X11
 #include <QX11Info>
 #endif
@@ -40,6 +41,7 @@
 #include <kwindowsystem.h>
 
 #include "private/packages_p.h"
+#include "framebackgroundprovider.h"
 
 namespace Plasma
 {
@@ -49,6 +51,32 @@
 static const int DEFAULT_WALLPAPER_WIDTH = 1920;
 static const int DEFAULT_WALLPAPER_HEIGHT = 1200;
 
+class StandardThemeBackgroundProvider : public FrameBackgroundProvider {
+  public:
+    StandardThemeBackgroundProvider();
+    virtual void apply(QPainter& target, QPoint offset);
+    virtual QString identity();
+    QColor m_color;
+    QString m_pattern;
+    int m_patternAlpha;
+    int m_offsetX;
+    int m_offsetY;
+
+    void clearCache() {
+      m_cachedPatterns.clear();
+    }
+
+  private:
+    //Maps file-name to (image, alpha)
+    typedef QPair<QImage, uint> PatternAlphaPair; //The alpha value is statically \
applied to the pattern +    QMap<QString, PatternAlphaPair > m_cachedPatterns;
+};
+
+static StandardThemeBackgroundProvider& standardThemeBackgroundProvider() {
+    static StandardThemeBackgroundProvider ret;
+    return ret;
+}
+
 class ThemePrivate
 {
 public:
@@ -82,6 +110,10 @@
         return KConfigGroup(KSharedConfig::openConfig(themeRcFile), \
"CachePolicies");  }
 
+    const KConfigGroup& config() const {
+      return const_cast<ThemePrivate*>(this)->config();
+    }
+
     KConfigGroup &config()
     {
         if (!cfg.isValid()) {
@@ -102,6 +134,28 @@
         return cfg;
     }
 
+    /**
+     *  Reads optional configuration, that is specific to the current composite \
mode: +     *  When composition is active, the configuration entry is prefixed with \
"composite_". +     *  Optionally, the configuration can also be specific to the \
specified image path: +     *  Then the image path has to be appended to the \
configuration name +     */
+    template<class T>
+    T readOptionalConfig(QString configName, T _default, QString imagePath) {
+      if(compositingActive)
+          configName = "composite_" + configName;
+
+      T ret = config().readEntry(configName, _default);
+      return config().readEntry(configName + "_" + imagePath, ret);
+    }
+
+    bool hasOptionalConfig(QString configName, QString imagePath = QString()) {
+      if(compositingActive)
+          configName = "composite_" + configName;
+
+      return config().hasKey(configName) || config().hasKey(configName + "_" + \
imagePath); +    }
+
     QString findInTheme(const QString &image, const QString &theme) const;
     void compositingChanged();
     void discardCache();
@@ -164,7 +218,7 @@
     if (locolor) {
         search = "desktoptheme/" + theme + "/locolor/" + image;
         search =  KStandardDirs::locate("data", search);
-    } else if (!compositingActive) {
+    } else if (!compositingActive && \
!config().readEntry<bool>("forceTransparentTheme", false)) {  search = \
"desktoptheme/" + theme + "/opaque/" + image;  search =  \
KStandardDirs::locate("data", search);  }
@@ -292,13 +346,26 @@
 void ThemePrivate::settingsFileChanged(const QString &file)
 {
     kDebug() << file;
+    QMap< QString, QString > oldEntries = config().entryMap();
+    
     config().config()->reparseConfiguration();
-    q->settingsChanged();
+    
+    if(oldEntries != config().entryMap())
+      q->settingsChanged();
 }
 
 void Theme::settingsChanged()
 {
-    d->setThemeName(d->config().readEntry("name", ThemePrivate::defaultTheme), \
false); +     standardThemeBackgroundProvider().clearCache(); //So we don't waste \
memory with background images that are not used +
+     QString newThemeName = d->config().readEntry("name", \
ThemePrivate::defaultTheme); +     if(newThemeName != d->themeName) {
+      d->setThemeName(newThemeName, false);
+     }else{
+      ///@todo More precise monitoring of attributes
+      d->discardCache(true);
+      emit themeChanged();
+     }
 }
 
 void Theme::setThemeName(const QString &themeName)
@@ -697,6 +764,86 @@
     }
 }
 
+StandardThemeBackgroundProvider::StandardThemeBackgroundProvider() : \
m_color(Qt::black), m_patternAlpha(0) {  }
 
+void StandardThemeBackgroundProvider::apply(QPainter& target, QPoint offset) {
+    target.setCompositionMode(QPainter::CompositionMode_DestinationOver);
+
+    //Apply color
+    if(m_color.alpha())
+        target.fillRect(target.clipRegion().boundingRect(), m_color);
+
+    //Apply pattern
+    if(m_patternAlpha && !m_pattern.isEmpty()) {
+        if(!m_cachedPatterns.contains(m_pattern) || \
m_cachedPatterns[m_pattern].second != m_patternAlpha) { +            \
m_cachedPatterns.remove(m_pattern); +            m_cachedPatterns.insert(m_pattern, \
PatternAlphaPair(QImage(m_pattern), m_patternAlpha)); +            if(m_patternAlpha \
!= 255) { +                PatternAlphaPair& cached(m_cachedPatterns[m_pattern]);
+                //Apply lower alpha value to the pattern
+                QImage alpha(cached.first.size(), QImage::Format_ARGB32);
+                alpha.fill(QColor(cached.second, cached.second, \
cached.second).rgb()); +                cached.first.setAlphaChannel(alpha);
+            }
+        }
+
+        PatternAlphaPair& cached(m_cachedPatterns[m_pattern]);
+
+        if(!cached.first.isNull()) {
+            QBrush brush;
+            QColor col(Qt::white);
+            col.setAlpha(m_patternAlpha);
+            brush.setColor(col);
+            brush.setTextureImage(cached.first);
+            target.setBrushOrigin(-(m_offsetX + offset.x()), -(m_offsetY + \
offset.y())); +            target.fillRect(target.clipRegion().boundingRect(), \
brush); +        }else{
+            kDebug() << "failed to load pattern" << m_pattern;
+        }
+    }
+}
+
+QString StandardThemeBackgroundProvider::identity() {
+    return QString("bgcolor_%1=").arg(m_color.alpha()) + \
m_color.name()+QString("_pattern_%1=").arg(m_patternAlpha)+m_pattern + \
QString("_offsets_%1_%2__").arg(m_offsetX).arg(m_offsetY); +}
+
+FrameBackgroundProvider* Theme::frameBackgroundProvider(QString imagePath) const {
+    if(d->locolor)
+        return 0;
+
+    if((imagePath.startsWith("widgets/panel-") || imagePath.startsWith("dialogs/")) \
&& +       (d->hasOptionalConfig("frameBackgroundColor") || \
d->hasOptionalConfig("frameBackgroundPattern"))) +    {
+        StandardThemeBackgroundProvider& \
provider(standardThemeBackgroundProvider());; +      
+        provider.m_color = d->readOptionalConfig<QColor>("frameBackgroundColor", \
Qt::black, imagePath); +        if(d->hasOptionalConfig("frameBackgroundColor"))
+            provider.m_color.setAlpha(d->readOptionalConfig<int>("frameBackgroundColorAlpha", \
255, imagePath)); +        else
+            provider.m_color.setAlpha(0);
+
+        provider.m_pattern = \
d->readOptionalConfig<QString>("frameBackgroundPattern", QString(), imagePath); +     \
provider.m_patternAlpha = d->readOptionalConfig<int>("frameBackgroundPatternAlpha", \
255, imagePath); +        provider.m_offsetX = \
d->readOptionalConfig<int>("frameBackgroundPatternOffsetX", 0, imagePath); +        \
provider.m_offsetY = d->readOptionalConfig<int>("frameBackgroundPatternOffsetY", 0, \
imagePath); +        int randomX = \
d->readOptionalConfig<int>("frameBackgroundPatternOffsetRandomX", 0, imagePath); +    \
int randomY = d->readOptionalConfig<int>("frameBackgroundPatternOffsetRandomY", 0, \
imagePath); +
+        if(randomX || randomY) {
+            //Add "this" so the offsets are different after every startup, but stay \
same for the same image path +            qsrand(qHash(imagePath) + ((size_t)this) + \
randomX + 11 * randomY); +            if(randomX)
+                provider.m_offsetX += qrand() % randomX;
+            if(randomY)
+                provider.m_offsetY += qrand() % randomY;
+        }
+
+        return &provider;
+    }else
+        return 0;
+}
+
+}
+
 #include <theme.moc>
--- trunk/KDE/kdelibs/plasma/theme.h #961914:961915
@@ -31,7 +31,7 @@
 
 namespace Plasma
 {
-
+class FrameBackgroundProvider;
 class ThemePrivate;
 
 /**
@@ -265,6 +265,18 @@
          */
         void releaseRectsCache(const QString &image);
 
+        /**
+         * Returns a frame background provider, that allows intelligently filling \
the +         * background of the frame represented by the given image.
+         *
+         * The ownership stays with the theme object, and the background provider
+         * is only for immediate usage.
+         *
+         * @param imagePath image path identifying the frame
+         * @return the backgrond-provider or zero, depending on the image, settings, \
and composition mode +         */
+        FrameBackgroundProvider* frameBackgroundProvider(QString imagePath) const;
+
     Q_SIGNALS:
         /**
          * Emitted when the user changes the theme. SVGs should be reloaded at


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic