Fixes: Use QRect::isEmpty() rather than isNull() if possible.
[qt:android-lighthouse.git] / src / gui / graphicsview / qgraphicsitem.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Qt Software Information (qt-info@nokia.com)
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** No Commercial Usage
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the either Technology Preview License Agreement or the
13 ** Beta Release License Agreement.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file.  Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
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 **
36 ** If you are unsure which license is appropriate for your use, please
37 ** contact the sales department at qt-sales@nokia.com.
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 /*!
43     \class QGraphicsItem
44     \brief The QGraphicsItem class is the base class for all graphical
45     items in a QGraphicsScene.
46     \since 4.2
47     \ingroup multimedia
48     \ingroup graphicsview-api
49
50     It provides a light-weight foundation for writing your own custom items.
51     This includes defining the item's geometry, collision detection, its
52     painting implementation and item interaction through its event handlers.
53     QGraphicsItem is part of \l{The Graphics View Framework}
54
55     \img graphicsview-items.png
56
57     For convenience, Qt provides a set of standard graphics items for the most
58     common shapes. These are:
59
60     \list
61     \o QGraphicsEllipseItem provides an ellipse item
62     \o QGraphicsLineItem provides a line item
63     \o QGraphicsPathItem provides an arbitrary path item
64     \o QGraphicsPixmapItem provides a pixmap item
65     \o QGraphicsPolygonItem provides a polygon item
66     \o QGraphicsRectItem provides a rectangular item
67     \o QGraphicsSimpleTextItem provides a simple text label item
68     \o QGraphicsTextItem provides an advanced text browser item
69     \endlist
70
71     All of an item's geometric information is based on its local coordinate
72     system. The item's position, pos(), is the only function that does not
73     operate in local coordinates, as it returns a position in parent
74     coordinates. \l {The Graphics View Coordinate System} describes the coordinate
75     system in detail.
76
77     You can set whether an item should be visible (i.e., drawn, and accepting
78     events), by calling setVisible(). Hiding an item will also hide its
79     children. Similarly, you can enable or disable an item by calling
80     setEnabled(). If you disable an item, all its children will also be
81     disabled. By default, items are both visible and enabled. To toggle
82     whether an item is selected or not, first enable selection by setting
83     the ItemIsSelectable flag, and then call setSelected(). Normally,
84     selection is toggled by the scene, as a result of user interaction.
85
86     To write your own graphics item, you first create a subclass of
87     QGraphicsItem, and then start by implementing its two pure virtual public
88     functions: boundingRect(), which returns an estimate of the area painted
89     by the item, and paint(), which implements the actual painting. For
90     example:
91
92     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 0
93
94     The boundingRect() function has many different purposes. QGraphicsScene
95     bases its item index on boundingRect(), and QGraphicsView uses it both for
96     culling invisible items, and for determining the area that needs to be
97     recomposed when drawing overlapping items. In addition, QGraphicsItem's
98     collision detection mechanisms use boundingRect() to provide an efficient
99     cut-off. The fine grained collision algorithm in collidesWithItem() is based
100     on calling shape(), which returns an accurate outline of the item's shape
101     as a QPainterPath.
102
103     QGraphicsScene expects all items boundingRect() and shape() to remain
104     unchanged unless it is notified. If you want to change an item's geometry
105     in any way, you must first call prepareGeometryChange() to allow
106     QGraphicsScene to update its bookkeeping.
107
108     Collision detection can be done in two ways:
109
110     \list 1
111
112     \o Reimplement shape() to return an accurate shape for your item, and rely
113     on the default implementation of collidesWithItem() to do shape-shape
114     intersection. This can be rather expensive if the shapes are complex.
115
116     \o Reimplement collidesWithItem() to provide your own custom item and shape
117     collision algorithm.
118
119     \endlist
120
121     The contains() function can be called to determine whether the item \e
122     contains a point or not. This function can also be reimplemented by the
123     item. The default behavior of contains() is based on calling shape().
124
125     Items can contain other items, and also be contained by other items. All
126     items can have a parent item and a list of children. Unless the item has
127     no parent, its position is in \e parent coordinates (i.e., the parent's
128     local coordinates). Parent items propagate both their position and their
129     transformation to all children.
130
131     \img graphicsview-parentchild.png
132
133     QGraphicsItem supports affine transformations in addition to its base
134     position, pos(). To change the item's transformation, you can either pass
135     a transformation matrix to setTransform(), or call one of the convenience
136     functions rotate(), scale(), translate(), or shear(). Item transformations
137     accumulate from parent to child, so if both a parent and child item are
138     rotated 90 degrees, the child's total transformation will be 180 degrees.
139     Similarly, if the item's parent is scaled to 2x its original size, its
140     children will also be twice as large. An item's transformation does not
141     affect its own local geometry; all geometry functions (e.g., contains(),
142     update(), and all the mapping functions) still operate in local
143     coordinates. For convenience, QGraphicsItem provides the functions
144     sceneTransform(), which returns the item's total transformation matrix
145     (including its position and all parents' positions and transformations),
146     and scenePos(), which returns its position in scene coordinates. To reset
147     an item's matrix, call resetTransform().
148
149     The paint() function is called by QGraphicsView to paint the item's
150     contents. The item has no background or default fill of its own; whatever
151     is behind the item will shine through all areas that are not explicitly
152     painted in this function.  You can call update() to schedule a repaint,
153     optionally passing the rectangle that needs a repaint. Depending on
154     whether or not the item is visible in a view, the item may or may not be
155     repainted; there is no equivalent to QWidget::repaint() in QGraphicsItem.
156
157     Items are painted by the view, starting with the parent items and then
158     drawing children, in ascending stacking order. You can set an item's
159     stacking order by calling setZValue(), and test it by calling
160     zValue(), where items with low z-values are painted before items with
161     high z-values. Stacking order applies to sibling items; parents are always
162     drawn before their children.
163
164     QGraphicsItem receives events from QGraphicsScene through the virtual
165     function sceneEvent(). This function distributes the most common events
166     to a set of convenience event handlers:
167
168     \list
169     \o contextMenuEvent() handles context menu events
170     \o focusInEvent() and focusOutEvent() handle focus in and out events
171     \o hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() handles
172     hover enter, move and leave events
173     \o inputMethodEvent() handles input events, for accessibility support
174     \o keyPressEvent() and keyReleaseEvent handle key press and release events
175     \o mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and
176     mouseDoubleClickEvent() handles mouse press, move, release, click and
177     doubleclick events
178     \endlist
179
180     You can filter events for any other item by installing event
181     filters. This functionaly is separate from from Qt's regular
182     event filters (see QObject::installEventFilter()), which only
183     work on subclasses of QObject. After installing your item as an
184     event filter for another item by calling
185     installSceneEventFilter(), the filtered events will be received
186     by the virtual function sceneEventFilter(). You can remove item
187     event filters by calling removeSceneEventFilter().
188
189     Sometimes it's useful to register custom data with an item, be it a custom
190     item, or a standard item. You can call setData() on any item to store data
191     in it using a key-value pair (the key being an integer, and the value is a
192     QVariant). To get custom data from an item, call data(). This
193     functionality is completely untouched by Qt itself; it is provided for the
194     user's convenience.
195
196     \sa QGraphicsScene, QGraphicsView, {The Graphics View Framework}
197 */
198
199 /*!
200     \variable QGraphicsItem::UserType
201
202     The lowest permitted type value for custom items (subclasses
203     of QGraphicsItem or any of the standard items). This value is
204     used in conjunction with a reimplementation of QGraphicsItem::type()
205     and declaring a Type enum value. Example:
206
207     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 1
208 */
209
210 /*!
211     \enum QGraphicsItem::GraphicsItemFlag
212
213     This enum describes different flags that you can set on an item to
214     toggle different features in the item's behavior.
215
216     All flags are disabled by default.
217
218     \value ItemIsMovable The item supports interactive movement using
219     the mouse. By clicking on the item and then dragging, the item
220     will move together with the mouse cursor. If the item has
221     children, all children are also moved. If the item is part of a
222     selection, all selected items are also moved. This feature is
223     provided as a convenience through the base implementation of
224     QGraphicsItem's mouse event handlers.
225
226     \value ItemIsSelectable The item supports selection. Enabling this
227     feature will enable setSelected() to toggle selection for the
228     item. It will also let the item be selected automatically as a
229     result of calling QGraphicsScene::setSelectionArea(), by clicking
230     on an item, or by using rubber band selection in QGraphicsView.
231
232     \value ItemIsFocusable The item supports keyboard input focus (i.e., it is
233     an input item). Enabling this flag will allow the item to accept focus,
234     which again allows the delivery of key events to
235     QGraphicsItem::keyPressEvent() and QGraphicsItem::keyReleaseEvent().
236
237     \value ItemClipsToShape The item clips to its own shape. The item cannot
238     draw or receive mouse, tablet, drag and drop or hover events outside ts
239     shape. It is disabled by default. This behavior is enforced by
240     QGraphicsView::drawItems() or QGraphicsScene::drawItems(). This flag was
241     introduced in Qt 4.3.
242
243     \value ItemClipsChildrenToShape The item clips the painting of all its
244     descendants to its own shape. Items that are either direct or indirect
245     children of this item cannot draw outside this item's shape. By default,
246     this flag is disabled; children can draw anywhere. This behavior is
247     enforced by QGraphicsView::drawItems() or
248     QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3.
249
250     \value ItemIgnoresTransformations The item ignores inherited
251     transformations (i.e., its position is still anchored to its parent, but
252     the parent or view rotation, zoom or shear transformations are ignored).
253     This flag is useful for keeping text label items horizontal and unscaled,
254     so they will still be readable if the view is transformed.  When set, the
255     item's view geometry and scene geometry will be maintained separately. You
256     must call deviceTransform() to map coordinates and detect collisions in
257     the view. By default, this flag is disabled. This flag was introduced in
258     Qt 4.3. \note With this flag set you can still scale the item itself, and
259     that scale transformation will influence the item's children.
260
261     \value ItemIgnoresParentOpacity The item ignores its parent's opacity. The
262     item's effective opacity is the same as its own; it does not combine with
263     the parent's opacity. This flags allows your item to keep its absolute
264     opacity even if the parent is semitransparent. This flag was introduced in
265     Qt 4.5.
266
267     \value ItemDoesntPropagateOpacityToChildren The item doesn't propagate its
268     opacity to its children. This flag allows you to create a semitransparent
269     item that does not affect the opacity of its children. This flag was
270     introduced in Qt 4.5.
271
272     \value ItemStacksBehindParent The item is stacked behind its parent. By
273     default, child items are stacked on top of the parent item. But setting
274     this flag, the child will be stacked behind it. This flag is useful for
275     drop shadow effects and for decoration objects that follow the parent
276     item's geometry without drawing on top of it.
277 */
278
279 /*!
280     \enum QGraphicsItem::GraphicsItemChange
281
282         ItemVisibleHasChanged,
283         ItemEnabledHasChanged,
284         ItemSelectedHasChanged,
285         ItemParentHasChanged,
286         ItemSceneHasChanged
287
288     This enum describes the state changes that are notified by
289     QGraphicsItem::itemChange(). The notifications are sent as the state
290     changes, and in some cases, adjustments can be made (see the documentation
291     for each change for details).
292
293     Note: Be careful with calling functions on the QGraphicsItem itself inside
294     itemChange(), as certain function calls can lead to unwanted
295     recursion. For example, you cannot call setPos() in itemChange() on an
296     ItemPositionChange notification, as the setPos() function will again call
297     itemChange(ItemPositionChange). Instead, you can return the new, adjusted
298     position from itemChange().
299
300     \value ItemEnabledChange The item's enabled state changes. If the item is
301     presently enabled, it will become disabled, and vice verca. The value
302     argument is the new enabled state (i.e., true or false). Do not call
303     setEnabled() in itemChange() as this notification is delivered. Instead,
304     you can return the new state from itemChange().
305
306     \value ItemEnabledHasChanged The item's enabled state has changed. The
307     value argument is the new enabled state (i.e., true or false). Do not call
308     setEnabled() in itemChange() as this notification is delivered. The return
309     value is ignored.
310
311     \value ItemMatrixChange The item's affine transformation matrix is
312     changing. This value is obsolete; you can use ItemTransformChange instead.
313
314     \value ItemPositionChange The item's position changes. This notification
315     is only sent when the item's local position changes, relative to its
316     parent, has changed (i.e., as a result of calling setPos() or
317     moveBy()). The value argument is the new position (i.e., a QPointF).  You
318     can call pos() to get the original position. Do not call setPos() or
319     moveBy() in itemChange() as this notification is delivered; instead, you
320     can return the new, adjusted position from itemChange(). After this
321     notification, QGraphicsItem immediately sends the ItemPositionHasChanged
322     notification if the position changed.
323
324     \value ItemPositionHasChanged The item's position has changed. This
325     notification is only sent after the item's local position, relative to its
326     parent, has changed. The value argument is the new position (the same as
327     pos()), and QGraphicsItem ignores the return value for this notification
328     (i.e., a read-only notification).
329
330     \value ItemTransformChange The item's transformation matrix changes. This
331     notification is only sent when the item's local transformation matrix
332     changes (i.e., as a result of calling setTransform(), or one of the
333     convenience transformation functions, such as rotate()). The value
334     argument is the new matrix (i.e., a QTransform); to get the old matrix,
335     call transform(). Do not call setTransform() or any of the transformation
336     convenience functions in itemChange() as this notification is delivered;
337     instead, you can return the new matrix from itemChange().
338
339     \value ItemTransformHasChanged The item's transformation matrix has
340     changed.  This notification is only sent after the item's local
341     trasformation matrix has changed. The value argument is the new matrix
342     (same as transform()), and QGraphicsItem ignores the return value for this
343     notification (i.e., a read-only notification).
344
345     \value ItemSelectedChange The item's selected state changes. If the item
346     is presently selected, it will become unselected, and vice verca. The
347     value argument is the new selected state (i.e., true or false). Do not
348     call setSelected() in itemChange() as this notification is delivered();
349     instead, you can return the new selected state from itemChange().
350
351     \value ItemSelectedHasChanged The item's selected state has changed. The
352     value argument is the new selected state (i.e., true or false). Do not
353     call setSelected() in itemChange() as this notification is delivered. The
354     return value is ignored.
355
356     \value ItemVisibleChange The item's visible state changes. If the item is
357     presently visible, it will become invisible, and vice verca. The value
358     argument is the new visible state (i.e., true or false). Do not call
359     setVisible() in itemChange() as this notification is delivered; instead,
360     you can return the new visible state from itemChange().
361
362     \value ItemVisibleHasChanged The item's visible state has changed. The
363     value argument is the new visible state (i.e., true or false). Do not call
364     setVisible() in itemChange() as this notification is delivered. The return
365     value is ignored.
366
367     \value ItemParentChange The item's parent changes. The value argument is
368     the new parent item (i.e., a QGraphicsItem pointer).  Do not call
369     setParentItem() in itemChange() as this notification is delivered;
370     instead, you can return the new parent from itemChange().
371
372     \value ItemParentHasChanged The item's parent has changed. The value
373     argument is the new parent (i.e., a pointer to a QGraphicsItem). Do not
374     call setParentItem() in itemChange() as this notification is
375     delivered. The return value is ignored.
376
377     \value ItemChildAddedChange A child is added to this item. The value
378     argument is the new child item (i.e., a QGraphicsItem pointer). Do not
379     pass this item to any item's setParentItem() function as this notification
380     is delivered. The return value is unused; you cannot adjust anything in
381     this notification. Note that the new child might not be fully constructed
382     when this notification is sent; calling pure virtual functions on
383     the child can lead to a crash.
384
385     \value ItemChildRemovedChange A child is removed from this item. The value
386     argument is the child item that is about to be removed (i.e., a
387     QGraphicsItem pointer). The return value is unused; you cannot adjust
388     anything in this notification.
389
390     \value ItemSceneChange The item is moved to a new scene. This notification
391     is also sent when the item is added to its initial scene, and when it is
392     removed. The value argument is the new scene (i.e., a QGraphicsScene
393     pointer), or a null pointer if the item is removed from a scene. Do not
394     override this change by passing this item to QGraphicsScene::addItem() as
395     this notification is delivered; instead, you can return the new scene from
396     itemChange(). Use this feature with caution; objecting to a scene change can
397     quickly lead to unwanted recursion.
398
399     \value ItemSceneHasChanged The item's scene has changed. The value
400     argument is the new scene (i.e., a pointer to a QGraphicsScene). Do not
401     call setScene() in itemChange() as this notification is delivered. The
402     return value is ignored.
403
404     \value ItemCursorChange The item's cursor changes. The value argument is
405     the new cursor (i.e., a QCursor). Do not call setCursor() in itemChange()
406     as this notification is delivered. Instead, you can return a new cursor
407     from itemChange().
408
409     \value ItemCursorHasChanged The item's cursor has changed. The value
410     argument is the new cursor (i.e., a QCursor). Do not call setCursor() as
411     this notification is delivered. The return value is ignored.
412
413     \value ItemToolTipChange The item's tooltip changes. The value argument is
414     the new tooltip (i.e., a QToolTip). Do not call setToolTip() in
415     itemChange() as this notification is delivered. Instead, you can return a
416     new tooltip from itemChange().
417
418     \value ItemToolTipHasChanged The item's tooltip has changed. The value
419     argument is the new tooltip (i.e., a QToolTip). Do not call setToolTip()
420     as this notification is delivered. The return value is ignored.
421
422     \value ItemFlagsChange The item's flags change. The value argument is the
423     new flags (i.e., a quint32). Do not call setFlags() in itemChange() as
424     this notification is delivered. Instead, you can return the new flags from
425     itemChange().
426
427     \value ItemFlagsHaveChanged The item's flags have changed. The value
428     argument is the new flags (i.e., a quint32). Do not call setFlags() in
429     itemChange() as this notification is delivered. The return value is
430     ignored.
431
432     \value ItemZValueChange The item's Z-value changes. The value argument is
433     the new Z-value (i.e., a double). Do not call setZValue() in itemChange()
434     as this notification is delivered. Instead, you can return a new Z-value
435     from itemChange().
436
437     \value ItemZValueHasChanged The item's Z-value has changed. The value
438     argument is the new Z-value (i.e., a double). Do not call setZValue() as
439     this notification is delivered. The return value is ignored.
440
441     \value ItemOpacityChange The item's opacity changes. The value argument is
442     the new opacity (i.e., a double). Do not call setOpacity() in itemChange()
443     as this notification is delivered. Instead, you can return a new opacity
444     from itemChange().
445
446     \value ItemOpacityHasChanged The item's opacity has changed. The value
447     argument is the new opacity (i.e., a double). Do not call setOpacity() as
448     this notification is delivered. The return value is ignored.
449 */
450
451 /*!
452     \enum QGraphicsItem::CacheMode
453     \since 4.4
454
455     This enum describes QGraphicsItem's cache modes. Caching is used to speed
456     up rendering by allocating and rendering to an off-screen pixel buffer,
457     which can be reused when the item requires redrawing. For some paint
458     devices, the cache is stored directly in graphics memory, which makes
459     rendering very quick.
460
461     \value NoCache The default; all item caching is
462     disabled. QGraphicsItem::paint() is called every time the item needs
463     redrawing.
464
465     \value ItemCoordinateCache Caching is enabled for the item's logical
466     (local) coordinate system. QGraphicsItem creates an off-screen pixel
467     buffer with a configurable size / resolution that you can pass to
468     QGraphicsItem::setCacheMode(). Rendering quality will typically degrade,
469     depending on the resolution of the cache and the item transformation.  The
470     first time the item is redrawn, it will render itself into the cache, and
471     the cache is then reused for every subsequent expose. The cache is also
472     reused as the item is transformed. To adjust the resolution of the cache,
473     you can call setCacheMode() again.
474
475     \value DeviceCoordinateCache Caching is enabled at the paint device level,
476     in device coordinates. This mode is for items that can move, but are not
477     rotated, scaled or sheared. If the item is transformed directly or
478     indirectly, the cache will be regenerated automatically. Unlike
479     ItemCoordinateCacheMode, DeviceCoordinateCache always renders at maximum
480     quality.
481
482     \sa QGraphicsItem::setCacheMode()
483 */
484
485 /*!
486     \enum QGraphicsItem::Extension
487     \internal
488
489     Note: This is provided as a hook to avoid future problems related
490     to adding virtual functions. See also extension(),
491     supportsExtension() and setExtension().
492 */
493
494 #include "qgraphicsitem.h"
495
496 #ifndef QT_NO_GRAPHICSVIEW
497
498 #include "qgraphicsscene.h"
499 #include "qgraphicsscene_p.h"
500 #include "qgraphicssceneevent.h"
501 #include "qgraphicsview.h"
502 #include "qgraphicswidget.h"
503 #include "qgraphicsproxywidget.h"
504 #include <QtCore/qbitarray.h>
505 #include <QtCore/qdebug.h>
506 #include <QtCore/qpoint.h>
507 #include <QtCore/qstack.h>
508 #include <QtCore/qtimer.h>
509 #include <QtCore/qvariant.h>
510 #include <QtCore/qvarlengtharray.h>
511 #include <QtGui/qapplication.h>
512 #include <QtGui/qbitmap.h>
513 #include <QtGui/qpainter.h>
514 #include <QtGui/qpainterpath.h>
515 #include <QtGui/qpixmapcache.h>
516 #include <QtGui/qstyleoption.h>
517 #include <QtGui/qevent.h>
518
519 #include <private/qgraphicsitem_p.h>
520 #include <private/qgraphicswidget_p.h>
521 #include <private/qtextcontrol_p.h>
522 #include <private/qtextdocumentlayout_p.h>
523 #include <private/qtextengine_p.h>
524
525 #include <math.h>
526
527 QT_BEGIN_NAMESPACE
528
529 // QRectF::intersects() returns false always if either the source or target
530 // rectangle's width or height are 0. This works around that problem.
531 static QRectF _q_adjustedRect(const QRectF &rect)
532 {
533     static const qreal p = (qreal)0.00001;
534     QRectF r = rect;
535     if (!r.width())
536         r.adjust(-p, 0, p, 0);
537     if (!r.height())
538         r.adjust(0, -p, 0, p);
539     return r;
540 }
541
542 static QRect _q_adjustedRect(const QRect &rect)
543 {
544     QRect r = rect;
545     if (!r.width())
546         r.adjust(0, 0, 1, 0);
547     if (!r.height())
548         r.adjust(0, 0, 0, 1);
549     return r;
550 }
551
552 /*
553     ### Move this into QGraphicsItemPrivate
554  */
555 class QGraphicsItemCustomDataStore
556 {
557 public:
558     QMap<const QGraphicsItem *, QMap<int, QVariant> > data;
559 };
560 Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)
561
562 /*!
563     \internal
564
565     Removes the first instance of \a child from \a children. This is a
566     heuristic approach that assumes that it's common to remove items from the
567     start or end of the list.
568 */
569 static void qt_graphicsitem_removeChild(QGraphicsItem *child, QList<QGraphicsItem *> *children)
570 {
571     const int n = children->size();
572     for (int i = 0; i < (n + 1) / 2; ++i) {
573         if (children->at(i) == child) {
574             children->removeAt(i);
575             return;
576         }
577         int j = n - i - 1;
578         if (children->at(j) == child) {
579             children->removeAt(j);
580             return;
581         }
582     }
583 }
584
585 /*!
586     \internal
587
588     Returns a QPainterPath of \a path when stroked with the \a pen.
589     Ignoring dash pattern.
590 */
591 static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen)
592 {
593     // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
594     // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
595     const qreal penWidthZero = qreal(0.00000001);
596
597     if (path == QPainterPath())
598         return path;
599     QPainterPathStroker ps;
600     ps.setCapStyle(pen.capStyle());
601     if (pen.widthF() <= 0.0)
602         ps.setWidth(penWidthZero);
603     else
604         ps.setWidth(pen.widthF());
605     ps.setJoinStyle(pen.joinStyle());
606     ps.setMiterLimit(pen.miterLimit());
607     QPainterPath p = ps.createStroke(path);
608     p.addPath(path);
609     return p;
610 }
611
612 /*!
613     \internal
614
615     Propagates the ancestor flag \a flag with value \a enabled to all this
616     item's children. If \a root is false, the flag is also set on this item
617     (default is true).
618 */
619 void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
620                                            AncestorFlag flag, bool enabled, bool root)
621 {
622     Q_Q(QGraphicsItem);
623     if (root) {
624         // For root items only. This is the item that has either enabled or
625         // disabled \a childFlag, or has been reparented.
626         switch (int(childFlag)) {
627         case -1:
628             flag = AncestorHandlesChildEvents;
629             enabled = q->handlesChildEvents();
630             break;
631         case QGraphicsItem::ItemClipsChildrenToShape:
632             flag = AncestorClipsChildren;
633             enabled = flags & QGraphicsItem::ItemClipsChildrenToShape;
634             break;
635         case QGraphicsItem::ItemIgnoresTransformations:
636             flag = AncestorIgnoresTransformations;
637             enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
638             break;
639         default:
640             return;
641         }
642
643         // Inherit the enabled-state from our parents.
644         if ((parent && ((parent->d_ptr->ancestorFlags & flag)
645                         || (int(parent->d_ptr->flags & childFlag) == childFlag)
646                         || (childFlag == -1 && parent->d_ptr->handlesChildEvents)))) {
647             enabled = true;
648             ancestorFlags |= flag;
649         }
650
651         // Top-level root items don't have any ancestors, so there are no
652         // ancestor flags either.
653         if (!parent)
654             ancestorFlags = 0;
655     } else {
656         // Don't set or propagate the ancestor flag if it's already correct.
657         if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled))
658             return;
659
660         // Set the flag.
661         if (enabled)
662             ancestorFlags |= flag;
663         else
664             ancestorFlags &= ~flag;
665
666         // Don't process children if the item has the main flag set on itself.
667         if ((childFlag != -1 &&  int(flags & childFlag) == childFlag) || (int(childFlag) == -1 && handlesChildEvents))
668             return;
669     }
670
671     foreach (QGraphicsItem *child, children)
672         child->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false);
673 }
674
675 /*!
676     \internal
677
678     Propagates item group membership.
679 */
680 void QGraphicsItemPrivate::setIsMemberOfGroup(bool enabled)
681 {
682     Q_Q(QGraphicsItem);
683     isMemberOfGroup = enabled;
684     if (!qgraphicsitem_cast<QGraphicsItemGroup *>(q)) {
685         foreach (QGraphicsItem *child, children)
686             child->d_func()->setIsMemberOfGroup(enabled);
687     }
688 }
689
690 /*!
691     \internal
692
693     Maps any item pos properties of \a event to \a item's coordinate system.
694 */
695 void QGraphicsItemPrivate::remapItemPos(QEvent *event, QGraphicsItem *item)
696 {
697     Q_Q(QGraphicsItem);
698     switch (event->type()) {
699     case QEvent::GraphicsSceneMouseMove:
700     case QEvent::GraphicsSceneMousePress:
701     case QEvent::GraphicsSceneMouseRelease:
702     case QEvent::GraphicsSceneMouseDoubleClick: {
703         QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
704         mouseEvent->setPos(item->mapFromItem(q, mouseEvent->pos()));
705         mouseEvent->setLastPos(item->mapFromItem(q, mouseEvent->pos()));
706         for (int i = 0x1; i <= 0x10; i <<= 1) {
707             if (mouseEvent->buttons() & i) {
708                 Qt::MouseButton button = Qt::MouseButton(i);
709                 mouseEvent->setButtonDownPos(button, item->mapFromItem(q, mouseEvent->buttonDownPos(button)));
710             }
711         }
712         break;
713     }
714     case QEvent::GraphicsSceneWheel: {
715         QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event);
716         wheelEvent->setPos(item->mapFromItem(q, wheelEvent->pos()));
717         break;
718     }
719     case QEvent::GraphicsSceneContextMenu: {
720         QGraphicsSceneContextMenuEvent *contextEvent = static_cast<QGraphicsSceneContextMenuEvent *>(event);
721         contextEvent->setPos(item->mapFromItem(q, contextEvent->pos()));
722         break;
723     }
724     case QEvent::GraphicsSceneHoverMove: {
725         QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
726         hoverEvent->setPos(item->mapFromItem(q, hoverEvent->pos()));
727         break;
728     }
729     default:
730         break;
731     }
732 }
733
734 /*!
735     \internal
736
737     Maps the point \a pos from scene to item coordinates. If \a view is passed and the item
738     is untransformable, this function will correctly map \a pos from the scene using the
739     view's transformation.
740 */
741 QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos,
742                                                   const QWidget *viewport) const
743 {
744     Q_Q(const QGraphicsItem);
745     if (!itemIsUntransformable())
746         return q->mapFromScene(pos);
747     QGraphicsView *view = 0;
748     if (viewport)
749         view = qobject_cast<QGraphicsView *>(viewport->parentWidget());
750     if (!view)
751         return q->mapFromScene(pos);
752     // ### More ping pong than needed.
753     return q->deviceTransform(view->viewportTransform()).inverted().map(view->mapFromScene(pos));
754 }
755
756 /*!
757     \internal
758
759     Returns true if this item or any of its ancestors are untransformable.
760 */
761 bool QGraphicsItemPrivate::itemIsUntransformable() const
762 {
763     return (flags & QGraphicsItem::ItemIgnoresTransformations)
764         || (ancestorFlags & AncestorIgnoresTransformations);
765 }
766
767 /*!
768     \internal
769
770     This helper function helped us add input method query support in
771     Qt 4.4.1 without having to reimplement the inputMethodQuery()
772     function in QGraphicsProxyWidget. ### Qt 5: Remove. We cannot
773     remove it in 4.5+ even if we do reimplement the function properly,
774     because apps compiled with 4.4 will not be able to call the
775     reimplementation.
776 */
777 QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const
778 {
779     Q_UNUSED(query);
780     return QVariant();
781 }
782
783 /*!
784     \internal
785
786     Empty all cached pixmaps from the pixmap cache.
787 */
788 void QGraphicsItemCache::purge()
789 {
790     QPixmapCache::remove(key);
791     QMutableMapIterator<QPaintDevice *, DeviceData> it(deviceData);
792     while (it.hasNext()) {
793         DeviceData &data = it.next().value();
794         QPixmapCache::remove(data.key);
795         data.cacheIndent = QPoint();
796     }
797     deviceData.clear();
798     allExposed = true;
799     exposed.clear();
800 }
801
802 /*!
803     Constructs a QGraphicsItem with the given \a parent.
804
805     If \a parent is 0, you can add the item to a scene by calling
806     QGraphicsScene::addItem(). The item will then become a top-level item.
807
808     \sa QGraphicsScene::addItem(), setParentItem()
809 */
810 QGraphicsItem::QGraphicsItem(QGraphicsItem *parent
811 #ifndef Q_QDOC
812                              // obsolete argument
813                              , QGraphicsScene *scene
814 #endif
815     )
816     : d_ptr(new QGraphicsItemPrivate)
817 {
818     d_ptr->q_ptr = this;
819     setParentItem(parent);
820
821     if (scene && parent && parent->scene() != scene) {
822         qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is"
823                  " different from parent's scene (%p)",
824                  scene, parent->scene());
825         return;
826     }
827     if (scene && !parent)
828         scene->addItem(this);
829 }
830
831 /*!
832     \internal
833 */
834 QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent,
835                              QGraphicsScene *scene)
836     : d_ptr(&dd)
837 {
838     d_ptr->q_ptr = this;
839     setParentItem(parent);
840
841     if (scene && parent && parent->scene() != scene) {
842         qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is"
843                  " different from parent's scene (%p)",
844                  scene, parent->scene());
845         return;
846     }
847     if (scene && !parent)
848         scene->addItem(this);
849 }
850
851 /*!
852     Destroys the QGraphicsItem and all its children. If this item is currently
853     associated with a scene, the item will be removed from the scene before it
854     is deleted.
855 */
856 QGraphicsItem::~QGraphicsItem()
857 {
858     clearFocus();
859     d_ptr->removeExtraItemCache();
860
861     QVariant variant;
862     foreach (QGraphicsItem *child, d_ptr->children) {
863         if (QGraphicsItem *parent = child->parentItem()) {
864             qVariantSetValue<QGraphicsItem *>(variant, child);
865             parent->itemChange(ItemChildRemovedChange, variant);
866         }
867         delete child;
868     }
869     d_ptr->children.clear();
870
871     if (QGraphicsItem *parent = parentItem()) {
872         qVariantSetValue<QGraphicsItem *>(variant, this);
873         parent->itemChange(ItemChildRemovedChange, variant);
874         qt_graphicsitem_removeChild(this, &parent->d_func()->children);
875     }
876     if (d_ptr->scene)
877         d_ptr->scene->d_func()->_q_removeItemLater(this);
878
879     delete d_ptr;
880
881     qt_dataStore()->data.remove(this);
882 }
883
884 /*!
885     Returns the current scene for the item, or 0 if the item is not stored in
886     a scene.
887
888     To add or move an item to a scene, call QGraphicsScene::addItem().
889 */
890 QGraphicsScene *QGraphicsItem::scene() const
891 {
892     return d_ptr->scene;
893 }
894
895 /*!
896     Returns a pointer to this item's item group, or 0 if this item is not
897     member of a group.
898
899     \sa QGraphicsItemGroup, QGraphicsScene::createItemGroup()
900 */
901 QGraphicsItemGroup *QGraphicsItem::group() const
902 {
903     if (!d_ptr->isMemberOfGroup)
904         return 0;
905     QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
906     while ((parent = parent->d_ptr->parent)) {
907         if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(parent))
908             return group;
909     }
910     // Unreachable; if d_ptr->isMemberOfGroup is != 0, then one parent of this
911     // item is a group item.
912     return 0;
913 }
914
915 /*!
916     Adds this item to the item group \a group. If \a group is 0, this item is
917     removed from any current group and added as a child of the previous
918     group's parent.
919
920     \sa group(), QGraphicsScene::createItemGroup()
921 */
922 void QGraphicsItem::setGroup(QGraphicsItemGroup *group)
923 {
924     if (!group) {
925         if (QGraphicsItemGroup *group = this->group())
926             group->removeFromGroup(this);
927     } else {
928         group->addToGroup(this);
929     }
930 }
931
932 /*!
933     Returns a pointer to this item's parent item. If this item does not have a
934     parent, 0 is returned.
935
936     \sa setParentItem(), children()
937 */
938 QGraphicsItem *QGraphicsItem::parentItem() const
939 {
940     return d_ptr->parent;
941 }
942
943 /*!
944     Returns this item's top-level item. The top-level item is the item's
945     topmost ancestor item whose parent is 0. If an item has no parent, its own
946     pointer is returned (i.e., a top-level item is its own top-level item).
947
948     \sa parentItem()
949 */
950 QGraphicsItem *QGraphicsItem::topLevelItem() const
951 {
952     QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
953     while (QGraphicsItem *grandPa = parent->parentItem())
954         parent = grandPa;
955     return parent;
956 }
957
958 /*!
959     \since 4.4
960
961     Returns a pointer to the item's parent widget. The item's parent widget is
962     the closest parent item that is a widget.
963
964     \sa parentItem(), childItems()
965 */
966 QGraphicsWidget *QGraphicsItem::parentWidget() const
967 {
968     QGraphicsItem *p = parentItem();
969     while (p && !p->isWidget())
970         p = p->parentItem();
971     return (p && p->isWidget()) ? static_cast<QGraphicsWidget *>(p) : 0;
972 }
973
974 /*!
975     \since 4.4
976
977     Returns a pointer to the item's top level widget (i.e., the item's
978     ancestor whose parent is 0, or whose parent is not a widget), or 0 if this
979     item does not have a top level widget. If the item is its own top level
980     widget, this function returns a pointer to the item itself.
981 */
982 QGraphicsWidget *QGraphicsItem::topLevelWidget() const
983 {
984     if (const QGraphicsWidget *p = parentWidget())
985         return p->topLevelWidget();
986     return isWidget() ? static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)) : 0;
987 }
988
989 /*!
990     \since 4.4
991
992     Returns the item's window, or 0 if this item does not have a window. If
993     the item is a window, it will return itself.  Otherwise it will return the
994     closest ancestor that is a window.
995
996     \sa QGraphicsWidget::isWindow()
997 */
998 QGraphicsWidget *QGraphicsItem::window() const
999 {
1000     if (isWidget() && static_cast<const QGraphicsWidget *>(this)->isWindow())
1001         return static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this));
1002     if (QGraphicsWidget *parent = parentWidget())
1003         return parent->window();
1004     return 0;
1005 }
1006
1007 /*!
1008     Sets this item's parent item to \a parent. If this item already has a
1009     parent, it is first removed from the previous parent. If \a parent is 0,
1010     this item will become a top-level item.
1011
1012     Note that this implicitly adds this graphics item to the scene of
1013     the parent. You should not \l{QGraphicsScene::addItem()}{add} the
1014     item to the scene yourself.
1015
1016     \sa parentItem(), children()
1017 */
1018 void QGraphicsItem::setParentItem(QGraphicsItem *parent)
1019 {
1020     if (parent == this) {
1021         qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
1022         return;
1023     }
1024     if (parent == d_ptr->parent)
1025         return;
1026     QVariant variant;
1027     qVariantSetValue<QGraphicsItem *>(variant, parent);
1028     parent = qVariantValue<QGraphicsItem *>(itemChange(ItemParentChange, variant));
1029     if (parent == d_ptr->parent)
1030         return;
1031
1032     if (QGraphicsWidget *w = d_ptr->isWidget ? static_cast<QGraphicsWidget *>(this) : parentWidget()) {
1033         // Update the child focus chain; when reparenting a widget that has a
1034         // focus child, ensure that that focus child clears its focus child
1035         // chain from our parents before it's reparented.
1036         if (QGraphicsWidget *focusChild = w->focusWidget())
1037             focusChild->clearFocus();
1038     }
1039
1040     // We anticipate geometry changes
1041     prepareGeometryChange();
1042
1043     if (d_ptr->parent) {
1044         // Remove from current parent
1045         qt_graphicsitem_removeChild(this, &d_ptr->parent->d_func()->children);
1046         qVariantSetValue<QGraphicsItem *>(variant, this);
1047         d_ptr->parent->itemChange(ItemChildRemovedChange, variant);
1048     }
1049
1050     if ((d_ptr->parent = parent)) {
1051         bool implicitUpdate = false;
1052         if (parent->d_func()->scene && parent->d_func()->scene != d_ptr->scene) {
1053             // Move this item to its new parent's scene
1054             parent->d_func()->scene->addItem(this);
1055             implicitUpdate = true;
1056         } else if (!parent->d_func()->scene && d_ptr->scene) {
1057             // Remove this item from its former scene
1058             d_ptr->scene->removeItem(this);
1059         }
1060
1061         d_ptr->parent->d_func()->children << this;
1062         qVariantSetValue<QGraphicsItem *>(variant, this);
1063         d_ptr->parent->itemChange(ItemChildAddedChange, variant);
1064         if (!implicitUpdate)
1065             d_ptr->updateHelper();
1066
1067         // Inherit ancestor flags from the new parent.
1068         d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
1069         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
1070         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
1071
1072         // Update item visible / enabled.
1073         if (d_ptr->parent->isVisible() != d_ptr->visible) {
1074             if (!d_ptr->parent->isVisible() || !d_ptr->explicitlyHidden)
1075                 d_ptr->setVisibleHelper(d_ptr->parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
1076         }
1077         if (d_ptr->parent->isEnabled() != d_ptr->enabled) {
1078             if (!d_ptr->parent->isEnabled() || !d_ptr->explicitlyDisabled)
1079                 d_ptr->setEnabledHelper(d_ptr->parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
1080         }
1081
1082     } else {
1083         // Inherit ancestor flags from the new parent.
1084         d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
1085         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
1086         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
1087
1088         // Update item visible / enabled.
1089         if (!d_ptr->visible && !d_ptr->explicitlyHidden)
1090             d_ptr->setVisibleHelper(true, /* explicit = */ false);
1091         if (!d_ptr->enabled && !d_ptr->explicitlyDisabled)
1092             d_ptr->setEnabledHelper(true, /* explicit = */ false);
1093
1094         d_ptr->updateHelper();
1095     }
1096
1097     if (d_ptr->scene) {
1098         // Invalidate any sort caching; arrival of a new item means we need to
1099         // resort.
1100         d_ptr->scene->d_func()->invalidateSortCache();
1101     }
1102
1103     // Resolve opacity.
1104     if (QGraphicsItem *p = d_ptr->parent)
1105         d_ptr->resolveEffectiveOpacity(p->effectiveOpacity());
1106     else
1107         d_ptr->resolveEffectiveOpacity(1.0);
1108
1109     // Resolve depth.
1110     d_ptr->resolveDepth(parent ? parent->d_ptr->depth : -1);
1111
1112     // Invalidate transform cache.
1113     d_ptr->invalidateSceneTransformCache();
1114
1115     // Deliver post-change notification
1116     itemChange(QGraphicsItem::ItemParentHasChanged, qVariantFromValue<QGraphicsItem *>(parent));
1117 }
1118
1119 /*!
1120     \obsolete
1121
1122     Use childItems() instead.
1123
1124     \sa setParentItem()
1125 */
1126 QList<QGraphicsItem *> QGraphicsItem::children() const
1127 {
1128     return childItems();
1129 }
1130
1131 /*!
1132     \since 4.4
1133
1134     Returns a list of this item's children. The items are returned in no
1135     particular order.
1136
1137     \sa setParentItem()
1138 */
1139 QList<QGraphicsItem *> QGraphicsItem::childItems() const
1140 {
1141     return d_ptr->children;
1142 }
1143
1144 /*!
1145     \since 4.4
1146     Returns true if this item is a widget (i.e., QGraphicsWidget); otherwise,
1147     returns false.
1148 */
1149 bool QGraphicsItem::isWidget() const
1150 {
1151     return d_ptr->isWidget;
1152 }
1153
1154 /*!
1155     \since 4.4
1156     Returns true if the item is a QGraphicsWidget window, otherwise returns
1157     false.
1158
1159     \sa QGraphicsWidget::windowFlags()
1160 */
1161 bool QGraphicsItem::isWindow() const
1162 {
1163     return isWidget() && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
1164 }
1165
1166 /*!
1167     Returns this item's flags. The flags describe what configurable features
1168     of the item are enabled and not. For example, if the flags include
1169     ItemIsFocusable, the item can accept input focus.
1170
1171     By default, no flags are enabled.
1172
1173     \sa setFlags(), setFlag()
1174 */
1175 QGraphicsItem::GraphicsItemFlags QGraphicsItem::flags() const
1176 {
1177     return GraphicsItemFlags(d_ptr->flags);
1178 }
1179
1180 /*!
1181     If \a enabled is true, the item flag \a flag is enabled; otherwise, it is
1182     disabled.
1183
1184     \sa flags(), setFlags()
1185 */
1186 void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled)
1187 {
1188     if (enabled)
1189         setFlags(flags() | flag);
1190     else
1191         setFlags(flags() & ~flag);
1192 }
1193
1194 /*!
1195     \internal
1196
1197     Sets the flag \a flag on \a item and all its children, to \a enabled.
1198 */
1199 static void _q_qgraphicsItemSetFlag(QGraphicsItem *item, QGraphicsItem::GraphicsItemFlag flag,
1200                                     bool enabled)
1201 {
1202     if (item->flags() & flag) {
1203         // If this item already has the correct flag set, we don't have to
1204         // propagate it.
1205         return;
1206     }
1207     item->setFlag(flag, enabled);
1208     foreach (QGraphicsItem *child, item->children())
1209         _q_qgraphicsItemSetFlag(child, flag, enabled);
1210 }
1211
1212 /*!
1213     Sets the item flags to \a flags. All flags in \a flags are enabled; all
1214     flags not in \a flags are disabled.
1215
1216     If the item had focus and \a flags does not enable ItemIsFocusable, the
1217     item loses focus as a result of calling this function. Similarly, if the
1218     item was selected, and \a flags does not enabled ItemIsSelectable, the
1219     item is automatically unselected.
1220
1221     By default, no flags are enabled.
1222
1223     \sa flags(), setFlag()
1224 */
1225 void QGraphicsItem::setFlags(GraphicsItemFlags flags)
1226 {
1227     // Notify change and check for adjustment.
1228     if (quint32(d_ptr->flags) == quint32(flags))
1229         return;
1230     flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt());
1231     if (quint32(d_ptr->flags) == quint32(flags))
1232         return;
1233
1234     // Flags that alter the geometry of the item (or its children).
1235     int geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);
1236     bool fullUpdate = (flags & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
1237     if (fullUpdate)
1238         d_ptr->fullUpdateHelper();
1239
1240     // Keep the old flags to compare the diff.
1241     GraphicsItemFlags oldFlags = this->flags();
1242
1243     // Update flags.
1244     d_ptr->flags = flags;
1245
1246     // Reresolve effective opacity if the opacity flags change.
1247     static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren;
1248     if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask)) {
1249         if (QGraphicsItem *p = d_ptr->parent)
1250             d_ptr->resolveEffectiveOpacity(p->effectiveOpacity());
1251         else
1252             d_ptr->resolveEffectiveOpacity(1.0);
1253     }
1254
1255     if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
1256         // Clear focus on the item if it has focus when the focusable flag
1257         // is unset.
1258         clearFocus();
1259     }
1260
1261     if (!(d_ptr->flags & ItemIsSelectable) && isSelected()) {
1262         // Unselect the item if it is selected when the selectable flag is
1263         // unset.
1264         setSelected(false);
1265     }
1266
1267     if ((flags & ItemClipsChildrenToShape) != (oldFlags & ItemClipsChildrenToShape)) {
1268         // Item children clipping changes. Propagate the ancestor flag to
1269         // all children.
1270         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
1271     }
1272
1273     if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
1274         // Item children clipping changes. Propagate the ancestor flag to
1275         // all children.
1276         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
1277     }
1278
1279     // ### Why updateHelper?
1280     d_ptr->updateHelper();
1281
1282     // Notify change.
1283     itemChange(ItemFlagsHaveChanged, quint32(flags));
1284 }
1285
1286 /*!
1287     \since 4.4
1288     Returns the cache mode for this item. The default mode is NoCache (i.e.,
1289     cache is disabled and all painting is immediate).
1290
1291     \sa setCacheMode()
1292 */
1293 QGraphicsItem::CacheMode QGraphicsItem::cacheMode() const
1294 {
1295     return QGraphicsItem::CacheMode(d_ptr->cacheMode);
1296 }
1297
1298 /*!
1299     \since 4.4
1300     Sets the item's cache mode to \a mode.
1301
1302     The optional \a logicalCacheSize argument is used only by
1303     ItemCoordinateCache mode, and describes the resolution of the cache
1304     buffer; if \a logicalCacheSize is (100, 100), QGraphicsItem will fit the
1305     item into 100x100 pixels in graphics memory, regardless of the logical
1306     size of the item itself. By default QGraphicsItem uses the size of
1307     boundingRect(). For all other cache modes than ItemCoordinateCache, \a
1308     logicalCacheSize is ignored.
1309
1310     Caching can speed up rendering if your item spends a significant time
1311     redrawing itself. In some cases the cache can also slow down rendering, in
1312     particular when the item spends less time redrawing than QGraphicsItem
1313     spends redrawing from the cache. When enabled, the item's paint() function
1314     will be called only once for each call to update(); for any subsequent
1315     repaint requests, the Graphics View framework will redraw from the
1316     cache. This approach works particularly well with QGLWidget, which stores
1317     all the cache as OpenGL textures.
1318
1319     Be aware that QPixmapCache's cache limit may need to be changed to obtain
1320     optimal performance.
1321
1322     You can read more about the different cache modes in the CacheMode
1323     documentation.
1324
1325     \sa CacheMode, QPixmapCache::setCacheLimit()
1326 */
1327 void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
1328 {
1329     CacheMode lastMode = CacheMode(d_ptr->cacheMode);
1330     d_ptr->cacheMode = mode;
1331     bool noVisualChange = (mode == NoCache && lastMode == NoCache)
1332                           || (mode == NoCache && lastMode == DeviceCoordinateCache)
1333                           || (mode == DeviceCoordinateCache && lastMode == NoCache);
1334     if (mode == NoCache) {
1335         d_ptr->removeExtraItemCache();
1336     } else {
1337         QGraphicsItemCache *cache = d_ptr->extraItemCache();
1338
1339         // Reset old cache
1340         cache->purge();
1341
1342         if (mode == ItemCoordinateCache) {
1343             if (cache->key.isEmpty()) {
1344                 // Generate new simple pixmap cache key.
1345                 QString tmp;
1346                 tmp.sprintf("qgv-%p", this);
1347                 cache->key = tmp;
1348             }
1349             if (lastMode == mode && cache->fixedSize == logicalCacheSize)
1350                 noVisualChange = true;
1351             cache->fixedSize = logicalCacheSize;
1352         }
1353     }
1354     if (!noVisualChange)
1355         update();
1356 }
1357
1358 #ifndef QT_NO_TOOLTIP
1359 /*!
1360     Returns the item's tool tip, or an empty QString if no tool tip has been
1361     set.
1362
1363     \sa setToolTip(), QToolTip
1364 */
1365 QString QGraphicsItem::toolTip() const
1366 {
1367     return d_ptr->extra(QGraphicsItemPrivate::ExtraToolTip).toString();
1368 }
1369
1370 /*!
1371     Sets the item's tool tip to \a toolTip. If \a toolTip is empty, the item's
1372     tool tip is cleared.
1373
1374     \sa toolTip(), QToolTip
1375 */
1376 void QGraphicsItem::setToolTip(const QString &toolTip)
1377 {
1378     QString newCursor = itemChange(ItemToolTipChange, toolTip).toString();
1379     d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTip);
1380     itemChange(ItemToolTipHasChanged, toolTip);
1381 }
1382 #endif // QT_NO_TOOLTIP
1383
1384 #ifndef QT_NO_CURSOR
1385 /*!
1386     Returns the current cursor shape for the item. The mouse cursor
1387     will assume this shape when it's over this item. See the \link
1388     Qt::CursorShape list of predefined cursor objects\endlink for a
1389     range of useful shapes.
1390
1391     An editor item might want to use an I-beam cursor:
1392
1393     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 2
1394
1395     If no cursor has been set, the parent's cursor is used.
1396
1397     \sa setCursor(), hasCursor(), unsetCursor(), QWidget::cursor,
1398     QApplication::overrideCursor()
1399 */
1400 QCursor QGraphicsItem::cursor() const
1401 {
1402     return qVariantValue<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor));
1403 }
1404
1405 /*!
1406     Sets the current cursor shape for the item to \a cursor. The mouse cursor
1407     will assume this shape when it's over this item. See the \link
1408     Qt::CursorShape list of predefined cursor objects\endlink for a range of
1409     useful shapes.
1410
1411     An editor item might want to use an I-beam cursor:
1412
1413     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 3
1414
1415     If no cursor has been set, the cursor of the item beneath is used.
1416
1417     \sa cursor(), hasCursor(), unsetCursor(), QWidget::cursor,
1418     QApplication::overrideCursor()
1419 */
1420 void QGraphicsItem::setCursor(const QCursor &cursor)
1421 {
1422     QCursor newCursor = qVariantValue<QCursor>(itemChange(ItemCursorChange,
1423                                                           qVariantFromValue<QCursor>(cursor)));
1424     d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, newCursor);
1425     d_ptr->hasCursor = 1;
1426     if (d_ptr->scene) {
1427         foreach (QGraphicsView *view, d_ptr->scene->views()) {
1428             // Note: Some of this logic is duplicated in QGraphicsView's mouse events.
1429             if (view->underMouse()) {
1430                 foreach (QGraphicsItem *itemUnderCursor, view->items(view->mapFromGlobal(QCursor::pos()))) {
1431                     if (itemUnderCursor->hasCursor()) {
1432                         QMetaObject::invokeMethod(view, "_q_setViewportCursor",
1433                                                   Q_ARG(QCursor, itemUnderCursor->cursor()));
1434                         break;
1435                     }
1436                 }
1437                 break;
1438             }
1439         }
1440     }
1441     itemChange(ItemCursorHasChanged, qVariantFromValue<QCursor>(newCursor));
1442 }
1443
1444 /*!
1445     Returns true if this item has a cursor set; otherwise, false is returned.
1446
1447     By default, items don't have any cursor set. cursor() will return a
1448     standard pointing arrow cursor.
1449
1450     \sa unsetCursor()
1451 */
1452 bool QGraphicsItem::hasCursor() const
1453 {
1454     return d_ptr->hasCursor;
1455 }
1456
1457 /*!
1458     Clears the cursor from this item.
1459
1460     \sa hasCursor(), setCursor()
1461 */
1462 void QGraphicsItem::unsetCursor()
1463 {
1464     d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraCursor);
1465     d_ptr->hasCursor = 0;
1466     if (d_ptr->scene) {
1467         foreach (QGraphicsView *view, d_ptr->scene->views()) {
1468             if (view->underMouse() && view->itemAt(view->mapFromGlobal(QCursor::pos())) == this) {
1469                 QMetaObject::invokeMethod(view, "_q_unsetViewportCursor");
1470                 break;
1471             }
1472         }
1473     }
1474 }
1475
1476 #endif // QT_NO_CURSOR
1477
1478 /*!
1479    Returns true if the item is visible; otherwise, false is returned.
1480
1481    Note that the item's general visibility is unrelated to whether or not it
1482    is actually being visualized by a QGraphicsView.
1483
1484    \sa setVisible()
1485 */
1486 bool QGraphicsItem::isVisible() const
1487 {
1488     return d_ptr->visible;
1489 }
1490
1491 /*!
1492     \since 4.4
1493     Returns true if the item is visible to \a parent; otherwise, false is
1494     returned. \a parent can be 0, in which case this function will return
1495     whether the item is visible to the scene or not.
1496
1497     An item may not be visible to its ancestors even if isVisible() is true. If
1498     any ancestor is hidden, the item itself will be implicitly hidden, in which
1499     case this function will return false.
1500
1501     \sa isVisible(), setVisible()
1502 */
1503 bool QGraphicsItem::isVisibleTo(const QGraphicsItem *parent) const
1504 {
1505     if (!d_ptr->visible)
1506         return false;
1507     if (parent == this)
1508         return true;
1509     if (parentItem() && parentItem()->isVisibleTo(parent))
1510         return true;
1511     if (!parent && !parentItem())
1512         return true;
1513     return false;
1514 }
1515
1516 /*!
1517     \internal
1518
1519     Sets this item's visibility to \a newVisible. If \a explicitly is true,
1520     this item will be "explicitly" \a newVisible; otherwise, it.. will not be.
1521 */
1522 void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bool update)
1523 {
1524     Q_Q(QGraphicsItem);
1525
1526     // Update explicit bit.
1527     if (explicitly)
1528         explicitlyHidden = newVisible ? 0 : 1;
1529
1530     // Check if there's nothing to do.
1531     if (visible == quint32(newVisible))
1532         return;
1533
1534     // Modify the property.
1535     newVisible = q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, quint32(newVisible)).toBool();
1536     if (visible == quint32(newVisible))
1537         return;
1538     visible = newVisible;
1539
1540     // Schedule redrawing
1541     if (update) {
1542         QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
1543         if (c)
1544             c->purge();
1545         updateHelper(QRectF(), /* force = */ true);
1546     }
1547
1548     // Certain properties are dropped as an item becomes invisible.
1549     if (!newVisible) {
1550         if (scene) {
1551             if (scene->d_func()->mouseGrabberItems.contains(q))
1552                 q->ungrabMouse();
1553             if (scene->d_func()->keyboardGrabberItems.contains(q))
1554                 q->ungrabKeyboard();
1555         }
1556         if (q_ptr->hasFocus() && scene) {
1557             // Hiding the closest non-window ancestor of the focus item
1558             QGraphicsItem *focusItem = scene->focusItem();
1559             bool clear = true;
1560             if (isWidget && !focusItem->isWindow()) {
1561                 do {
1562                     if (focusItem == q_ptr) {
1563                         clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
1564                         break;
1565                     }
1566                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isWindow());
1567             }
1568             if (clear)
1569                 q_ptr->clearFocus();
1570         }
1571         if (q_ptr->isSelected())
1572             q_ptr->setSelected(false);
1573     } else {
1574         if (isWidget && scene) {
1575             QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
1576             if (widget->windowType() == Qt::Popup)
1577                 scene->d_func()->addPopup(widget);
1578         }
1579     }
1580
1581     // Update children with explicitly = false.
1582     foreach (QGraphicsItem *child, children) {
1583         if (!newVisible || !child->d_ptr->explicitlyHidden)
1584             child->d_ptr->setVisibleHelper(newVisible, false);
1585     }
1586
1587     // Enable subfocus
1588     if (newVisible && isWidget) {
1589         QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
1590         QGraphicsWidget *fw = widget->focusWidget();
1591         if (fw && fw != scene->focusItem())
1592             scene->setFocusItem(fw);
1593     }
1594
1595     // Deliver post-change notification.
1596     q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, quint32(visible));
1597 }
1598
1599 /*!
1600     If \a visible is true, the item is made visible. Otherwise, the item is
1601     made invisible. Invisible items are not painted, nor do they receive any
1602     events. In particular, mouse events pass right through invisible items,
1603     and are delivered to any item that may be behind. Invisible items are also
1604     unselectable, they cannot take input focus, and are not detected by
1605     QGraphicsScene's item location functions.
1606
1607     If an item becomes invisible while grabbing the mouse, (i.e., while it is
1608     receiving mouse events,) it will automatically lose the mouse grab, and
1609     the grab is not regained by making the item visible again; it must receive
1610     a new mouse press to regain the mouse grab.
1611
1612     Similarly, an invisible item cannot have focus, so if the item has focus
1613     when it becomes invisible, it will lose focus, and the focus is not
1614     regained by simply making the item visible again.
1615
1616     If you hide a parent item, all its children will also be hidden. If you
1617     show a parent item, all children will be shown, unless they have been
1618     explicitly hidden (i.e., if you call setVisible(false) on a child, it will
1619     not be reshown even if its parent is hidden, and then shown again).
1620
1621     Items are visible by default; it is unnecessary to call
1622     setVisible() on a new item.
1623
1624     \sa isVisible(), show(), hide()
1625 */
1626 void QGraphicsItem::setVisible(bool visible)
1627 {
1628     d_ptr->setVisibleHelper(visible, /* explicit = */ true);
1629 }
1630
1631 /*!
1632     \fn void QGraphicsItem::hide()
1633
1634     Hides the item. (Items are visible by default.)
1635
1636     This convenience function is equivalent to calling \c setVisible(false).
1637
1638     \sa show(), setVisible()
1639 */
1640
1641 /*!
1642     \fn void QGraphicsItem::show()
1643
1644     Shows the item. (Items are visible by default.)
1645
1646     This convenience function is equivalent to calling \c setVisible(true).
1647
1648     \sa hide(), setVisible()
1649 */
1650
1651 /*!
1652     Returns true if the item is enabled; otherwise, false is returned.
1653
1654     \sa setEnabled()
1655 */
1656 bool QGraphicsItem::isEnabled() const
1657 {
1658     return d_ptr->enabled;
1659 }
1660
1661 /*!
1662     \internal
1663
1664     Sets this item's visibility to \a newEnabled. If \a explicitly is true,
1665     this item will be "explicitly" \a newEnabled; otherwise, it.. will not be.
1666 */
1667 void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bool update)
1668 {
1669     // Update explicit bit.
1670     if (explicitly)
1671         explicitlyDisabled = newEnabled ? 0 : 1;
1672
1673     // Check if there's nothing to do.
1674     if (enabled == quint32(newEnabled))
1675         return;
1676
1677     // Certain properties are dropped when an item is disabled.
1678     if (!newEnabled) {
1679         if (scene && scene->mouseGrabberItem() == q_ptr)
1680             q_ptr->ungrabMouse();
1681         if (q_ptr->hasFocus()) {
1682             // Disabling the closest non-window ancestor of the focus item
1683             // causes focus to pop to the next item, otherwise it's cleared.
1684             QGraphicsItem *focusItem = scene->focusItem();
1685             bool clear = true;
1686             if (isWidget && !focusItem->isWindow() && q_ptr->isAncestorOf(focusItem)) {
1687                 do {
1688                     if (focusItem == q_ptr) {
1689                         clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
1690                         break;
1691                     }
1692                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isWindow());
1693             }
1694             if (clear)
1695                 q_ptr->clearFocus();
1696         }
1697         if (q_ptr->isSelected())
1698             q_ptr->setSelected(false);
1699     }
1700
1701     // Modify the property.
1702     enabled = q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, quint32(newEnabled)).toBool();
1703
1704     // Schedule redraw.
1705     if (update)
1706         updateHelper();
1707
1708     foreach (QGraphicsItem *child, children) {
1709         if (!newEnabled || !child->d_ptr->explicitlyDisabled)
1710             child->d_ptr->setEnabledHelper(newEnabled, /* explicitly = */ false);
1711     }
1712
1713     // Deliver post-change notification.
1714     q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, quint32(enabled));
1715 }
1716
1717 /*!
1718     If \a enabled is true, the item is enabled; otherwise, it is disabled.
1719
1720     Disabled items are visible, but they do not receive any events, and cannot
1721     take focus nor be selected. Mouse events are discarded; they are not
1722     propagated unless the item is also invisible, or if it does not accept
1723     mouse events (see acceptedMouseButtons()). A disabled item cannot become the
1724     mouse grabber, and as a result of this, an item loses the grab if it
1725     becomes disabled when grabbing the mouse, just like it loses focus if it
1726     had focus when it was disabled.
1727
1728     Disabled items are traditionally drawn using grayed-out colors (see \l
1729     QPalette::Disabled).
1730
1731     If you disable a parent item, all its children will also be disabled. If
1732     you enable a parent item, all children will be enabled, unless they have
1733     been explicitly disabled (i.e., if you call setEnabled(false) on a child,
1734     it will not be reenabled if its parent is disabled, and then enabled
1735     again).
1736
1737     Items are enabled by default.
1738
1739     \note If you install an event filter, you can still intercept events
1740     before they are delivered to items; this mechanism disregards the item's
1741     enabled state.
1742
1743     \sa isEnabled()
1744 */
1745 void QGraphicsItem::setEnabled(bool enabled)
1746 {
1747     d_ptr->setEnabledHelper(enabled, /* explicitly = */ true);
1748 }
1749
1750 /*!
1751     Returns true if this item is selected; otherwise, false is returned.
1752
1753     Items that are in a group inherit the group's selected state.
1754
1755     Items are not selected by default.
1756
1757     \sa setSelected(), QGraphicsScene::setSelectionArea()
1758 */
1759 bool QGraphicsItem::isSelected() const
1760 {
1761     if (QGraphicsItemGroup *group = this->group())
1762         return group->isSelected();
1763     return d_ptr->selected;
1764 }
1765
1766 /*!
1767     If \a selected is true and this item is selectable, this item is selected;
1768     otherwise, it is unselected.
1769
1770     If the item is in a group, the whole group's selected state is toggled by
1771     this function. If the group is selected, all items in the group are also
1772     selected, and if the group is not selected, no item in the group is
1773     selected.
1774
1775     Only visible, enabled, selectable items can be selected.  If \a selected
1776     is true and this item is either invisible or disabled or unselectable,
1777     this function does nothing.
1778
1779     By default, items cannot be selected. To enable selection, set the
1780     ItemIsSelectable flag.
1781
1782     This function is provided for convenience, allowing individual toggling of
1783     the selected state of an item. However, a more common way of selecting
1784     items is to call QGraphicsScene::setSelectionArea(), which will call this
1785     function for all visible, enabled, and selectable items within a specified
1786     area on the scene.
1787
1788     \sa isSelected(), QGraphicsScene::selectedItems()
1789 */
1790 void QGraphicsItem::setSelected(bool selected)
1791 {
1792     if (QGraphicsItemGroup *group = this->group()) {
1793         group->setSelected(selected);
1794         return;
1795     }
1796
1797     if (!(d_ptr->flags & ItemIsSelectable) || !d_ptr->enabled || !d_ptr->visible)
1798         selected = false;
1799     if (d_ptr->selected == selected)
1800         return;
1801     bool newSelected = itemChange(ItemSelectedChange, quint32(selected)).toBool();
1802     if (d_ptr->selected == newSelected)
1803         return;
1804     d_ptr->selected = newSelected;
1805
1806     d_ptr->updateHelper();
1807
1808     if (d_ptr->scene) {
1809         QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
1810         if (selected) {
1811             sceneD->selectedItems << this;
1812         } else {
1813             // QGraphicsScene::selectedItems() lazily pulls out all items that are
1814             // no longer selected.
1815         }
1816         if (!sceneD->selectionChanging)
1817             emit d_ptr->scene->selectionChanged();
1818     }
1819
1820     // Deliver post-change notification.
1821     itemChange(QGraphicsItem::ItemSelectedHasChanged, quint32(d_ptr->selected));
1822 }
1823
1824 /*!
1825     \since 4.5
1826
1827     Returns this item's local opacity, which is between 0.0 (transparent) and
1828     1.0 (opaque). This value is combined with parent and ancestor values into
1829     the effectiveOpacity(). The effective opacity decides how the item is
1830     rendered.
1831
1832     The opacity property decides the state of the painter passed to the
1833     paint() function. If the item is cached, i.e., ItemCoordinateCache or
1834     DeviceCoordinateCache, the effective property will be applied to the item's
1835     cache as it is rendered.
1836
1837     The default opacity is 1.0; fully opaque.
1838
1839     \sa setOpacity(), paint(), ItemIgnoresParentOpacity,
1840     ItemDoesntPropagateOpacityToChildren
1841 */
1842 qreal QGraphicsItem::opacity() const
1843 {
1844     if (d_ptr->hasOpacity) {
1845         QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity);
1846         if (!o.isNull())
1847             return o.toDouble();
1848     }
1849     return qreal(1.0);
1850 }
1851
1852 /*!
1853     \since 4.5
1854
1855     Returns this item's \e effective opacity, which is between 0.0
1856     (transparent) and 1.0 (opaque). This value is a combination of this item's
1857     local opacity, and its parent and ancestors' opacities. The effective
1858     opacity decides how the item is rendered.
1859
1860     \sa opacity(), setOpacity(), paint(), ItemIgnoresParentOpacity,
1861     ItemDoesntPropagateOpacityToChildren
1862 */
1863 qreal QGraphicsItem::effectiveOpacity() const
1864 {
1865     QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity);
1866     return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble());
1867 }
1868
1869 /*!
1870     \since 4.5
1871
1872     Sets this item's local \a opacity, between 0.0 (transparent) and 1.0
1873     (opaque). The item's local opacity is combined with parent and ancestor
1874     opacities into the effectiveOpacity().
1875
1876     By default, opacity propagates from parent to child, so if a parent's
1877     opacity is 0.5 and the child is also 0.5, the child's effective opacity
1878     will be 0.25.
1879
1880     The opacity property decides the state of the painter passed to the
1881     paint() function. If the item is cached, i.e., ItemCoordinateCache or
1882     DeviceCoordinateCache, the effective property will be applied to the
1883     item's cache as it is rendered.
1884
1885     There are two item flags that affect how the item's opacity is combined
1886     with the parent: ItemIgnoresParentOpacity and
1887     ItemDoesntPropagateOpacityToChildren.
1888
1889     \sa opacity(), effectiveOpacity()
1890 */
1891 void QGraphicsItem::setOpacity(qreal opacity)
1892 {
1893     // Notify change.
1894     qreal newOpacity = itemChange(ItemOpacityChange, double(opacity)).toDouble();
1895
1896     // Normalize.
1897     newOpacity = qBound<qreal>(0.0, newOpacity, 1.0);
1898
1899     // No change? Done.
1900     if (qFuzzyCompare(newOpacity, this->opacity()))
1901         return;
1902
1903     // Assign local opacity.
1904     if (qFuzzyCompare(newOpacity, qreal(1.0))) {
1905         // Opaque, unset opacity.
1906         d_ptr->hasOpacity = 0;
1907         d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity);
1908     } else {
1909         d_ptr->hasOpacity = 1;
1910         d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity));
1911     }
1912
1913     // Resolve effective opacity.
1914     if (QGraphicsItem *p = d_ptr->parent)
1915         d_ptr->resolveEffectiveOpacity(p->effectiveOpacity());
1916     else
1917         d_ptr->resolveEffectiveOpacity(1.0);
1918
1919     // Notify change.
1920     itemChange(ItemOpacityHasChanged, newOpacity);
1921
1922     // Update.
1923     d_ptr->fullUpdateHelper();
1924 }
1925
1926 /*!
1927    Returns true if this item can accept drag and drop events; otherwise,
1928    returns false. By default, items do not accept drag and drop events; items
1929    are transparent to drag and drop.
1930
1931    \sa setAcceptDrops()
1932 */
1933 bool QGraphicsItem::acceptDrops() const
1934 {
1935     return d_ptr->acceptDrops;
1936 }
1937
1938 /*!
1939     If \a on is true, this item will accept drag and drop events; otherwise,
1940     it is transparent for drag and drop events. By default, items do not
1941     accept drag and drop events.
1942
1943     \sa acceptDrops()
1944 */
1945 void QGraphicsItem::setAcceptDrops(bool on)
1946 {
1947     d_ptr->acceptDrops = on;
1948 }
1949
1950 /*!
1951     Returns the mouse buttons that this item accepts mouse events for.  By
1952     default, all mouse buttons are accepted.
1953
1954     If an item accepts a mouse button, it will become the mouse
1955     grabber item when a mouse press event is delivered for that mouse
1956     button. However, if the item does not accept the button,
1957     QGraphicsScene will forward the mouse events to the first item
1958     beneath it that does.
1959
1960     \sa setAcceptedMouseButtons(), mousePressEvent()
1961 */
1962 Qt::MouseButtons QGraphicsItem::acceptedMouseButtons() const
1963 {
1964     return Qt::MouseButtons(d_ptr->acceptedMouseButtons);
1965 }
1966
1967 /*!
1968     Sets the mouse \a buttons that this item accepts mouse events for.
1969
1970     By default, all mouse buttons are accepted. If an item accepts a
1971     mouse button, it will become the mouse grabber item when a mouse
1972     press event is delivered for that button. However, if the item
1973     does not accept the mouse button, QGraphicsScene will forward the
1974     mouse events to the first item beneath it that does.
1975
1976     To disable mouse events for an item (i.e., make it transparent for mouse
1977     events), call setAcceptedMouseButtons(0).
1978
1979     \sa acceptedMouseButtons(), mousePressEvent()
1980 */
1981 void QGraphicsItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
1982 {
1983     if (Qt::MouseButtons(d_ptr->acceptedMouseButtons) != buttons) {
1984         if (buttons == 0 && d_ptr->scene && d_ptr->scene->mouseGrabberItem() == this
1985             && d_ptr->scene->d_func()->lastMouseGrabberItemHasImplicitMouseGrab) {
1986             ungrabMouse();
1987         }
1988         d_ptr->acceptedMouseButtons = quint32(buttons);
1989     }
1990 }
1991
1992 /*!
1993     \since 4.4
1994
1995     Returns true if an item accepts hover events
1996     (QGraphicsSceneHoverEvent); otherwise, returns false. By default,
1997     items do not accept hover events.
1998
1999     \sa setAcceptedMouseButtons()
2000 */
2001 bool QGraphicsItem::acceptHoverEvents() const
2002 {
2003     return d_ptr->acceptsHover;
2004 }
2005
2006 /*!
2007     \obsolete
2008
2009     Call acceptHoverEvents() instead.
2010 */
2011 bool QGraphicsItem::acceptsHoverEvents() const
2012 {
2013     return d_ptr->acceptsHover;
2014 }
2015
2016 /*!
2017     \since 4.4
2018
2019     If \a enabled is true, this item will accept hover events;
2020     otherwise, it will ignore them. By default, items do not accept
2021     hover events.
2022
2023     Hover events are delivered when there is no current mouse grabber
2024     item.  They are sent when the mouse cursor enters an item, when it
2025     moves around inside the item, and when the cursor leaves an
2026     item. Hover events are commonly used to highlight an item when
2027     it's entered, and for tracking the mouse cursor as it hovers over
2028     the item (equivalent to QWidget::mouseTracking).
2029
2030     Parent items receive hover enter events before their children, and
2031     leave events after their children. The parent does not receive a
2032     hover leave event if the cursor enters a child, though; the parent
2033     stays "hovered" until the cursor leaves its area, including its
2034     children's areas.
2035
2036     If a parent item handles child events (setHandlesChildEvents()), it will
2037     receive hover move, drag move, and drop events as the cursor passes
2038     through its children, but it does not receive hover enter and hover leave,
2039     nor drag enter and drag leave events on behalf of its children.
2040
2041     A QGraphicsWidget with window decorations will accept hover events
2042     regardless of the value of acceptHoverEvents().
2043
2044     \sa acceptHoverEvents(), hoverEnterEvent(), hoverMoveEvent(),
2045     hoverLeaveEvent()
2046 */
2047 void QGraphicsItem::setAcceptHoverEvents(bool enabled)
2048 {
2049     d_ptr->acceptsHover = quint32(enabled);
2050 }
2051
2052 /*!
2053     \obsolete
2054
2055     Use setAcceptHoverEvents(\a enabled) instead.
2056 */
2057 void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
2058 {
2059     d_ptr->acceptsHover = quint32(enabled);
2060 }
2061
2062 /*!
2063     Returns true if this item handles child events (i.e., all events
2064     intended for any of its children are instead sent to this item);
2065     otherwise, false is returned.
2066
2067     This property is useful for item groups; it allows one item to
2068     handle events on behalf of its children, as opposed to its
2069     children handling their events individually.
2070
2071     The default is to return false; children handle their own events.
2072     The exception for this is if the item is a QGraphicsItemGroup, then
2073     it defaults to return true.
2074
2075     \sa setHandlesChildEvents()
2076 */
2077 bool QGraphicsItem::handlesChildEvents() const
2078 {
2079     return d_ptr->handlesChildEvents;
2080 }
2081
2082 /*!
2083     If \a enabled is true, this item is set to handle all events for
2084     all its children (i.e., all events intented for any of its
2085     children are instead sent to this item); otherwise, if \a enabled
2086     is false, this item will only handle its own events. The default
2087     value is false.
2088
2089     This property is useful for item groups; it allows one item to
2090     handle events on behalf of its children, as opposed to its
2091     children handling their events individually.
2092
2093     If a child item accepts hover events, its parent will receive
2094     hover move events as the cursor passes through the child, but it
2095     does not receive hover enter and hover leave events on behalf of
2096     its child.
2097
2098     \sa handlesChildEvents()
2099 */
2100 void QGraphicsItem::setHandlesChildEvents(bool enabled)
2101 {
2102     if (d_ptr->handlesChildEvents == enabled)
2103         return;
2104
2105     d_ptr->handlesChildEvents = enabled;
2106     d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
2107 }
2108
2109 /*!
2110     Returns true if this item has keyboard input focus; otherwise, returns
2111     false.
2112
2113     \sa QGraphicsScene::focusItem(), setFocus(), QGraphicsScene::setFocusItem()
2114 */
2115 bool QGraphicsItem::hasFocus() const
2116 {
2117     return (d_ptr->scene && d_ptr->scene->focusItem() == this);
2118 }
2119
2120 /*!
2121     Gives keyboard input focus to this item. The \a focusReason argument will
2122     be passed into any focus event generated by this function; it is used to
2123     give an explanation of what caused the item to get focus.
2124
2125     Only items that set the ItemIsFocusable flag can accept keyboard focus.
2126
2127     If this item is not visible (i.e., isVisible() returns false), not
2128     enabled, not associated with a scene, or if it already has input focus,
2129     this function will do nothing.
2130
2131     As a result of calling this function, this item will receive a focus in
2132     event with \a focusReason. If another item already has focus, that item
2133     will first receive a focus out event indicating that it has lost input
2134     focus.
2135
2136     \sa clearFocus(), hasFocus()
2137 */
2138 void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
2139 {
2140     if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable))
2141         return;
2142     if (isVisible()) {
2143         // Visible items immediately gain focus from scene.
2144         d_ptr->scene->setFocusItem(this, focusReason);
2145     } else if (d_ptr->isWidget) {
2146         // Just set up subfocus.
2147         static_cast<QGraphicsWidget *>(this)->d_func()->setFocusWidget();
2148     }
2149 }
2150
2151 /*!
2152     Takes keyboard input focus from the item.
2153
2154     If it has focus, a focus out event is sent to this item to tell it that it
2155     is about to lose the focus.
2156
2157     Only items that set the ItemIsFocusable flag, or widgets that set an
2158     appropriate focus policy, can accept keyboard focus.
2159
2160     \sa setFocus(), QGraphicsWidget::focusPolicy
2161 */
2162 void QGraphicsItem::clearFocus()
2163 {
2164     if (!d_ptr->scene)
2165         return;
2166     if (d_ptr->isWidget) {
2167         // Invisible widget items with focus must explicitly clear subfocus.
2168         static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget();
2169     }
2170     if (d_ptr->scene->focusItem() == this) {
2171         // If this item has the scene's input focus, clear it.
2172         d_ptr->scene->setFocusItem(0);
2173     }
2174 }
2175
2176 /*!
2177     \since 4.4
2178     Grabs the mouse input.
2179
2180     This item will receive all mouse events for the scene until any of the
2181     following events occurs:
2182
2183     \list
2184     \o The item becomes invisible
2185     \o The item is removed from the scene
2186     \o The item is deleted
2187     \o The item call ungrabMouse()
2188     \o Another item calls grabMouse(); the item will regain the mouse grab
2189     when the other item calls ungrabMouse().
2190     \endlist
2191
2192     When an item gains the mouse grab, it receives a QEvent::GrabMouse
2193     event. When it loses the mouse grab, it receives a QEvent::UngrabMouse
2194     event. These events can be used to detect when your item gains or loses
2195     the mouse grab through other means than receiving mouse button events.
2196
2197     It is almost never necessary to explicitly grab the mouse in Qt, as Qt
2198     grabs and releases it sensibly. In particular, Qt grabs the mouse when you
2199     press a mouse button, and keeps the mouse grabbed until you release the
2200     last mouse button. Also, Qt::Popup widgets implicitly call grabMouse()
2201     when shown, and ungrabMouse() when hidden.
2202
2203     Note that only visible items can grab mouse input. Calling grabMouse() on
2204     an invisible item has no effect.
2205
2206     Keyboard events are not affected.
2207
2208     \sa QGraphicsScene::mouseGrabberItem(), ungrabMouse(), grabKeyboard()
2209 */
2210 void QGraphicsItem::grabMouse()
2211 {
2212     if (!d_ptr->scene) {
2213         qWarning("QGraphicsItem::grabMouse: cannot grab mouse without scene");
2214         return;
2215     }
2216     if (!d_ptr->visible) {
2217         qWarning("QGraphicsItem::grabMouse: cannot grab mouse while invisible");
2218         return;
2219     }
2220     d_ptr->scene->d_func()->grabMouse(this);
2221 }
2222
2223 /*!
2224     \since 4.4
2225     Releases the mouse grab.
2226
2227     \sa grabMouse(), ungrabKeyboard()
2228 */
2229 void QGraphicsItem::ungrabMouse()
2230 {
2231     if (!d_ptr->scene) {
2232         qWarning("QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene");
2233         return;
2234     }
2235     d_ptr->scene->d_func()->ungrabMouse(this);
2236 }
2237
2238 /*!
2239     \since 4.4
2240     Grabs the keyboard input.
2241
2242     The item will receive all keyboard input to the scene until one of the
2243     following events occur:
2244
2245     \list
2246     \o The item becomes invisible
2247     \o The item is removed from the scene
2248     \o The item is deleted
2249     \o The item calls ungrabKeyboard()
2250     \o Another item calls grabKeyboard(); the item will regain the keyboard grab
2251     when the other item calls ungrabKeyboard().
2252     \endlist
2253
2254     When an item gains the keyboard grab, it receives a QEvent::GrabKeyboard
2255     event. When it loses the keyboard grab, it receives a
2256     QEvent::UngrabKeyboard event. These events can be used to detect when your
2257     item gains or loses the keyboard grab through other means than gaining
2258     input focus.
2259
2260     It is almost never necessary to explicitly grab the keyboard in Qt, as Qt
2261     grabs and releases it sensibly. In particular, Qt grabs the keyboard when
2262     your item gains input focus, and releases it when your item loses input
2263     focus, or when the item is hidden.
2264
2265     Note that only visible items can grab keyboard input. Calling
2266     grabKeyboard() on an invisible item has no effect.
2267
2268     Keyboard events are not affected.
2269
2270     \sa ungrabKeyboard(), grabMouse(), setFocus()
2271 */
2272 void QGraphicsItem::grabKeyboard()
2273 {
2274     if (!d_ptr->scene) {
2275         qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard without scene");
2276         return;
2277     }
2278     if (!d_ptr->visible) {
2279         qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard while invisible");
2280         return;
2281     }
2282     d_ptr->scene->d_func()->grabKeyboard(this);
2283 }
2284
2285 /*!
2286     \since 4.4
2287     Releases the keyboard grab.
2288
2289     \sa grabKeyboard(), ungrabMouse()
2290 */
2291 void QGraphicsItem::ungrabKeyboard()
2292 {
2293     if (!d_ptr->scene) {
2294         qWarning("QGraphicsItem::ungrabKeyboard: cannot ungrab keyboard without scene");
2295         return;
2296     }
2297     d_ptr->scene->d_func()->ungrabKeyboard(this);
2298 }
2299
2300 /*!
2301     Returns the position of the item in parent coordinates. If the item has no
2302     parent, its position is given in scene coordinates.
2303
2304     The position of the item describes its origin (local coordinate
2305     (0, 0)) in parent coordinates; this function returns the same as
2306     mapToParent(0, 0).
2307
2308     For convenience, you can also call scenePos() to determine the
2309     item's position in scene coordinates, regardless of its parent.
2310
2311     \sa x(), y(), setPos(), matrix(), {The Graphics View Coordinate System}
2312 */
2313 QPointF QGraphicsItem::pos() const
2314 {
2315     return d_ptr->pos;
2316 }
2317
2318 /*!
2319     \fn QGraphicsItem::x() const
2320
2321     This convenience function is equivalent to calling pos().x().
2322
2323     \sa y()
2324 */
2325
2326 /*!
2327     \fn QGraphicsItem::y() const
2328
2329     This convenience function is equivalent to calling pos().y().
2330
2331     \sa x()
2332 */
2333
2334 /*!
2335     Returns the item's position in scene coordinates. This is
2336     equivalent to calling \c mapToScene(0, 0).
2337
2338     \sa pos(), sceneTransform(), {The Graphics View Coordinate System}
2339 */
2340 QPointF QGraphicsItem::scenePos() const
2341 {
2342     return mapToScene(0, 0);
2343 }
2344
2345 /*!
2346     \internal
2347
2348     Sets the position \a pos and notifies the change. If \a update is true,
2349     the item is also updated; otherwise it is not updated before and after the
2350     change.
2351 */
2352 void QGraphicsItemPrivate::setPosHelper(const QPointF &pos, bool update)
2353 {
2354     Q_Q(QGraphicsItem);
2355     if (this->pos == pos)
2356         return;
2357
2358     // Notify the item that the position is changing.
2359     QPointF newPos = q->itemChange(QGraphicsItem::ItemPositionChange, pos).toPointF();
2360     if (newPos == this->pos)
2361         return;
2362
2363     // Update and repositition.
2364     if (scene && update) {
2365         fullUpdateHelper(true);
2366         q->prepareGeometryChange();
2367     }
2368     this->pos = newPos;
2369     invalidateSceneTransformCache();
2370
2371     // Send post-notification.
2372     q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPos);
2373 }
2374
2375 /*!
2376     Sets the position of the item to \a pos, which is in parent
2377     coordinates.  For items with no parent, \a pos is in scene
2378     coordinates.
2379
2380     The position of the item describes its origin (local coordinate
2381     (0, 0)) in parent coordinates.
2382
2383     \sa pos(), scenePos(), {The Graphics View Coordinate System}
2384 */
2385 void QGraphicsItem::setPos(const QPointF &pos)
2386 {
2387     d_ptr->setPosHelper(pos, /* update = */ true);
2388 }
2389
2390 /*!
2391     \fn void QGraphicsItem::setPos(qreal x, qreal y)
2392     \overload
2393
2394     This convenience function is equivalent to calling setPos(QPointF(\a x, \a
2395     y)).
2396 */
2397
2398 /*!
2399     \fn void QGraphicsItem::moveBy(qreal dx, qreal dy)
2400
2401     Moves the item by \a dx points horizontally, and \a dy point
2402     vertically. This function is equivalent to calling setPos(pos() +
2403     QPointF(\a dx, \a dy)).
2404 */
2405
2406 /*!
2407     If this item is part of a scene that is viewed by a QGraphicsView, this
2408     convenience function will attempt to scroll the view to ensure that \a
2409     rect is visible inside the view's viewport. If \a rect is a null rect (the
2410     default), QGraphicsItem will default to the item's bounding rect. \a xmargin
2411     and \a ymargin are the number of pixels the view should use for margins.
2412
2413     If the specified rect cannot be reached, the contents are scrolled to the
2414     nearest valid position.
2415
2416     If this item is not viewed by a QGraphicsView, this function does nothing.
2417
2418     \sa QGraphicsView::ensureVisible()
2419 */
2420 void QGraphicsItem::ensureVisible(const QRectF &rect, int xmargin, int ymargin)
2421 {
2422     if (d_ptr->scene) {
2423         QRectF sceneRect;
2424         if (!rect.isNull())
2425             sceneRect = sceneTransform().mapRect(rect);
2426         else
2427             sceneRect = sceneBoundingRect();
2428         foreach (QGraphicsView *view, d_ptr->scene->d_func()->views)
2429             view->ensureVisible(sceneRect, xmargin, ymargin);
2430     }
2431 }
2432
2433 /*!
2434     \fn void QGraphicsItem::ensureVisible(qreal x, qreal y, qreal w, qreal h,
2435     int xmargin = 50, int ymargin = 50)
2436
2437     This convenience function is equivalent to calling
2438     ensureVisible(QRectF(\a x, \a y, \a w, \a h), \a xmargin, \a ymargin):
2439 */
2440
2441 /*!
2442     \obsolete
2443
2444     Returns the item's affine transformation matrix. This is a subset or the
2445     item's full transformation matrix, and might not represent the item's full
2446     transformation.
2447
2448     Use transform() instead.
2449
2450     \sa setTransform(), sceneTransform()
2451 */
2452 QMatrix QGraphicsItem::matrix() const
2453 {
2454     return transform().toAffine();
2455 }
2456
2457 /*!
2458     \since 4.3
2459
2460     Returns this item's transformation matrix. If no matrix has been set, the
2461     identity matrix is returned.
2462
2463     \sa setTransform(), sceneTransform()
2464 */
2465 QTransform QGraphicsItem::transform() const
2466 {
2467     if (!d_ptr->hasTransform)
2468         return QTransform();
2469     return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform));
2470 }
2471
2472 /*!
2473     \obsolete
2474
2475     Use sceneTransform() instead.
2476
2477     \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}
2478 */
2479 QMatrix QGraphicsItem::sceneMatrix() const
2480 {
2481     return sceneTransform().toAffine();
2482 }
2483
2484
2485 /*!
2486     \since 4.3
2487
2488     Returns this item's scene transformation matrix. This matrix can be used
2489     to map coordinates and geometrical shapes from this item's local
2490     coordinate system to the scene's coordinate system. To map coordinates
2491     from the scene, you must first invert the returned matrix.
2492
2493     Example:
2494
2495     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 4
2496
2497     Unlike transform(), which returns only an item's local transformation, this
2498     function includes the item's (and any parents') position.
2499
2500     \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}
2501 */
2502 QTransform QGraphicsItem::sceneTransform() const
2503 {
2504     // Check if there's any entry in the transform cache.
2505     QGraphicsScenePrivate *sd = d_ptr->scene ? d_ptr->scene->d_func() : 0;
2506     int index = d_ptr->sceneTransformIndex;
2507     if (sd && index != -1 && sd->validTransforms.testBit(index))
2508         return sd->sceneTransformCache[index];
2509
2510     // Calculate local transform.
2511     QTransform m;
2512     if (d_ptr->hasTransform) {
2513         m = transform();
2514         m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
2515     } else {
2516         // ### ? QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y())
2517         m.translate(d_ptr->pos.x(), d_ptr->pos.y());
2518     }
2519
2520     // Combine with parent and add to cache.
2521     if (d_ptr->parent) {
2522         m *= d_ptr->parent->sceneTransform();
2523         // Don't cache toplevels
2524         if (sd) {
2525             if (index == -1) {
2526                 if (!sd->freeSceneTransformSlots.isEmpty()) {
2527                     index = sd->freeSceneTransformSlots.last();
2528                     sd->freeSceneTransformSlots.pop_back();
2529                 } else {
2530                     index = sd->sceneTransformCache.size();
2531                 }
2532                 d_ptr->sceneTransformIndex = index;
2533                 if (index >= sd->validTransforms.size()) {
2534                     sd->validTransforms.resize(index + 1);
2535                     sd->sceneTransformCache.resize(index + 1);
2536                 }
2537             }
2538             sd->validTransforms.setBit(index, 1);
2539             sd->sceneTransformCache[index] = m;
2540         }
2541     }
2542     return m;
2543 }
2544
2545 /*!
2546     \since 4.3
2547
2548     Returns this item's device transformation matrix, using \a
2549     viewportTransform to map from scene to device coordinates. This matrix can
2550     be used to map coordinates and geometrical shapes from this item's local
2551     coordinate system to the viewport's (or any device's) coordinate
2552     system. To map coordinates from the viewport, you must first invert the
2553     returned matrix.
2554
2555     Example:
2556
2557     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 5
2558
2559     This function is the same as combining this item's scene transform with
2560     the view's viewport transform, but it also understands the
2561     ItemIgnoresTransformations flag. The device transform can be used to do
2562     accurate coordinate mapping (and collision detection) for untransformable
2563     items.
2564
2565     \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate
2566     System}, itemTransform()
2567 */
2568 QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const
2569 {
2570     // Find the topmost item that ignores view transformations.
2571     const QGraphicsItem *untransformedAncestor = this;
2572     QList<const QGraphicsItem *> parents;
2573     while (untransformedAncestor && ((untransformedAncestor->d_ptr->ancestorFlags
2574                                      & QGraphicsItemPrivate::AncestorIgnoresTransformations))) {
2575         parents.prepend(untransformedAncestor);
2576         untransformedAncestor = untransformedAncestor->parentItem();
2577     }
2578
2579     if (!untransformedAncestor) {
2580         // Assert in debug mode, continue in release.
2581         Q_ASSERT_X(untransformedAncestor, "QGraphicsItem::deviceTransform",
2582                    "Invalid object structure!");
2583         return QTransform();
2584     }
2585
2586     // First translate the base untransformable item.
2587     QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0));
2588     QTransform matrix;
2589     matrix.translate(mappedPoint.x(), mappedPoint.y());
2590     matrix = untransformedAncestor->transform() * matrix;
2591
2592     // Then transform and translate all children.
2593     for (int i = 0; i < parents.size(); ++i) {
2594         const QGraphicsItem *parent = parents.at(i);
2595         QPointF pos = parent->pos();
2596         QTransform moveMatrix;
2597         moveMatrix.translate(pos.x(), pos.y());
2598         matrix = (parent->transform() * moveMatrix) * matrix;
2599     }
2600
2601     return matrix;
2602 }
2603
2604 /*!
2605     \since 4.5
2606
2607     Returns a QTransform that maps coordinates from this item to \a other. If
2608     \a ok is not null, and if there is no such transform, the boolean pointed
2609     to by \a ok will be set to false; otherwise it will be set to true.
2610
2611     This transform provides an alternative to the mapToItem() or mapFromItem()
2612     functions, by returning the appropriate transform so that you can map
2613     shapes and coordinates yourself. It also helps you write more efficient
2614     code when repeatedly mapping between the same two items.
2615
2616     \note In rare circumstances, there is no transform that maps between two
2617     items.
2618
2619     \sa mapToItem(), mapFromItem(), deviceTransform()
2620 */
2621 QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) const
2622 {
2623     // Catch simple cases first.
2624     if (other == 0) {
2625         qWarning("QGraphicsItem::itemTransform: null pointer passed");
2626         return QTransform();
2627     }
2628     if (other == this) {
2629         if (ok)
2630             *ok = true;
2631         return QTransform();
2632     }
2633
2634     QGraphicsItem *parent = d_ptr->parent;
2635     const QGraphicsItem *otherParent = other->d_ptr->parent;
2636
2637     // This is other's child
2638     if (parent == other) {
2639         if (ok)
2640             *ok = true;
2641         const QPointF &itemPos = d_ptr->pos;
2642         if (d_ptr->hasTransform)
2643             return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y());
2644         return QTransform::fromTranslate(itemPos.x(), itemPos.y());
2645     }
2646
2647     // This is other's parent
2648     if (otherParent == this) {
2649         const QPointF &otherPos = other->d_ptr->pos;
2650         if (other->d_ptr->hasTransform) {
2651             QTransform otherToParent = other->transform();
2652             otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y());
2653             return otherToParent.inverted(ok);
2654         } else {
2655             if (ok)
2656                 *ok = true;
2657             return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
2658         }
2659     }
2660
2661     // Siblings
2662     if (parent == otherParent) {
2663         bool hasTr = d_ptr->hasTransform;
2664         bool otherHasTr = other->d_ptr->hasTransform;
2665         const QPointF &itemPos = d_ptr->pos;
2666         const QPointF &otherPos = other->d_ptr->pos;
2667
2668         if (!hasTr && !otherHasTr) {
2669             QPointF delta = itemPos - otherPos;
2670             if (ok)
2671                 *ok = true;
2672             return QTransform::fromTranslate(delta.x(), delta.y());
2673         }
2674
2675         QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y());
2676         if (hasTr)
2677             itemToParent = transform() * itemToParent;
2678
2679         QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y());
2680         if (otherHasTr)
2681             otherToParent = other->transform() * otherToParent;
2682
2683         return itemToParent * otherToParent.inverted(ok);
2684     }
2685
2686     // Find the closest common ancestor. If the two items don't share an
2687     // ancestor, then the only way is to combine their scene transforms.
2688     const QGraphicsItem *commonAncestor = commonAncestorItem(other);
2689     if (!commonAncestor)
2690         return sceneTransform() * other->sceneTransform().inverted(ok);
2691
2692     // If the two items are cousins (in sibling branches), map both to the
2693     // common ancestor, and combine the two transforms.
2694     bool cousins = other != commonAncestor && this != commonAncestor;
2695     if (cousins) {
2696         bool good = false;
2697         QTransform thisToScene;
2698         QTransform otherToScene;
2699         thisToScene = itemTransform(commonAncestor, &good);
2700         if (good)
2701             otherToScene = other->itemTransform(commonAncestor, &good);
2702         if (!good) {
2703             if (ok)
2704                 *ok = false;
2705             return QTransform();
2706         }
2707         return thisToScene * otherToScene.inverted(ok);
2708     }
2709
2710     // One is an ancestor of the other; walk the chain.
2711     bool parentOfOther = isAncestorOf(other);
2712     const QGraphicsItem *child = parentOfOther ? other : this;
2713     const QGraphicsItem *root = parentOfOther ? this : other;
2714
2715     QTransform x;
2716     const QGraphicsItem *p = child;
2717     do {
2718         const QGraphicsItemPrivate *pd = p->d_ptr;
2719         if (pd->hasTransform)
2720             x *= p->transform();
2721         x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y());
2722     } while ((p = p->d_ptr->parent) && p != root);
2723     if (parentOfOther)
2724         return x.inverted(ok);
2725     if (ok)
2726         *ok = true;
2727     return x;
2728 }
2729
2730 /*!
2731     \obsolete
27