[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