Plasma::Svg debuts. it is an image centric wrapper around QSvgRenderer that takes care of things such as:

* caching rendered pixmaps
* looking up the images from the Plasma::Theme
* scheduling needed updates, e.g. when the plasma theme changes


svn path=/trunk/KDE/kdebase/workspace/plasma/lib/; revision=640418
This commit is contained in:
Aaron J. Seigo 2007-03-07 23:27:37 +00:00
parent bfe37da902
commit 5cfabdc869
5 changed files with 305 additions and 4 deletions

View File

@ -7,6 +7,7 @@ set(plasma_LIB_SRCS
applet.cpp
interface.cpp
runner.cpp
svg.cpp
theme.cpp
dataengine.cpp
datavisualization.cpp

171
svg.cpp Normal file
View File

@ -0,0 +1,171 @@
/*
* Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* 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 <QMatrix>
#include <QPainter>
#include <QPixmapCache>
#include <QSvgRenderer>
#include <KDebug>
#include "svg.h"
#include "theme.h"
namespace Plasma
{
class Svg::Private
{
public:
Private( const QString& image )
: renderer( 0 ),
themePath( image )
{
}
~Private()
{
delete renderer;
}
void removeFromCache()
{
if ( id.isEmpty() ) {
return;
}
QPixmapCache::remove( id );
id.clear();
}
void findInCache( QPainter* painter, QPixmap& p )
{
if ( path.isNull() ) {
path = Plasma::Theme::self()->image( themePath );
if ( path.isNull() ) {
// bad theme path
return;
}
}
QMatrix matrix = painter->worldMatrix();
//TODO: if the id changes, should we remove it or just let QPixmapCache do that for us?
id = QString::fromLatin1( "%7_%1_%2_%3_%4_%5_%6" )
.arg( size.width() )
.arg( size.height() )
.arg( matrix.m11() )
.arg( matrix.m12() )
.arg( matrix.m21() )
.arg( matrix.m22() )
.arg( themePath );
if ( QPixmapCache::find( id, p ) ) {
kDebug() << "found cached version of " << id << endl;
return;
} else {
kDebug() << "didn't find cached version of " << id << ", so re-rendering" << endl;
}
// we have to re-render this puppy
if ( ! renderer ) {
//TODO: connect the renderer's repaintNeeded to the Plasma::Svg signal
// take into consideration for cache, e.g. don't cache if svg is animated
renderer = new QSvgRenderer( path );
}
p.resize( size );
p.fill(Qt::transparent);
QPainter renderPainter( &p );
renderPainter.setWorldMatrix( matrix );
renderer->render( &renderPainter, p.rect() );
renderPainter.end();
QPixmapCache::insert( id, p );
}
//TODO: share renderers between Svg objects with identical themePath
QSvgRenderer* renderer;
QString themePath;
QString path;
QString id;
QSize size;
};
Svg::Svg( const QString& imagePath, QObject* parent )
: QObject( parent ),
d( new Private( imagePath ) )
{
connect( Plasma::Theme::self(), SIGNAL(changed()), this, SLOT(themeChanged()) );
}
Svg::~Svg()
{
}
void Svg::paint( QPainter* painter, const QPoint& point )
{
QPixmap pix;
d->findInCache( painter, pix );
QMatrix matrix = painter->worldMatrix();
painter->setWorldMatrix( QMatrix() );
painter->drawPixmap( point, pix );
painter->setWorldMatrix( matrix );
}
void Svg::paint( QPainter* painter, int x, int y )
{
paint( painter, QPoint( x, y ) );
}
void Svg::paint( QPainter* painter, const QRect& rect )
{
QPixmap pix;
d->findInCache( painter, pix );
QMatrix matrix = painter->worldMatrix();
painter->setWorldMatrix( QMatrix() );
painter->drawPixmap( rect, pix );
painter->setWorldMatrix( matrix );
}
void Svg::resize( int width, int height )
{
resize( QSize( width, height ) );
}
void Svg::resize( const QSize& size )
{
d->size = size;
}
void Svg::themeChanged()
{
d->removeFromCache();
d->path.clear();
delete d->renderer;
d->renderer = 0;
emit repaintNeeded();
}
} // Plasma namespace
#include "svg.moc"

104
svg.h Normal file
View File

@ -0,0 +1,104 @@
/*
* Copyright (C) 2006 Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* 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.
*/
#ifndef PLASMA_SVG_H
#define PLASMA_SVG_H
#include <QtCore/QObject>
#include <kdemacros.h>
namespace Plasma
{
class KDE_EXPORT Svg : public QObject
{
Q_OBJECT
public:
/**
* Constructs an SVG object that implicitly shares and caches rendering
* As opposed to QSvgRenderer, which this class uses internally,
* Plasma::Svg represents an image generated from an SVG. As such, it
* has a related size and transform matrix (the latter being provided
* by the painter used to paint the image).
*
* The size is initialized to be the SVG's native size.
*
* @arg imagePath the image to show, used to load the image from
* Plasma::Theme
* @arg parent options QObject to parent this to
*/
explicit Svg( const QString& imagePath, QObject* parent = 0 );
~Svg();
/**
* Paints the SVG represented by this object
* @arg painter the QPainter to use
* @arg point the position to start drawing; the entire svg will be
* drawn starting at this point.
*/
void paint( QPainter* painter, const QPoint& point );
/**
* Paints the SVG represented by this object
* @arg painter the QPainter to use
* @arg x the horizontal coordinate to start painting from
* @arg y the vertical coordinate to start painting from
*/
void paint( QPainter* painter, int x, int y );
/**
* Paints the SVG represented by this object
* @arg painter the QPainter to use
* @arg rect the rect to draw into; if small than the current size
* of the
* drawn starting at this point.
*/
void paint( QPainter* painter, const QRect& rect );
/**
* Resizes the rendered image. Rendering will actually take place on
* the next call to paint.
* @arg width the new width
* @arg height the new height
**/
void resize( int width, int height );
/**
* Resizes the rendered image. Rendering will actually take place on
* the next call to paint.
* @arg size the new size of the image
**/
void resize( const QSize& size );
Q_SIGNALS:
void repaintNeeded();
private Q_SLOTS:
void themeChanged();
private:
class Private;
Private* d;
};
} // Plasma namespace
#endif // multiple inclusion guard

View File

@ -33,9 +33,22 @@ class Theme::Private
{
}
QString themeName;
QString themeName;
};
class ThemeSingleton
{
public:
Theme self;
};
K_GLOBAL_STATIC( ThemeSingleton, privateSelf )
Theme* Theme::self()
{
return &privateSelf->self;
}
Theme::Theme(QObject* parent)
: QObject(parent),
d(new Private)
@ -56,9 +69,16 @@ QString Theme::themeName() const
QString Theme::image( const QString& name ) const
{
return KStandardDirs::locate( "data", "desktoptheme/" +
d->themeName +
"/" + name + ".svg" );
QString search = "desktoptheme/" + d->themeName + "/" + name + ".svg";
QString path = KStandardDirs::locate( "data", search );
if ( path.isEmpty() ) {
kDebug() << "Theme says: bad image path " << name
<< "; looked in: " << search
<< endl;
}
return path;
}
}

View File

@ -31,6 +31,11 @@ class KDE_EXPORT Theme : public QObject
Q_OBJECT
public:
/**
* Singleton pattern accessor
**/
static Theme* self();
explicit Theme( QObject* parent = 0 );
~Theme();