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>
28 #include <QSignalMapper>
30 KdmPixmap::KdmPixmap( QObject
*parent
, const QDomNode
&node
)
31 : KdmItem( parent
, node
)
38 // Set default values for pixmap (note: strings are already Null)
39 pixmap
.normal
.tint
.setRgb( 0xFFFFFF );
40 pixmap
.normal
.present
= true;
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
);
65 KdmPixmap::definePixmap( const QDomElement
&el
, PixmapStruct::PixmapClass
&pClass
)
67 QString fileName
= el
.attribute( "file" );
68 if (fileName
.isEmpty())
71 pClass
.fullpath
= fileName
;
72 if (fileName
.at( 0 ) != '/')
73 pClass
.fullpath
= themer()->baseDir() + '/' + fileName
;
75 pClass
.svgImage
= fileName
.endsWith( ".svg" ) || fileName
.endsWith( ".svgz" );
77 pClass
.svgElement
= el
.attribute( "element" );
81 KdmPixmap::loadPixmap( PixmapStruct::PixmapClass
&pClass
)
83 if (!pClass
.image
.isNull())
85 if (pClass
.fullpath
.isEmpty())
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
) ) ))
95 if (!pClass
.image
.load( pClass
.fullpath
)) {
96 kWarning() << "failed to load " << pClass
.fullpath
;
97 pClass
.fullpath
.clear();
101 if (pClass
.image
.format() != QImage::Format_ARGB32
)
102 pClass
.image
= pClass
.image
.convertToFormat( QImage::Format_ARGB32
);
103 applyTint( pClass
, pClass
.image
);
108 KdmPixmap::loadSvg( PixmapStruct::PixmapClass
&pClass
)
110 if (pClass
.svgRenderer
)
112 if (pClass
.fullpath
.isEmpty())
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();
122 if (pClass
.svgRenderer
->animated()) {
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();
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();
144 if (loadSvg( pixmap
.normal
))
145 return pixmap
.normal
.svgSizeHint
;
147 return KdmItem::sizeHint();
151 KdmPixmap::updateSize( PixmapStruct::PixmapClass
&pClass
)
153 if (pClass
.readyPixmap
.size() != area
.size())
154 pClass
.readyPixmap
= QPixmap();
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
);
168 KdmPixmap::drawContents( QPainter
*p
, const QRect
&r
)
170 PixmapStruct::PixmapClass
&pClass
= getCurClass();
172 if (pClass
.readyPixmap
.isNull()) {
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
);
183 pClass
.svgRenderer
->render( &pa
, pClass
.svgElement
);
184 applyTint( pClass
, scaledImage
);
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
);
193 scaledImage
= pClass
.image
;
196 if (scaledImage
.isNull()) {
197 p
->fillRect( r
, Qt::black
);
201 pClass
.readyPixmap
= QPixmap::fromImage( scaledImage
);
203 p
->drawPixmap( r
.topLeft(), pClass
.readyPixmap
, QRect( r
.topLeft() - area
.topLeft(), r
.size() ) );
207 KdmPixmap::applyTint( PixmapStruct::PixmapClass
&pClass
, QImage
&img
)
209 if (pClass
.tint
.rgba() == 0xFFFFFFFF)
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
) {
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
)
236 (sts
== Sprelight
&& pixmap
.prelight
.present
) ?
238 (sts
== Sactive
&& pixmap
.active
.present
) ?
244 KdmPixmap::slotAnimate( int sts
)
246 PixmapStruct::PixmapClass
&pClass
= getClass( ItemState(sts
) );
247 pClass
.readyPixmap
= QPixmap();
248 if (&pClass
== &getCurClass())
253 KdmPixmap::statusChanged( bool descend
)
255 KdmItem::statusChanged( descend
);
256 if (!pixmap
.active
.present
&& !pixmap
.prelight
.present
)
258 if ((state
== Sprelight
&& !pixmap
.prelight
.present
) ||
259 (state
== Sactive
&& !pixmap
.active
.present
))
264 #include "kdmpixmap.moc"