Achieve the additional background painting without adding any public API

svn path=/trunk/KDE/kdelibs/; revision=962014
This commit is contained in:
David Nolden 2009-05-01 12:17:04 +00:00
parent 0b5c4e1947
commit 42172d0178
6 changed files with 98 additions and 133 deletions

View File

@ -72,7 +72,6 @@ set(plasma_LIB_SRCS
framesvg.cpp
plasma.cpp
popupapplet.cpp
framebackgroundprovider.cpp
private/applethandle.cpp
private/datacontainer_p.cpp
private/desktoptoolbox.cpp
@ -224,7 +223,6 @@ set(plasma_LIB_INCLUDES
servicejob.h
svg.h
theme.h
framebackgroundprovider.h
tooltipcontent.h
tooltipmanager.h
tooltipmanager.h

View File

@ -1,27 +0,0 @@
/*
* Copyright 2009 David Nolden <david.nolden.kdevelop@art-master.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "framebackgroundprovider.h"
namespace Plasma {
FrameBackgroundProvider::~FrameBackgroundProvider() {
}
}

View File

@ -32,7 +32,7 @@
#include <plasma/theme.h>
#include <plasma/applet.h>
#include "framebackgroundprovider.h"
#include "private/framebackgroundprovider.h"
namespace Plasma
{
@ -388,12 +388,11 @@ void FrameSvg::paintFrame(QPainter *painter, const QPointF &pos)
QString FrameSvgPrivate::cacheId(const FrameData* frame) const
{
Theme *theme = Theme::defaultTheme();
FrameBackgroundProvider* backgroundProvider = theme->frameBackgroundProvider(q->imagePath());
StandardThemeBackgroundProvider backgroundProvider(theme, 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());
.arg(q->imagePath()).arg(backgroundProvider.identity());
}
void FrameSvgPrivate::generateBackground(FrameData *frame)
@ -612,9 +611,10 @@ void FrameSvgPrivate::generateBackground(FrameData *frame)
}
if(!prefix.startsWith("mask-")) {
if(FrameBackgroundProvider* backgroundProvider = theme->frameBackgroundProvider(q->imagePath())) {
StandardThemeBackgroundProvider backgroundProvider(theme, q->imagePath());
if(backgroundProvider) {
p.setClipRegion(q->mask() );
backgroundProvider->apply(p);
backgroundProvider.apply(p);
}
}

View File

@ -20,27 +20,20 @@
#ifndef PLASMA_PANELBACKGROUNDPROVIDER_H
#define PLASMA_PANELBACKGROUNDPROVIDER_H
#include <plasma/plasma_export.h>
#include <QtCore/QPoint>
class QPainter;
class QRegion;
namespace Plasma {
class Theme;
/**
* Abstract class to provide additional panel backgrounds behind translucent panels.
* A class that paints an additional background behind specific elements of a theme.
* Construct it locally right before using it.
*/
class PLASMA_EXPORT FrameBackgroundProvider
{
public:
virtual ~FrameBackgroundProvider();
class StandardThemeBackgroundProvider {
public:
/**
* Returns an identity that can be used for caching the result of the background rendering.
* @return The identity string
* Constructs a background-provider for the given theme
*/
virtual QString identity() = 0;
StandardThemeBackgroundProvider(Theme* theme, QString imagePath);
/**
* Applies the background to the given target. The target must have correct alpha-values,
* so the background can be painted under it. Also the clip-region must be already set correctly
@ -48,9 +41,33 @@ public:
* @param target The target where the background should be painted
* @param offset Additional offset for the rendering: The render-source is translated by this offset
*/
virtual void apply(QPainter& target, QPoint offset = QPoint()) = 0;
void apply(QPainter& target) const;
/**
* Returns an identity that can be used for caching the result of the background rendering.
* @return The identity string
*/
QString identity() const;
static void clearCache();
/**
* Returns true if this background-provider will paint something
*/
operator bool() const;
private:
QColor m_color;
QString m_pattern;
int m_patternAlpha;
int m_offsetX;
int m_offsetY;
bool m_valid;
//Maps file-name to (image, alpha)
typedef QPair<QImage, int> PatternAlphaPair; //The alpha value is statically applied to the pattern
static QMap<QString, PatternAlphaPair > m_cachedPatterns;
};
}
#endif // PLASMA_PANELBACKGROUNDPROVIDER_H
#endif

124
theme.cpp
View File

@ -41,7 +41,7 @@
#include <kwindowsystem.h>
#include "private/packages_p.h"
#include "framebackgroundprovider.h"
#include "private/framebackgroundprovider.h"
namespace Plasma
{
@ -51,31 +51,7 @@ namespace Plasma
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;
}
QMap<QString, StandardThemeBackgroundProvider::PatternAlphaPair> StandardThemeBackgroundProvider::m_cachedPatterns;
class ThemePrivate
{
@ -356,7 +332,7 @@ void ThemePrivate::settingsFileChanged(const QString &file)
void Theme::settingsChanged()
{
standardThemeBackgroundProvider().clearCache(); //So we don't waste memory with background images that are not used
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) {
@ -764,10 +740,51 @@ void Theme::setCacheLimit(int kbytes)
}
}
StandardThemeBackgroundProvider::StandardThemeBackgroundProvider() : m_color(Qt::black), m_patternAlpha(0) {
void StandardThemeBackgroundProvider::clearCache()
{
m_cachedPatterns.clear();
}
void StandardThemeBackgroundProvider::apply(QPainter& target, QPoint offset) {
StandardThemeBackgroundProvider::StandardThemeBackgroundProvider(Theme* theme, QString imagePath) : m_color(Qt::black), m_patternAlpha(0), m_valid(false)
{
if(theme->d->locolor)
return;
if((imagePath.startsWith("widgets/panel-") || imagePath.startsWith("dialogs/")) &&
(theme->d->hasOptionalConfig("frameBackgroundColor") || theme->d->hasOptionalConfig("frameBackgroundPattern")))
{
m_valid = true;
m_color = theme->d->readOptionalConfig<QColor>("frameBackgroundColor", Qt::black, imagePath);
if(theme->d->hasOptionalConfig("frameBackgroundColor"))
m_color.setAlpha(theme->d->readOptionalConfig<int>("frameBackgroundColorAlpha", 255, imagePath));
else
m_color.setAlpha(0);
m_pattern = theme->d->readOptionalConfig<QString>("frameBackgroundPattern", QString(), imagePath);
m_patternAlpha = theme->d->readOptionalConfig<int>("frameBackgroundPatternAlpha", 255, imagePath);
m_offsetX = theme->d->readOptionalConfig<int>("frameBackgroundPatternOffsetX", 0, imagePath);
m_offsetY = theme->d->readOptionalConfig<int>("frameBackgroundPatternOffsetY", 0, imagePath);
int randomX = theme->d->readOptionalConfig<int>("frameBackgroundPatternOffsetRandomX", 0, imagePath);
int randomY = theme->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)
m_offsetX += qrand() % randomX;
if(randomY)
m_offsetY += qrand() % randomY;
}
}
}
void StandardThemeBackgroundProvider::apply(QPainter& target) const
{
if(!m_valid)
return;
target.setCompositionMode(QPainter::CompositionMode_DestinationOver);
//Apply color
@ -796,7 +813,7 @@ void StandardThemeBackgroundProvider::apply(QPainter& target, QPoint offset) {
col.setAlpha(m_patternAlpha);
brush.setColor(col);
brush.setTextureImage(cached.first);
target.setBrushOrigin(-(m_offsetX + offset.x()), -(m_offsetY + offset.y()));
target.setBrushOrigin(-m_offsetX, -m_offsetY);
target.fillRect(target.clipRegion().boundingRect(), brush);
}else{
kDebug() << "failed to load pattern" << m_pattern;
@ -804,46 +821,17 @@ void StandardThemeBackgroundProvider::apply(QPainter& target, QPoint offset) {
}
}
QString StandardThemeBackgroundProvider::identity() {
StandardThemeBackgroundProvider::operator bool() const
{
return m_valid;
}
QString StandardThemeBackgroundProvider::identity() const
{
if(!m_valid)
return QString();
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>

15
theme.h
View File

@ -31,7 +31,7 @@
namespace Plasma
{
class FrameBackgroundProvider;
class StandardThemeBackgroundProvider;
class ThemePrivate;
/**
@ -265,18 +265,6 @@ class PLASMA_EXPORT Theme : public QObject
*/
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
@ -294,6 +282,7 @@ class PLASMA_EXPORT Theme : public QObject
private:
friend class ThemeSingleton;
friend class ThemePrivate;
friend class StandardThemeBackgroundProvider;
ThemePrivate *const d;
Q_PRIVATE_SLOT(d, void compositingChanged())