not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kdm / kfrontend / themer / kdmpixmap.cpp
blobdfc849efa0499c292c084f146930a9d43252b4c1
1 /*
2 * Copyright (C) 2003 by Unai Garro <ugarro@users.sourceforge.net>
3 * Copyright (C) 2004 by Enrico Ros <rosenric@dei.unipd.it>
4 * Copyright (C) 2004 by Stephan Kulow <coolo@kde.org>
5 * Copyright (C) 2004 by Oswald Buddenhagen <ossi@kde.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "kdmpixmap.h"
23 #include "kdmthemer.h"
25 #include <ksvgrenderer.h>
27 #include <QPainter>
28 #include <QSignalMapper>
30 KdmPixmap::KdmPixmap( QObject *parent, const QDomNode &node )
31 : KdmItem( parent, node )
32 , qsm( 0 )
34 itemType = "pixmap";
35 if (!isVisible())
36 return;
38 // Set default values for pixmap (note: strings are already Null)
39 pixmap.normal.tint.setRgb( 0xFFFFFF );
40 pixmap.normal.present = true;
42 // Read PIXMAP TAGS
43 QDomNodeList childList = node.childNodes();
44 for (int nod = 0; nod < childList.count(); nod++) {
45 QDomNode child = childList.item( nod );
46 QDomElement el = child.toElement();
47 QString tagName = el.tagName();
49 if (tagName == "normal") {
50 definePixmap( el, pixmap.normal );
51 parseColor( el.attribute( "tint", "#ffffff" ), el.attribute( "alpha", "1.0" ), pixmap.normal.tint );
52 } else if (tagName == "active") {
53 pixmap.active.present = true;
54 definePixmap( el, pixmap.active );
55 parseColor( el.attribute( "tint", "#ffffff" ), el.attribute( "alpha", "1.0" ), pixmap.active.tint );
56 } else if (tagName == "prelight") {
57 pixmap.prelight.present = true;
58 definePixmap( el, pixmap.prelight );
59 parseColor( el.attribute( "tint", "#ffffff" ), el.attribute( "alpha", "1.0" ), pixmap.prelight.tint );
64 void
65 KdmPixmap::definePixmap( const QDomElement &el, PixmapStruct::PixmapClass &pClass )
67 QString fileName = el.attribute( "file" );
68 if (fileName.isEmpty())
69 return;
71 pClass.fullpath = fileName;
72 if (fileName.at( 0 ) != '/')
73 pClass.fullpath = themer()->baseDir() + '/' + fileName;
75 pClass.svgImage = fileName.endsWith( ".svg" ) || fileName.endsWith( ".svgz" );
76 if (pClass.svgImage)
77 pClass.svgElement = el.attribute( "element" );
80 bool
81 KdmPixmap::loadPixmap( PixmapStruct::PixmapClass &pClass )
83 if (!pClass.image.isNull())
84 return true;
85 if (pClass.fullpath.isEmpty())
86 return false;
87 if (area.isValid()) {
88 int dot = pClass.fullpath.lastIndexOf( '.' );
89 if (pClass.image.load( pClass.fullpath.left( dot )
90 .append( QString( "-%1x%2" )
91 .arg( area.width() ).arg( area.height() ) )
92 .append( pClass.fullpath.mid( dot ) ) ))
93 goto gotit;
95 if (!pClass.image.load( pClass.fullpath )) {
96 kWarning() << "failed to load " << pClass.fullpath ;
97 pClass.fullpath.clear();
98 return false;
100 gotit:
101 if (pClass.image.format() != QImage::Format_ARGB32)
102 pClass.image = pClass.image.convertToFormat( QImage::Format_ARGB32 );
103 applyTint( pClass, pClass.image );
104 return true;
107 bool
108 KdmPixmap::loadSvg( PixmapStruct::PixmapClass &pClass )
110 if (pClass.svgRenderer)
111 return true;
112 if (pClass.fullpath.isEmpty())
113 return false;
114 pClass.svgRenderer = new KSvgRenderer( pClass.fullpath, this );
115 if (!pClass.svgRenderer->isValid()) {
116 delete pClass.svgRenderer;
117 pClass.svgRenderer = 0;
118 kWarning() << "failed to load " << pClass.fullpath ;
119 pClass.fullpath.clear();
120 return false;
122 if (pClass.svgRenderer->animated()) {
123 if (!qsm) {
124 qsm = new QSignalMapper( this );
125 connect( qsm, SIGNAL(mapped( int )), SLOT(slotAnimate( int )) );
127 qsm->setMapping( pClass.svgRenderer, state ); // assuming we only load the current state
128 connect( pClass.svgRenderer, SIGNAL(repaintNeeded()), qsm, SLOT(map()) );
130 pClass.svgSizeHint = pClass.svgElement.isEmpty() ?
131 pClass.svgRenderer->defaultSize() :
132 pClass.svgRenderer->boundsOnElement( pClass.svgElement ).size().toSize();
133 return true;
136 QSize
137 KdmPixmap::sizeHint()
139 // use the pixmap size as the size hint
140 if (!pixmap.normal.svgImage) {
141 if (loadPixmap( pixmap.normal ))
142 return pixmap.normal.image.size();
143 } else {
144 if (loadSvg( pixmap.normal ))
145 return pixmap.normal.svgSizeHint;
147 return KdmItem::sizeHint();
150 void
151 KdmPixmap::updateSize( PixmapStruct::PixmapClass &pClass )
153 if (pClass.readyPixmap.size() != area.size())
154 pClass.readyPixmap = QPixmap();
157 void
158 KdmPixmap::setGeometry( QStack<QSize> &parentSizes, const QRect &newGeometry, bool force )
160 KdmItem::setGeometry( parentSizes, newGeometry, force );
161 updateSize( pixmap.active );
162 updateSize( pixmap.prelight );
163 updateSize( pixmap.normal );
167 void
168 KdmPixmap::drawContents( QPainter *p, const QRect &r )
170 PixmapStruct::PixmapClass &pClass = getCurClass();
172 if (pClass.readyPixmap.isNull()) {
173 QImage scaledImage;
175 if (pClass.svgImage) {
176 if (loadSvg( pClass )) {
177 scaledImage = QImage( area.size(), QImage::Format_ARGB32 );
178 scaledImage.fill( 0 );
179 QPainter pa( &scaledImage );
180 if (pClass.svgElement.isEmpty())
181 pClass.svgRenderer->render( &pa );
182 else
183 pClass.svgRenderer->render( &pa, pClass.svgElement );
184 applyTint( pClass, scaledImage );
186 } else {
187 // use the loaded pixmap or a scaled version if needed
188 if (area.size() != pClass.image.size()) { // true for isNull
189 if (loadPixmap( pClass ))
190 scaledImage = pClass.image.scaled( area.size(),
191 Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
192 } else
193 scaledImage = pClass.image;
196 if (scaledImage.isNull()) {
197 p->fillRect( r, Qt::black );
198 return;
201 pClass.readyPixmap = QPixmap::fromImage( scaledImage );
203 p->drawPixmap( r.topLeft(), pClass.readyPixmap, QRect( r.topLeft() - area.topLeft(), r.size() ) );
206 void
207 KdmPixmap::applyTint( PixmapStruct::PixmapClass &pClass, QImage &img )
209 if (pClass.tint.rgba() == 0xFFFFFFFF)
210 return;
212 int w = img.width();
213 int h = img.height();
214 int tint_red = pClass.tint.red();
215 int tint_green = pClass.tint.green();
216 int tint_blue = pClass.tint.blue();
217 int tint_alpha = pClass.tint.alpha();
219 for (int y = 0; y < h; ++y) {
220 QRgb *ls = (QRgb *)img.scanLine( y );
221 for (int x = 0; x < w; ++x) {
222 QRgb l = ls[x];
223 int r = qRed( l ) * tint_red / 255;
224 int g = qGreen( l ) * tint_green / 255;
225 int b = qBlue( l ) * tint_blue / 255;
226 int a = qAlpha( l ) * tint_alpha / 255;
227 ls[x] = qRgba( r, g, b, a );
232 KdmPixmap::PixmapStruct::PixmapClass &
233 KdmPixmap::getClass( ItemState sts )
235 return
236 (sts == Sprelight && pixmap.prelight.present) ?
237 pixmap.prelight :
238 (sts == Sactive && pixmap.active.present) ?
239 pixmap.active :
240 pixmap.normal;
243 void
244 KdmPixmap::slotAnimate( int sts )
246 PixmapStruct::PixmapClass &pClass = getClass( ItemState(sts) );
247 pClass.readyPixmap = QPixmap();
248 if (&pClass == &getCurClass())
249 needUpdate();
252 void
253 KdmPixmap::statusChanged( bool descend )
255 KdmItem::statusChanged( descend );
256 if (!pixmap.active.present && !pixmap.prelight.present)
257 return;
258 if ((state == Sprelight && !pixmap.prelight.present) ||
259 (state == Sactive && !pixmap.active.present))
260 return;
261 needUpdate();
264 #include "kdmpixmap.moc"