source: trunk/src/svg/qgraphicssvgitem.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 11.8 KB
RevLine 
[2]1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
[561]4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
[2]6**
7** This file is part of the QtSvg module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
[561]24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
[2]27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
[561]36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
[2]38** $QT_END_LICENSE$
39**
40****************************************************************************/
41#include "qgraphicssvgitem.h"
42
43#ifndef QT_NO_GRAPHICSSVGITEM
44
45#include "qpainter.h"
46#include "qstyleoption.h"
47#include "qsvgrenderer.h"
48#include "qdebug.h"
49
50#include "private/qobject_p.h"
51#include "private/qgraphicsitem_p.h"
52
53QT_BEGIN_NAMESPACE
54
[561]55class QGraphicsSvgItemPrivate : public QGraphicsItemPrivate
[2]56{
57public:
58 Q_DECLARE_PUBLIC(QGraphicsSvgItem)
59
60 QGraphicsSvgItemPrivate()
61 : renderer(0), shared(false)
62 {
63 }
64
[561]65 void init(QGraphicsItem *parent)
[2]66 {
67 Q_Q(QGraphicsSvgItem);
[561]68 q->setParentItem(parent);
[2]69 renderer = new QSvgRenderer(q);
70 QObject::connect(renderer, SIGNAL(repaintNeeded()),
71 q, SLOT(_q_repaintItem()));
72 q->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
73 q->setMaximumCacheSize(QSize(1024, 768));
74 }
75
76 void _q_repaintItem()
77 {
78 q_func()->update();
79 }
80
81 inline void updateDefaultSize()
82 {
83 QRectF bounds;
84 if (elemId.isEmpty()) {
85 bounds = QRectF(QPointF(0, 0), renderer->defaultSize());
86 } else {
87 bounds = renderer->boundsOnElement(elemId);
88 }
89 if (boundingRect.size() != bounds.size()) {
90 q_func()->prepareGeometryChange();
91 boundingRect.setSize(bounds.size());
92 }
93 }
94
95 QSvgRenderer *renderer;
96 QRectF boundingRect;
97 bool shared;
98 QString elemId;
99};
100
101/*!
102 \class QGraphicsSvgItem
103 \ingroup graphicsview-api
104 \brief The QGraphicsSvgItem class is a QGraphicsItem that can be used to render
105 the contents of SVG files.
106
107 \since 4.2
108
109 QGraphicsSvgItem provides a way of rendering SVG files onto QGraphicsView.
110 QGraphicsSvgItem can be created by passing the SVG file to be rendered to
111 its constructor or by explicit setting a shared QSvgRenderer on it.
112
113 Note that setting QSvgRenderer on a QGraphicsSvgItem doesn't make the item take
114 ownership of the renderer, therefore if using setSharedRenderer() method one has
115 to make sure that the lifetime of the QSvgRenderer object will be at least as long
116 as that of the QGraphicsSvgItem.
117
118 QGraphicsSvgItem provides a way of rendering only parts of the SVG files via
119 the setElementId. If setElementId() method is called, only the SVG element
120 (and its children) with the passed id will be renderer. This provides a convenient
121 way of selectively rendering large SVG files that contain a number of discrete
122 elements. For example the following code renders only jokers from a SVG file
123 containing a whole card deck:
124
125 \snippet doc/src/snippets/code/src_svg_qgraphicssvgitem.cpp 0
126
127 Size of the item can be set via the setSize() method or via
128 direct manipulation of the items transformation matrix.
129
130 By default the SVG rendering is cached using QGraphicsItem::DeviceCoordinateCache
131 mode to speedup the display of items. Caching can be disabled by passing
132 QGraphicsItem::NoCache to the QGraphicsItem::setCacheMode() method.
133
134 \sa QSvgWidget, {QtSvg Module}, QGraphicsItem, QGraphicsView
135*/
136
137/*!
138 Constructs a new SVG item with the given \a parent.
139*/
140QGraphicsSvgItem::QGraphicsSvgItem(QGraphicsItem *parent)
[561]141 : QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0, 0)
[2]142{
143 Q_D(QGraphicsSvgItem);
[561]144 d->init(parent);
[2]145}
146
147/*!
148 Constructs a new item with the given \a parent and loads the contents of the
149 SVG file with the specified \a fileName.
150*/
151QGraphicsSvgItem::QGraphicsSvgItem(const QString &fileName, QGraphicsItem *parent)
[561]152 : QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0, 0)
[2]153{
154 Q_D(QGraphicsSvgItem);
[561]155 d->init(parent);
[2]156 d->renderer->load(fileName);
157 d->updateDefaultSize();
158}
159
160/*!
161 Returns the currently use QSvgRenderer.
162*/
163QSvgRenderer *QGraphicsSvgItem::renderer() const
164{
165 return d_func()->renderer;
166}
167
168
169/*!
170 Returns the bounding rectangle of this item.
171*/
172QRectF QGraphicsSvgItem::boundingRect() const
173{
174 Q_D(const QGraphicsSvgItem);
175 return d->boundingRect;
176}
177
178/*!
179 \internal
180
181 Highlights \a item as selected.
182
183 NOTE: This function is a duplicate of qt_graphicsItem_highlightSelected() in qgraphicsitem.cpp!
184*/
185static void qt_graphicsItem_highlightSelected(
186 QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
187{
188 const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
[561]189 if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
[2]190 return;
191
192 const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
193 if (qMin(mbrect.width(), mbrect.height()) < qreal(1.0))
194 return;
195
196 qreal itemPenWidth;
197 switch (item->type()) {
198 case QGraphicsEllipseItem::Type:
199 itemPenWidth = static_cast<QGraphicsEllipseItem *>(item)->pen().widthF();
200 break;
201 case QGraphicsPathItem::Type:
202 itemPenWidth = static_cast<QGraphicsPathItem *>(item)->pen().widthF();
203 break;
204 case QGraphicsPolygonItem::Type:
205 itemPenWidth = static_cast<QGraphicsPolygonItem *>(item)->pen().widthF();
206 break;
207 case QGraphicsRectItem::Type:
208 itemPenWidth = static_cast<QGraphicsRectItem *>(item)->pen().widthF();
209 break;
210 case QGraphicsSimpleTextItem::Type:
211 itemPenWidth = static_cast<QGraphicsSimpleTextItem *>(item)->pen().widthF();
212 break;
213 case QGraphicsLineItem::Type:
214 itemPenWidth = static_cast<QGraphicsLineItem *>(item)->pen().widthF();
215 break;
216 default:
217 itemPenWidth = 1.0;
218 }
219 const qreal pad = itemPenWidth / 2;
220
221 const qreal penWidth = 0; // cosmetic pen
222
223 const QColor fgcolor = option->palette.windowText().color();
224 const QColor bgcolor( // ensure good contrast against fgcolor
225 fgcolor.red() > 127 ? 0 : 255,
226 fgcolor.green() > 127 ? 0 : 255,
227 fgcolor.blue() > 127 ? 0 : 255);
228
229 painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine));
230 painter->setBrush(Qt::NoBrush);
231 painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
232
233 painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
234 painter->setBrush(Qt::NoBrush);
235 painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
236}
237
238/*!
239 \reimp
240*/
241void QGraphicsSvgItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
242 QWidget *widget)
243{
244// Q_UNUSED(option);
245 Q_UNUSED(widget);
246
247 Q_D(QGraphicsSvgItem);
248 if (!d->renderer->isValid())
249 return;
250
251 if (d->elemId.isEmpty())
252 d->renderer->render(painter, d->boundingRect);
253 else
254 d->renderer->render(painter, d->elemId, d->boundingRect);
255
256 if (option->state & QStyle::State_Selected)
257 qt_graphicsItem_highlightSelected(this, painter, option);
258}
259
260/*!
261 \reimp
262*/
263int QGraphicsSvgItem::type() const
264{
265 return Type;
266}
267
[561]268/*!
269 \property QGraphicsSvgItem::maximumCacheSize
[2]270
[561]271 This property holds the maximum size of the device coordinate cache
272 for this item.
273 */
274
[2]275/*!
276 Sets the maximum device coordinate cache size of the item to \a size.
277 If the item is cached using QGraphicsItem::DeviceCoordinateCache mode,
278 caching is bypassed if the extension of the item in device coordinates
279 is larger than \a size.
280
281 The cache corresponds to the QPixmap which is used to cache the
282 results of the rendering.
283 Use QPixmapCache::setCacheLimit() to set limitations on the whole cache
284 and use setMaximumCacheSize() when setting cache size for individual
285 items.
286
287 \sa QGraphicsItem::cacheMode()
288*/
289void QGraphicsSvgItem::setMaximumCacheSize(const QSize &size)
290{
291 QGraphicsItem::d_ptr->setExtra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize, size);
292 update();
293}
294
295/*!
296 Returns the current maximum size of the device coordinate cache for this item.
297 If the item is cached using QGraphicsItem::DeviceCoordinateCache mode,
298 caching is bypassed if the extension of the item in device coordinates
299 is larger than the maximum size.
300
301 The default maximum cache size is 1024x768.
302 QPixmapCache::cacheLimit() gives the
303 cumulative bounds of the whole cache, whereas maximumCacheSize() refers
304 to a maximum cache size for this particular item.
305
306 \sa QGraphicsItem::cacheMode()
307*/
308QSize QGraphicsSvgItem::maximumCacheSize() const
309{
310 return QGraphicsItem::d_ptr->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize();
311}
312
313/*!
[561]314 \property QGraphicsSvgItem::elementId
315
316 This property holds the element's XML ID.
317 */
318
319/*!
320 Sets the XML ID of the element to \a id.
[2]321*/
322void QGraphicsSvgItem::setElementId(const QString &id)
323{
324 Q_D(QGraphicsSvgItem);
325 d->elemId = id;
326 d->updateDefaultSize();
327 update();
328}
329
330/*!
331 Returns the XML ID the element that is currently
[561]332 being rendered. Returns an empty string if the whole
[2]333 file is being rendered.
334*/
335QString QGraphicsSvgItem::elementId() const
336{
337 Q_D(const QGraphicsSvgItem);
338 return d->elemId;
339}
340
341/*!
342 Sets \a renderer to be a shared QSvgRenderer on the item. By
343 using this method one can share the same QSvgRenderer on a number
344 of items. This means that the SVG file will be parsed only once.
345 QSvgRenderer passed to this method has to exist for as long as
346 this item is used.
347*/
348void QGraphicsSvgItem::setSharedRenderer(QSvgRenderer *renderer)
349{
350 Q_D(QGraphicsSvgItem);
351 if (!d->shared)
352 delete d->renderer;
353
354 d->renderer = renderer;
355 d->shared = true;
356
357 d->updateDefaultSize();
358
359 update();
360}
361
362/*!
363 \obsolete
364
365 Use QGraphicsItem::setCacheMode() instead. Passing true to this function is equivalent
366 to QGraphicsItem::setCacheMode(QGraphicsItem::DeviceCoordinateCache).
367*/
368void QGraphicsSvgItem::setCachingEnabled(bool caching)
369{
370 setCacheMode(caching ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache);
371}
372
373/*!
374 \obsolete
375
376 Use QGraphicsItem::cacheMode() instead.
377*/
378bool QGraphicsSvgItem::isCachingEnabled() const
379{
380 return cacheMode() != QGraphicsItem::NoCache;
381}
382
383QT_END_NAMESPACE
384
385#include "moc_qgraphicssvgitem.cpp"
386
387#endif // QT_NO_GRAPHICSSVGITEM
Note: See TracBrowser for help on using the repository browser.