1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
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 
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 the \l{Graphics View Framework}
54 
55     \image 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.
95     QGraphicsScene bases its item index on boundingRect(), and
96     QGraphicsView uses it both for culling invisible items, and for
97     determining the area that needs to be recomposed when drawing
98     overlapping items. In addition, QGraphicsItem's collision
99     detection mechanisms use boundingRect() to provide an efficient
100     cut-off. The fine grained collision algorithm in
101     collidesWithItem() is based on calling shape(), which returns an
102     accurate outline of the item's shape as a QPainterPath.
103 
104     QGraphicsScene expects all items boundingRect() and shape() to
105     remain unchanged unless it is notified. If you want to change an
106     item's geometry in any way, you must first call
107     prepareGeometryChange() to allow QGraphicsScene to update its
108     bookkeeping.
109 
110     Collision detection can be done in two ways:
111 
112     \list 1
113 
114     \o Reimplement shape() to return an accurate shape for your item,
115     and rely on the default implementation of collidesWithItem() to do
116     shape-shape intersection. This can be rather expensive if the
117     shapes are complex.
118 
119     \o Reimplement collidesWithItem() to provide your own custom item
120     and shape collision algorithm.
121 
122     \endlist
123 
124     The contains() function can be called to determine whether the item \e
125     contains a point or not. This function can also be reimplemented by the
126     item. The default behavior of contains() is based on calling shape().
127 
128     Items can contain other items, and also be contained by other items. All
129     items can have a parent item and a list of children. Unless the item has
130     no parent, its position is in \e parent coordinates (i.e., the parent's
131     local coordinates). Parent items propagate both their position and their
132     transformation to all children.
133 
134     \img graphicsview-parentchild.png
135 
136     \target Transformations
137     \section1 Transformations
138 
139     QGraphicsItem supports projective transformations in addition to its base
140     position, pos(). There are several ways to change an item's transformation.
141     For simple transformations, you can call either of the convenience
142     functions setRotation() or setScale(), or you can pass any transformation
143     matrix to setTransform(). For advanced transformation control you also have
144     the option of setting several combined transformations by calling
145     setTransformations().
146 
147     Item transformations accumulate from parent to child, so if both a parent
148     and child item are rotated 90 degrees, the child's total transformation
149     will be 180 degrees. Similarly, if the item's parent is scaled to 2x its
150     original size, its children will also be twice as large. An item's
151     transformation does not affect its own local geometry; all geometry
152     functions (e.g., contains(), update(), and all the mapping functions) still
153     operate in local coordinates. For convenience, QGraphicsItem provides the
154     functions sceneTransform(), which returns the item's total transformation
155     matrix (including its position and all parents' positions and
156     transformations), and scenePos(), which returns its position in scene
157     coordinates. To reset an item's matrix, call resetTransform().
158 
159     Certain transformation operations produce a different outcome depending on
160     the order in which they are applied. For example, if you scale an
161     transform, and then rotate it, you may get a different result than if the
162     transform was rotated first. However, the order you set the transformation
163     properties on QGraphicsItem does not affect the resulting transformation;
164     QGraphicsItem always applies the properties in a fixed, defined order:
165 
166     \list
167     \o The item's base transform is applied (transform())
168     \o The item's transformations list is applied in order (transformations())
169     \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint())
170     \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint())
171     \endlist
172 
173     \section1 Painting
174 
175     The paint() function is called by QGraphicsView to paint the item's
176     contents. The item has no background or default fill of its own; whatever
177     is behind the item will shine through all areas that are not explicitly
178     painted in this function.  You can call update() to schedule a repaint,
179     optionally passing the rectangle that needs a repaint. Depending on
180     whether or not the item is visible in a view, the item may or may not be
181     repainted; there is no equivalent to QWidget::repaint() in QGraphicsItem.
182 
183     Items are painted by the view, starting with the parent items and then
184     drawing children, in ascending stacking order. You can set an item's
185     stacking order by calling setZValue(), and test it by calling
186     zValue(), where items with low z-values are painted before items with
187     high z-values. Stacking order applies to sibling items; parents are always
188     drawn before their children.
189 
190     \section1 Sorting
191 
192     All items are drawn in a defined, stable order, and this same order decides
193     which items will receive mouse input first when you click on the scene.
194     Normally you don't have to worry about sorting, as the items follow a
195     "natural order", following the logical structure of the scene.
196 
197     An item's children are stacked on top of the parent, and sibling items are
198     stacked by insertion order (i.e., in the same order that they were either
199     added to the scene, or added to the same parent). If you add item A, and
200     then B, then B will be on top of A. If you then add C, the items' stacking
201     order will be A, then B, then C.
202 
203     \image graphicsview-zorder.png
204 
205     This example shows the stacking order of all limbs of the robot from the
206     \l{graphicsview/dragdroprobot}{Drag and Drop Robot} example. The torso is
207     the root item (all other items are children or descendants of the torso),
208     so it is drawn first. Next, the head is drawn, as it is the first item in
209     the torso's list of children. Then the upper left arm is drawn. As the
210     lower arm is a child of the upper arm, the lower arm is then drawn,
211     followed by the upper arm's next sibling, which is the upper right arm, and
212     so on.
213 
214     For advanced users, there are ways to alter how your items are sorted:
215 
216     \list
217     \o You can call setZValue() on an item to explicitly stack it on top of, or
218     under, other sibling items. The default Z value for an item is 0. Items
219     with the same Z value are stacked by insertion order.
220 
221     \o You can call stackBefore() to reorder the list of children. This will
222     directly modify the insertion order.
223 
224     \o You can set the ItemStacksBehindParent flag to stack a child item behind
225     its parent.
226     \endlist
227 
228     The stacking order of two sibling items also counts for each item's
229     children and descendant items. So if one item is on top of another, then
230     all its children will also be on top of all the other item's children as
231     well.
232 
233     \section1 Events
234 
235     QGraphicsItem receives events from QGraphicsScene through the virtual
236     function sceneEvent(). This function distributes the most common events
237     to a set of convenience event handlers:
238 
239     \list
240     \o contextMenuEvent() handles context menu events
241     \o focusInEvent() and focusOutEvent() handle focus in and out events
242     \o hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() handles
243     hover enter, move and leave events
244     \o inputMethodEvent() handles input events, for accessibility support
245     \o keyPressEvent() and keyReleaseEvent() handle key press and release events
246     \o mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and
247     mouseDoubleClickEvent() handles mouse press, move, release, click and
248     doubleclick events
249     \endlist
250 
251     You can filter events for any other item by installing event filters. This
252     functionality is separate from Qt's regular event filters (see
253     QObject::installEventFilter()), which only work on subclasses of QObject. After
254     installing your item as an event filter for another item by calling
255     installSceneEventFilter(), the filtered events will be received by the virtual
256     function sceneEventFilter(). You can remove item event filters by calling
257     removeSceneEventFilter().
258 
259     \section1 Custom Data
260 
261     Sometimes it's useful to register custom data with an item, be it a custom
262     item, or a standard item. You can call setData() on any item to store data
263     in it using a key-value pair (the key being an integer, and the value is a
264     QVariant). To get custom data from an item, call data(). This
265     functionality is completely untouched by Qt itself; it is provided for the
266     user's convenience.
267 
268     \sa QGraphicsScene, QGraphicsView, {Graphics View Framework}
269 */
270 
271 /*!
272     \variable QGraphicsItem::Type
273 
274     The type value returned by the virtual type() function in standard
275     graphics item classes in Qt. All such standard graphics item
276     classes in Qt are associated with a unique value for Type,
277     e.g. the value returned by QGraphicsPathItem::type() is 2.
278 
279     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 18
280 */
281 
282 /*!
283     \variable QGraphicsItem::UserType
284 
285     The lowest permitted type value for custom items (subclasses
286     of QGraphicsItem or any of the standard items). This value is
287     used in conjunction with a reimplementation of QGraphicsItem::type()
288     and declaring a Type enum value. Example:
289 
290     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 1
291 
292     \note UserType = 65536
293 */
294 
295 /*!
296     \enum QGraphicsItem::GraphicsItemFlag
297 
298     This enum describes different flags that you can set on an item to
299     toggle different features in the item's behavior.
300 
301     All flags are disabled by default.
302 
303     \value ItemIsMovable The item supports interactive movement using
304     the mouse. By clicking on the item and then dragging, the item
305     will move together with the mouse cursor. If the item has
306     children, all children are also moved. If the item is part of a
307     selection, all selected items are also moved. This feature is
308     provided as a convenience through the base implementation of
309     QGraphicsItem's mouse event handlers.
310 
311     \value ItemIsSelectable The item supports selection. Enabling this
312     feature will enable setSelected() to toggle selection for the
313     item. It will also let the item be selected automatically as a
314     result of calling QGraphicsScene::setSelectionArea(), by clicking
315     on an item, or by using rubber band selection in QGraphicsView.
316 
317     \value ItemIsFocusable The item supports keyboard input focus (i.e., it is
318     an input item). Enabling this flag will allow the item to accept focus,
319     which again allows the delivery of key events to
320     QGraphicsItem::keyPressEvent() and QGraphicsItem::keyReleaseEvent().
321 
322     \value ItemClipsToShape The item clips to its own shape. The item cannot
323     draw or receive mouse, tablet, drag and drop or hover events outside its
324     shape. It is disabled by default. This behavior is enforced by
325     QGraphicsView::drawItems() or QGraphicsScene::drawItems(). This flag was
326     introduced in Qt 4.3.
327 
328     \value ItemClipsChildrenToShape The item clips the painting of all its
329     descendants to its own shape. Items that are either direct or indirect
330     children of this item cannot draw outside this item's shape. By default,
331     this flag is disabled; children can draw anywhere. This behavior is
332     enforced by QGraphicsView::drawItems() or
333     QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3.
334 
335     \value ItemIgnoresTransformations The item ignores inherited
336     transformations (i.e., its position is still anchored to its parent, but
337     the parent or view rotation, zoom or shear transformations are ignored).
338     This flag is useful for keeping text label items horizontal and unscaled,
339     so they will still be readable if the view is transformed.  When set, the
340     item's view geometry and scene geometry will be maintained separately. You
341     must call deviceTransform() to map coordinates and detect collisions in
342     the view. By default, this flag is disabled. This flag was introduced in
343     Qt 4.3. \note With this flag set you can still scale the item itself, and
344     that scale transformation will influence the item's children.
345 
346     \value ItemIgnoresParentOpacity The item ignores its parent's opacity. The
347     item's effective opacity is the same as its own; it does not combine with
348     the parent's opacity. This flags allows your item to keep its absolute
349     opacity even if the parent is semitransparent. This flag was introduced in
350     Qt 4.5.
351 
352     \value ItemDoesntPropagateOpacityToChildren The item doesn't propagate its
353     opacity to its children. This flag allows you to create a semitransparent
354     item that does not affect the opacity of its children. This flag was
355     introduced in Qt 4.5.
356 
357     \value ItemStacksBehindParent The item is stacked behind its parent. By
358     default, child items are stacked on top of the parent item. But setting
359     this flag, the child will be stacked behind it. This flag is useful for
360     drop shadow effects and for decoration objects that follow the parent
361     item's geometry without drawing on top of it. This flag was introduced
362     in Qt 4.5.
363 
364     \value ItemUsesExtendedStyleOption The item makes use of either
365     \l{QStyleOptionGraphicsItem::} {exposedRect} or
366     \l{QStyleOptionGraphicsItem::} {matrix} in
367     QStyleOptionGraphicsItem. By default, the
368     \l{QStyleOptionGraphicsItem::} {exposedRect} is initialized to the
369     item's boundingRect() and the
370     \l{QStyleOptionGraphicsItem::}{matrix} is untransformed.  You can
371     enable this flag for the style options to be set up with more
372     fine-grained values.  Note that
373     QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag
374     and always initialized to 1. Use
375     QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need
376     a higher value. This flag was introduced in Qt 4.6.
377 
378     \value ItemHasNoContents The item does not paint anything (i.e., calling
379     paint() on the item has no effect). You should set this flag on items that
380     do not need to be painted to ensure that Graphics View avoids unnecessary
381     painting preparations. This flag was introduced in Qt 4.6.
382 
383     \value ItemSendsGeometryChanges The item enables itemChange()
384     notifications for ItemPositionChange, ItemPositionHasChanged,
385     ItemMatrixChange, ItemTransformChange, ItemTransformHasChanged,
386     ItemRotationChange, ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged,
387     ItemTransformOriginPointChange, and ItemTransformOriginPointHasChanged. For
388     performance reasons, these notifications are disabled by default. You must
389     enable this flag to receive notifications for position and transform
390     changes. This flag was introduced in Qt 4.6.
391 
392     \value ItemAcceptsInputMethod The item supports input methods typically
393     used for Asian languages.
394     This flag was introduced in Qt 4.6.
395 
396     \value ItemNegativeZStacksBehindParent The item automatically
397     stacks behind it's parent if it's z-value is negative. This flag
398     enables setZValue() to toggle ItemStacksBehindParent. This flag
399     was introduced in Qt 4.6.
400 
401     \value ItemIsPanel The item is a panel. A panel provides activation and
402     contained focus handling. Only one panel can be active at a time (see
403     QGraphicsItem::isActive()). When no panel is active, QGraphicsScene
404     activates all non-panel items. Window items (i.e.,
405     QGraphicsItem::isWindow() returns true) are panels. This flag was
406     introduced in Qt 4.6.
407 
408     \omitvalue ItemIsFocusScope \omit Internal only (for now). \endomit
409 
410     \value ItemSendsScenePositionChanges The item enables itemChange()
411     notifications for ItemScenePositionHasChanged. For performance reasons,
412     these notifications are disabled by default. You must enable this flag
413     to receive notifications for scene position changes. This flag was
414     introduced in Qt 4.6.
415 
416     \omitvalue ItemStopsClickFocusPropagation \omit The item stops propagating
417     click focus to items underneath when being clicked on. This flag
418     allows you create a non-focusable item that can be clicked on without
419     changing the focus. \endomit
420 
421     \omitvalue ItemStopsFocusHandling \omit Same as
422     ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag
423     allows you to completely take over focus handling.
424     This flag was introduced in Qt 4.7. \endomit
425 */
426 
427 /*!
428     \enum QGraphicsItem::GraphicsItemChange
429 
430     This enum describes the state changes that are notified by
431     QGraphicsItem::itemChange(). The notifications are sent as the state
432     changes, and in some cases, adjustments can be made (see the documentation
433     for each change for details).
434 
435     Note: Be careful with calling functions on the QGraphicsItem itself inside
436     itemChange(), as certain function calls can lead to unwanted
437     recursion. For example, you cannot call setPos() in itemChange() on an
438     ItemPositionChange notification, as the setPos() function will again call
439     itemChange(ItemPositionChange). Instead, you can return the new, adjusted
440     position from itemChange().
441 
442     \value ItemEnabledChange The item's enabled state changes. If the item is
443     presently enabled, it will become disabled, and vice verca. The value
444     argument is the new enabled state (i.e., true or false). Do not call
445     setEnabled() in itemChange() as this notification is delivered. Instead,
446     you can return the new state from itemChange().
447 
448     \value ItemEnabledHasChanged The item's enabled state has changed. The
449     value argument is the new enabled state (i.e., true or false). Do not call
450     setEnabled() in itemChange() as this notification is delivered. The return
451     value is ignored.
452 
453     \value ItemMatrixChange The item's affine transformation matrix is
454     changing. This value is obsolete; you can use ItemTransformChange instead.
455 
456     \value ItemPositionChange The item's position changes. This notification
457     is sent if the ItemSendsGeometryChanges flag is enabled, and when the
458     item's local position changes, relative to its parent (i.e., as a result
459     of calling setPos() or moveBy()). The value argument is the new position
460     (i.e., a QPointF).  You can call pos() to get the original position. Do
461     not call setPos() or moveBy() in itemChange() as this notification is
462     delivered; instead, you can return the new, adjusted position from
463     itemChange(). After this notification, QGraphicsItem immediately sends the
464     ItemPositionHasChanged notification if the position changed.
465 
466     \value ItemPositionHasChanged The item's position has changed. This
467     notification is sent if the ItemSendsGeometryChanges flag is enabled, and
468     after the item's local position, relative to its parent, has changed. The
469     value argument is the new position (the same as pos()), and QGraphicsItem
470     ignores the return value for this notification (i.e., a read-only
471     notification).
472 
473     \value ItemTransformChange The item's transformation matrix changes. This
474     notification is send if the ItemSendsGeometryChanges flag is enabled, and
475     when the item's local transformation matrix changes (i.e., as a result of
476     calling setTransform(). The value argument is the new matrix (i.e., a
477     QTransform); to get the old matrix, call transform(). Do not call
478     setTransform() or set any of the transformation properties in itemChange()
479     as this notification is delivered; instead, you can return the new matrix
480     from itemChange().  This notification is not sent if you change the
481     transformation properties.
482 
483     \value ItemTransformHasChanged The item's transformation matrix has
484     changed either because setTransform is called, or one of the
485     transformation properties is changed. This notification is sent if the
486     ItemSendsGeometryChanges flag is enabled, and after the item's local
487     transformation matrix has changed. The value argument is the new matrix
488     (same as transform()), and QGraphicsItem ignores the return value for this
489     notification (i.e., a read-only notification).
490 
491     \value ItemRotationChange The item's rotation property changes. This
492     notification is sent if the ItemSendsGeometryChanges flag is enabled, and
493     when the item's rotation property changes (i.e., as a result of calling
494     setRotation()). The value argument is the new rotation (i.e., a double);
495     to get the old rotation, call rotation(). Do not call setRotation() in
496     itemChange() as this notification is delivered; instead, you can return
497     the new rotation from itemChange().
498 
499     \value ItemRotationHasChanged The item's rotation property has changed.
500     This notification is sent if the ItemSendsGeometryChanges flag is enabled,
501     and after the item's rotation property has changed. The value argument is
502     the new rotation (i.e., a double), and QGraphicsItem ignores the return
503     value for this notification (i.e., a read-only notification). Do not call
504     setRotation() in itemChange() as this notification is delivered.
505 
506     \value ItemScaleChange The item's scale property changes. This notification
507     is sent if the ItemSendsGeometryChanges flag is enabled, and when the item's
508     scale property changes (i.e., as a result of calling setScale()). The value
509     argument is the new scale (i.e., a double); to get the old scale, call
510     scale(). Do not call setScale() in itemChange() as this notification is
511     delivered; instead, you can return the new scale from itemChange().
512 
513     \value ItemScaleHasChanged The item's scale property has changed. This
514     notification is sent if the ItemSendsGeometryChanges flag is enabled, and
515     after the item's scale property has changed. The value argument is the new
516     scale (i.e., a double), and QGraphicsItem ignores the return value for this
517     notification (i.e., a read-only notification). Do not call setScale() in
518     itemChange() as this notification is delivered.
519 
520     \value ItemTransformOriginPointChange The item's transform origin point
521     property changes. This notification is sent if the ItemSendsGeometryChanges
522     flag is enabled, and when the item's transform origin point property changes
523     (i.e., as a result of calling setTransformOriginPoint()). The value argument
524     is the new origin point (i.e., a QPointF); to get the old origin point, call
525     transformOriginPoint(). Do not call setTransformOriginPoint() in itemChange()
526     as this notification is delivered; instead, you can return the new transform
527     origin point from itemChange().
528 
529     \value ItemTransformOriginPointHasChanged The item's transform origin point
530     property has changed. This notification is sent if the ItemSendsGeometryChanges
531     flag is enabled, and after the item's transform origin point property has
532     changed. The value argument is the new origin point (i.e., a QPointF), and
533     QGraphicsItem ignores the return value for this notification (i.e., a read-only
534     notification). Do not call setTransformOriginPoint() in itemChange() as this
535     notification is delivered.
536 
537     \value ItemSelectedChange The item's selected state changes. If the item is
538     presently selected, it will become unselected, and vice verca. The value
539     argument is the new selected state (i.e., true or false). Do not call
540     setSelected() in itemChange() as this notification is delivered; instead, you
541     can return the new selected state from itemChange().
542 
543     \value ItemSelectedHasChanged The item's selected state has changed. The
544     value argument is the new selected state (i.e., true or false). Do not
545     call setSelected() in itemChange() as this notification is delivered. The
546     return value is ignored.
547 
548     \value ItemVisibleChange The item's visible state changes. If the item is
549     presently visible, it will become invisible, and vice verca. The value
550     argument is the new visible state (i.e., true or false). Do not call
551     setVisible() in itemChange() as this notification is delivered; instead,
552     you can return the new visible state from itemChange().
553 
554     \value ItemVisibleHasChanged The item's visible state has changed. The
555     value argument is the new visible state (i.e., true or false). Do not call
556     setVisible() in itemChange() as this notification is delivered. The return
557     value is ignored.
558 
559     \value ItemParentChange The item's parent changes. The value argument is
560     the new parent item (i.e., a QGraphicsItem pointer).  Do not call
561     setParentItem() in itemChange() as this notification is delivered;
562     instead, you can return the new parent from itemChange().
563 
564     \value ItemParentHasChanged The item's parent has changed. The value
565     argument is the new parent (i.e., a pointer to a QGraphicsItem). Do not
566     call setParentItem() in itemChange() as this notification is
567     delivered. The return value is ignored.
568 
569     \value ItemChildAddedChange A child is added to this item. The value
570     argument is the new child item (i.e., a QGraphicsItem pointer). Do not
571     pass this item to any item's setParentItem() function as this notification
572     is delivered. The return value is unused; you cannot adjust anything in
573     this notification. Note that the new child might not be fully constructed
574     when this notification is sent; calling pure virtual functions on
575     the child can lead to a crash.
576 
577     \value ItemChildRemovedChange A child is removed from this item. The value
578     argument is the child item that is about to be removed (i.e., a
579     QGraphicsItem pointer). The return value is unused; you cannot adjust
580     anything in this notification.
581 
582     \value ItemSceneChange The item is moved to a new scene. This notification is
583     also sent when the item is added to its initial scene, and when it is removed.
584     The item's scene() is the old scene (or 0 if the item has not been added to a
585     scene yet). The value argument is the new scene (i.e., a QGraphicsScene
586     pointer), or a null pointer if the item is removed from a scene. Do not
587     override this change by passing this item to QGraphicsScene::addItem() as this
588     notification is delivered; instead, you can return the new scene from
589     itemChange(). Use this feature with caution; objecting to a scene change can
590     quickly lead to unwanted recursion.
591 
592     \value ItemSceneHasChanged The item's scene has changed. The item's scene() is
593     the new scene. This notification is also sent when the item is added to its
594     initial scene, and when it is removed.The value argument is the new scene
595     (i.e., a pointer to a QGraphicsScene). Do not call setScene() in itemChange()
596     as this notification is delivered. The return value is ignored.
597 
598     \value ItemCursorChange The item's cursor changes. The value argument is
599     the new cursor (i.e., a QCursor). Do not call setCursor() in itemChange()
600     as this notification is delivered. Instead, you can return a new cursor
601     from itemChange().
602 
603     \value ItemCursorHasChanged The item's cursor has changed. The value
604     argument is the new cursor (i.e., a QCursor). Do not call setCursor() as
605     this notification is delivered. The return value is ignored.
606 
607     \value ItemToolTipChange The item's tooltip changes. The value argument is
608     the new tooltip (i.e., a QToolTip). Do not call setToolTip() in
609     itemChange() as this notification is delivered. Instead, you can return a
610     new tooltip from itemChange().
611 
612     \value ItemToolTipHasChanged The item's tooltip has changed. The value
613     argument is the new tooltip (i.e., a QToolTip). Do not call setToolTip()
614     as this notification is delivered. The return value is ignored.
615 
616     \value ItemFlagsChange The item's flags change. The value argument is the
617     new flags (i.e., a quint32). Do not call setFlags() in itemChange() as
618     this notification is delivered. Instead, you can return the new flags from
619     itemChange().
620 
621     \value ItemFlagsHaveChanged The item's flags have changed. The value
622     argument is the new flags (i.e., a quint32). Do not call setFlags() in
623     itemChange() as this notification is delivered. The return value is
624     ignored.
625 
626     \value ItemZValueChange The item's Z-value changes. The value argument is
627     the new Z-value (i.e., a double). Do not call setZValue() in itemChange()
628     as this notification is delivered. Instead, you can return a new Z-value
629     from itemChange().
630 
631     \value ItemZValueHasChanged The item's Z-value has changed. The value
632     argument is the new Z-value (i.e., a double). Do not call setZValue() as
633     this notification is delivered. The return value is ignored.
634 
635     \value ItemOpacityChange The item's opacity changes. The value argument is
636     the new opacity (i.e., a double). Do not call setOpacity() in itemChange()
637     as this notification is delivered. Instead, you can return a new opacity
638     from itemChange().
639 
640     \value ItemOpacityHasChanged The item's opacity has changed. The value
641     argument is the new opacity (i.e., a double). Do not call setOpacity() as
642     this notification is delivered. The return value is ignored.
643 
644     \value ItemScenePositionHasChanged The item's scene position has changed.
645     This notification is sent if the ItemSendsScenePositionChanges flag is
646     enabled, and after the item's scene position has changed (i.e., the
647     position or transformation of the item itself or the position or
648     transformation of any ancestor has changed). The value argument is the
649     new scene position (the same as scenePos()), and QGraphicsItem ignores
650     the return value for this notification (i.e., a read-only notification).
651 */
652 
653 /*!
654     \enum QGraphicsItem::CacheMode
655     \since 4.4
656 
657     This enum describes QGraphicsItem's cache modes. Caching is used to speed
658     up rendering by allocating and rendering to an off-screen pixel buffer,
659     which can be reused when the item requires redrawing. For some paint
660     devices, the cache is stored directly in graphics memory, which makes
661     rendering very quick.
662 
663     \value NoCache The default; all item caching is
664     disabled. QGraphicsItem::paint() is called every time the item needs
665     redrawing.
666 
667     \value ItemCoordinateCache Caching is enabled for the item's logical
668     (local) coordinate system. QGraphicsItem creates an off-screen pixel
669     buffer with a configurable size / resolution that you can pass to
670     QGraphicsItem::setCacheMode(). Rendering quality will typically degrade,
671     depending on the resolution of the cache and the item transformation.  The
672     first time the item is redrawn, it will render itself into the cache, and
673     the cache is then reused for every subsequent expose. The cache is also
674     reused as the item is transformed. To adjust the resolution of the cache,
675     you can call setCacheMode() again.
676 
677     \value DeviceCoordinateCache Caching is enabled at the paint device level,
678     in device coordinates. This mode is for items that can move, but are not
679     rotated, scaled or sheared. If the item is transformed directly or
680     indirectly, the cache will be regenerated automatically. Unlike
681     ItemCoordinateCacheMode, DeviceCoordinateCache always renders at maximum
682     quality.
683 
684     \sa QGraphicsItem::setCacheMode()
685 */
686 
687 /*!
688     \enum QGraphicsItem::Extension
689     \internal
690 
691     Note: This is provided as a hook to avoid future problems related
692     to adding virtual functions. See also extension(),
693     supportsExtension() and setExtension().
694 */
695 
696 /*!
697     \enum QGraphicsItem::PanelModality
698     \since 4.6
699 
700     This enum specifies the behavior of a modal panel. A modal panel
701     is one that blocks input to other panels. Note that items that
702     are children of a modal panel are not blocked.
703 
704     The values are:
705 
706     \value NonModal The panel is not modal and does not block input to
707     other panels. This is the default value for panels.
708 
709     \value PanelModal The panel is modal to a single item hierarchy
710     and blocks input to its parent pane, all grandparent panels, and
711     all siblings of its parent and grandparent panels.
712 
713     \value SceneModal The window is modal to the entire scene and
714     blocks input to all panels.
715 
716     \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel
717 */
718 
719 #include "qgraphicsitem.h"
720 
721 #ifndef QT_NO_GRAPHICSVIEW
722 
723 #include "qgraphicsscene.h"
724 #include "qgraphicsscene_p.h"
725 #include "qgraphicssceneevent.h"
726 #include "qgraphicsview.h"
727 #include "qgraphicswidget.h"
728 #include "qgraphicsproxywidget.h"
729 #include "qgraphicsscenebsptreeindex_p.h"
730 #include <QtCore/qbitarray.h>
731 #include <QtCore/qdebug.h>
732 #include <QtCore/qpoint.h>
733 #include <QtCore/qstack.h>
734 #include <QtCore/qtimer.h>
735 #include <QtCore/qvariant.h>
736 #include <QtCore/qvarlengtharray.h>
737 #include <QtCore/qnumeric.h>
738 #include <QtGui/qapplication.h>
739 #include <QtGui/qbitmap.h>
740 #include <QtGui/qpainter.h>
741 #include <QtGui/qpainterpath.h>
742 #include <QtGui/qpixmapcache.h>
743 #include <QtGui/qstyleoption.h>
744 #include <QtGui/qevent.h>
745 #include <QtGui/qinputcontext.h>
746 #include <QtGui/qgraphicseffect.h>
747 #ifndef QT_NO_ACCESSIBILITY
748 # include "qaccessible.h"
749 #endif
750 
751 #include <private/qgraphicsitem_p.h>
752 #include <private/qgraphicswidget_p.h>
753 #include <private/qtextcontrol_p.h>
754 #include <private/qtextdocumentlayout_p.h>
755 #include <private/qtextengine_p.h>
756 #include <private/qwidget_p.h>
757 #include <private/qapplication_p.h>
758 
759 #ifdef Q_WS_X11
760 #include <private/qt_x11_p.h>
761 #include <private/qpixmap_x11_p.h>
762 #endif
763 
764 #include <private/qgesturemanager_p.h>
765 
766 #include <math.h>
767 
768 QT_BEGIN_NAMESPACE
769 
_q_adjustRect(QRect * rect)770 static inline void _q_adjustRect(QRect *rect)
771 {
772     Q_ASSERT(rect);
773     if (!rect->width())
774         rect->adjust(0, 0, 1, 0);
775     if (!rect->height())
776         rect->adjust(0, 0, 0, 1);
777 }
778 
779 /*
780     ### Move this into QGraphicsItemPrivate
781  */
782 class QGraphicsItemCustomDataStore
783 {
784 public:
785     QMap<const QGraphicsItem *, QMap<int, QVariant> > data;
786 };
Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore,qt_dataStore)787 Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)
788 
789 /*!
790     \internal
791 
792     Returns a QPainterPath of \a path when stroked with the \a pen.
793     Ignoring dash pattern.
794 */
795 static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen)
796 {
797     // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
798     // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
799     const qreal penWidthZero = qreal(0.00000001);
800 
801     if (path == QPainterPath())
802         return path;
803     QPainterPathStroker ps;
804     ps.setCapStyle(pen.capStyle());
805     if (pen.widthF() <= 0.0)
806         ps.setWidth(penWidthZero);
807     else
808         ps.setWidth(pen.widthF());
809     ps.setJoinStyle(pen.joinStyle());
810     ps.setMiterLimit(pen.miterLimit());
811     QPainterPath p = ps.createStroke(path);
812     p.addPath(path);
813     return p;
814 }
815 
816 /*!
817     \internal
818 
819     Propagates the ancestor flag \a flag with value \a enabled to all this
820     item's children. If \a root is false, the flag is also set on this item
821     (default is true).
822 */
updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,AncestorFlag flag,bool enabled,bool root)823 void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
824                                            AncestorFlag flag, bool enabled, bool root)
825 {
826     Q_Q(QGraphicsItem);
827     if (root) {
828         // For root items only. This is the item that has either enabled or
829         // disabled \a childFlag, or has been reparented.
830         switch (int(childFlag)) {
831         case -2:
832             flag = AncestorFiltersChildEvents;
833             enabled = q->filtersChildEvents();
834             break;
835         case -1:
836             flag = AncestorHandlesChildEvents;
837             enabled = q->handlesChildEvents();
838             break;
839         case QGraphicsItem::ItemClipsChildrenToShape:
840             flag = AncestorClipsChildren;
841             enabled = flags & QGraphicsItem::ItemClipsChildrenToShape;
842             break;
843         case QGraphicsItem::ItemIgnoresTransformations:
844             flag = AncestorIgnoresTransformations;
845             enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
846             break;
847         default:
848             return;
849         }
850 
851         if (parent) {
852             // Inherit the enabled-state from our parents.
853             if ((parent->d_ptr->ancestorFlags & flag)
854                     || (int(parent->d_ptr->flags & childFlag) == childFlag)
855                         || (childFlag == -1 && parent->d_ptr->handlesChildEvents)
856                         || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)) {
857                 enabled = true;
858                 ancestorFlags |= flag;
859             } else {
860                 ancestorFlags &= ~flag;
861             }
862         } else {
863             // Top-level root items don't have any ancestors, so there are no
864             // ancestor flags either.
865             ancestorFlags = 0;
866         }
867     } else {
868         // Don't set or propagate the ancestor flag if it's already correct.
869         if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled))
870             return;
871 
872         // Set the flag.
873         if (enabled)
874             ancestorFlags |= flag;
875         else
876             ancestorFlags &= ~flag;
877 
878         // Don't process children if the item has the main flag set on itself.
879         if ((childFlag != -1 &&  int(flags & childFlag) == childFlag)
880             || (int(childFlag) == -1 && handlesChildEvents)
881             || (int(childFlag) == -2 && filtersDescendantEvents))
882             return;
883     }
884 
885     for (int i = 0; i < children.size(); ++i)
886         children.at(i)->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false);
887 }
888 
updateAncestorFlags()889 void QGraphicsItemPrivate::updateAncestorFlags()
890 {
891     int flags = 0;
892     if (parent) {
893         // Inherit the parent's ancestor flags.
894         QGraphicsItemPrivate *pd = parent->d_ptr.data();
895         flags = pd->ancestorFlags;
896 
897         // Add in flags from the parent.
898         if (pd->filtersDescendantEvents)
899             flags |= AncestorFiltersChildEvents;
900         if (pd->handlesChildEvents)
901             flags |= AncestorHandlesChildEvents;
902         if (pd->flags & QGraphicsItem::ItemClipsChildrenToShape)
903             flags |= AncestorClipsChildren;
904         if (pd->flags & QGraphicsItem::ItemIgnoresTransformations)
905             flags |= AncestorIgnoresTransformations;
906     }
907 
908     if (ancestorFlags == flags)
909         return; // No change; stop propagation.
910     ancestorFlags = flags;
911 
912     // Propagate to children recursively.
913     for (int i = 0; i < children.size(); ++i)
914         children.at(i)->d_ptr->updateAncestorFlags();
915 }
916 
917 /*!
918     \internal
919 
920     Propagates item group membership.
921 */
setIsMemberOfGroup(bool enabled)922 void QGraphicsItemPrivate::setIsMemberOfGroup(bool enabled)
923 {
924     Q_Q(QGraphicsItem);
925     isMemberOfGroup = enabled;
926     if (!qgraphicsitem_cast<QGraphicsItemGroup *>(q)) {
927         foreach (QGraphicsItem *child, children)
928             child->d_func()->setIsMemberOfGroup(enabled);
929     }
930 }
931 
932 /*!
933     \internal
934 
935     Maps any item pos properties of \a event to \a item's coordinate system.
936 */
remapItemPos(QEvent * event,QGraphicsItem * item)937 void QGraphicsItemPrivate::remapItemPos(QEvent *event, QGraphicsItem *item)
938 {
939     Q_Q(QGraphicsItem);
940     switch (event->type()) {
941     case QEvent::GraphicsSceneMouseMove:
942     case QEvent::GraphicsSceneMousePress:
943     case QEvent::GraphicsSceneMouseRelease:
944     case QEvent::GraphicsSceneMouseDoubleClick: {
945         QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
946         mouseEvent->setPos(item->mapFromItem(q, mouseEvent->pos()));
947         mouseEvent->setLastPos(item->mapFromItem(q, mouseEvent->pos()));
948         for (int i = 0x1; i <= 0x10; i <<= 1) {
949             if (mouseEvent->buttons() & i) {
950                 Qt::MouseButton button = Qt::MouseButton(i);
951                 mouseEvent->setButtonDownPos(button, item->mapFromItem(q, mouseEvent->buttonDownPos(button)));
952             }
953         }
954         break;
955     }
956     case QEvent::GraphicsSceneWheel: {
957         QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event);
958         wheelEvent->setPos(item->mapFromItem(q, wheelEvent->pos()));
959         break;
960     }
961     case QEvent::GraphicsSceneContextMenu: {
962         QGraphicsSceneContextMenuEvent *contextEvent = static_cast<QGraphicsSceneContextMenuEvent *>(event);
963         contextEvent->setPos(item->mapFromItem(q, contextEvent->pos()));
964         break;
965     }
966     case QEvent::GraphicsSceneHoverMove: {
967         QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
968         hoverEvent->setPos(item->mapFromItem(q, hoverEvent->pos()));
969         break;
970     }
971     default:
972         break;
973     }
974 }
975 
976 /*!
977     \internal
978 
979     Maps the point \a pos from scene to item coordinates. If \a view is passed and the item
980     is untransformable, this function will correctly map \a pos from the scene using the
981     view's transformation.
982 */
genericMapFromScene(const QPointF & pos,const QWidget * viewport) const983 QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos,
984                                                   const QWidget *viewport) const
985 {
986     Q_Q(const QGraphicsItem);
987     if (!itemIsUntransformable())
988         return q->mapFromScene(pos);
989     QGraphicsView *view = 0;
990     if (viewport)
991         view = qobject_cast<QGraphicsView *>(viewport->parentWidget());
992     if (!view)
993         return q->mapFromScene(pos);
994     // ### More ping pong than needed.
995     return q->deviceTransform(view->viewportTransform()).inverted().map(view->mapFromScene(pos));
996 }
997 
998 /*!
999     \internal
1000 
1001     Combines this item's position and transform onto \a transform.
1002 
1003     If you need to change this function (e.g., adding more transformation
1004     modes / options), make sure to change all places marked with COMBINE.
1005 */
combineTransformToParent(QTransform * x,const QTransform * viewTransform) const1006 void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const
1007 {
1008     // COMBINE
1009     if (viewTransform && itemIsUntransformable()) {
1010         *x = q_ptr->deviceTransform(*viewTransform);
1011     } else {
1012         if (transformData)
1013             *x *= transformData->computedFullTransform();
1014         if (!pos.isNull())
1015             *x *= QTransform::fromTranslate(pos.x(), pos.y());
1016     }
1017 }
1018 
1019 /*!
1020     \internal
1021 
1022     Combines this item's position and transform onto \a transform.
1023 
1024     If you need to change this function (e.g., adding more transformation
1025     modes / options), make sure to change QGraphicsItem::deviceTransform() as
1026     well.
1027 */
combineTransformFromParent(QTransform * x,const QTransform * viewTransform) const1028 void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const
1029 {
1030     // COMBINE
1031     if (viewTransform && itemIsUntransformable()) {
1032         *x = q_ptr->deviceTransform(*viewTransform);
1033     } else {
1034         x->translate(pos.x(), pos.y());
1035         if (transformData)
1036             *x = transformData->computedFullTransform(x);
1037     }
1038 }
1039 
updateSceneTransformFromParent()1040 void QGraphicsItemPrivate::updateSceneTransformFromParent()
1041 {
1042     if (parent) {
1043         Q_ASSERT(!parent->d_ptr->dirtySceneTransform);
1044         if (parent->d_ptr->sceneTransformTranslateOnly) {
1045             sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(),
1046                                                        parent->d_ptr->sceneTransform.dy() + pos.y());
1047         } else {
1048             sceneTransform = parent->d_ptr->sceneTransform;
1049             sceneTransform.translate(pos.x(), pos.y());
1050         }
1051         if (transformData) {
1052             sceneTransform = transformData->computedFullTransform(&sceneTransform);
1053             sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1054         } else {
1055             sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly;
1056         }
1057     } else if (!transformData) {
1058         sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
1059         sceneTransformTranslateOnly = 1;
1060     } else if (transformData->onlyTransform) {
1061         sceneTransform = transformData->transform;
1062         if (!pos.isNull())
1063             sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y());
1064         sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1065     } else if (pos.isNull()) {
1066         sceneTransform = transformData->computedFullTransform();
1067         sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1068     } else {
1069         sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
1070         sceneTransform = transformData->computedFullTransform(&sceneTransform);
1071         sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1072     }
1073     dirtySceneTransform = 0;
1074 }
1075 
1076 /*!
1077     \internal
1078 
1079     This helper function helped us add input method query support in
1080     Qt 4.4.1 without having to reimplement the inputMethodQuery()
1081     function in QGraphicsProxyWidget. ### Qt 5: Remove. We cannot
1082     remove it in 4.5+ even if we do reimplement the function properly,
1083     because apps compiled with 4.4 will not be able to call the
1084     reimplementation.
1085 */
inputMethodQueryHelper(Qt::InputMethodQuery query) const1086 QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const
1087 {
1088     Q_UNUSED(query);
1089     return QVariant();
1090 }
1091 
1092 /*!
1093     \internal
1094 
1095     Make sure not to trigger any pure virtual function calls (e.g.,
1096     prepareGeometryChange) if the item is in its destructor, i.e.
1097     inDestructor is 1.
1098 */
setParentItemHelper(QGraphicsItem * newParent,const QVariant * newParentVariant,const QVariant * thisPointerVariant)1099 void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const QVariant *newParentVariant,
1100                                                const QVariant *thisPointerVariant)
1101 {
1102     Q_Q(QGraphicsItem);
1103     if (newParent == parent)
1104         return;
1105 
1106     if (isWidget)
1107         static_cast<QGraphicsWidgetPrivate *>(this)->fixFocusChainBeforeReparenting((newParent &&
1108                                                         newParent->isWidget()) ? static_cast<QGraphicsWidget *>(newParent) : 0,
1109                                                         scene);
1110     if (scene) {
1111         // Deliver the change to the index
1112         if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
1113             scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParent);
1114 
1115         // Disable scene pos notifications for old ancestors
1116         if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
1117             scene->d_func()->setScenePosItemEnabled(q, false);
1118     }
1119 
1120     if (subFocusItem && parent) {
1121         // Make sure none of the old parents point to this guy.
1122         subFocusItem->d_ptr->clearSubFocus(parent);
1123     }
1124 
1125     // We anticipate geometry changes. If the item is deleted, it will be
1126     // removed from the index at a later stage, and the whole scene will be
1127     // updated.
1128     if (!inDestructor)
1129         q_ptr->prepareGeometryChange();
1130 
1131     if (parent) {
1132         // Remove from current parent
1133         parent->d_ptr->removeChild(q);
1134         if (thisPointerVariant)
1135             parent->itemChange(QGraphicsItem::ItemChildRemovedChange, *thisPointerVariant);
1136     }
1137 
1138     // Update toplevelitem list. If this item is being deleted, its parent
1139     // will be 0 but we don't want to register/unregister it in the TLI list.
1140     if (scene && !inDestructor) {
1141         if (parent && !newParent) {
1142             scene->d_func()->registerTopLevelItem(q);
1143         } else if (!parent && newParent) {
1144             scene->d_func()->unregisterTopLevelItem(q);
1145         }
1146     }
1147 
1148     // Ensure any last parent focus scope does not point to this item or any of
1149     // its descendents.
1150     QGraphicsItem *p = parent;
1151     QGraphicsItem *parentFocusScopeItem = 0;
1152     while (p) {
1153         if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
1154             // If this item's focus scope's focus scope item points
1155             // to this item or a descendent, then clear it.
1156             QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
1157             if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
1158                 parentFocusScopeItem = fsi;
1159                 p->d_ptr->focusScopeItem = 0;
1160             }
1161             break;
1162         }
1163         p = p->d_ptr->parent;
1164     }
1165 
1166     // Update graphics effect optimization flag
1167     if (newParent && (graphicsEffect || mayHaveChildWithGraphicsEffect))
1168         newParent->d_ptr->updateChildWithGraphicsEffectFlagRecursively();
1169 
1170     // Update focus scope item ptr in new scope.
1171     QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
1172     if (newFocusScopeItem && newParent) {
1173         QGraphicsItem *p = newParent;
1174         while (p) {
1175             if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
1176                 if (subFocusItem && subFocusItem != q_ptr) {
1177                     // Find the subFocusItem's topmost focus scope within the new parent's focusscope
1178                     QGraphicsItem *ancestorScope = 0;
1179                     QGraphicsItem *p2 = subFocusItem->d_ptr->parent;
1180                     while (p2 && p2 != p) {
1181                         if (p2->d_ptr->flags & QGraphicsItem::ItemIsFocusScope)
1182                             ancestorScope = p2;
1183                         if (p2->d_ptr->flags & QGraphicsItem::ItemIsPanel)
1184                             break;
1185                         if (p2 == q_ptr)
1186                             break;
1187                         p2 = p2->d_ptr->parent;
1188                     }
1189                     if (ancestorScope)
1190                         newFocusScopeItem = ancestorScope;
1191                 }
1192 
1193                 p->d_ptr->focusScopeItem = newFocusScopeItem;
1194                 newFocusScopeItem->d_ptr->focusScopeItemChange(true);
1195                 // Ensure the new item is no longer the subFocusItem. The
1196                 // only way to set focus on a child of a focus scope is
1197                 // by setting focus on the scope itself.
1198                 if (subFocusItem && !p->focusItem())
1199                     subFocusItem->d_ptr->clearSubFocus();
1200                 break;
1201             }
1202             p = p->d_ptr->parent;
1203         }
1204     }
1205 
1206     // Resolve depth.
1207     invalidateDepthRecursively();
1208 
1209     if ((parent = newParent)) {
1210         if (parent->d_func()->scene && parent->d_func()->scene != scene) {
1211             // Move this item to its new parent's scene
1212             parent->d_func()->scene->addItem(q);
1213         } else if (!parent->d_func()->scene && scene) {
1214             // Remove this item from its former scene
1215             scene->removeItem(q);
1216         }
1217 
1218         parent->d_ptr->addChild(q);
1219         if (thisPointerVariant)
1220             parent->itemChange(QGraphicsItem::ItemChildAddedChange, *thisPointerVariant);
1221         if (scene) {
1222             // Re-enable scene pos notifications for new ancestors
1223             if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
1224                 scene->d_func()->setScenePosItemEnabled(q, true);
1225         }
1226 
1227         // Propagate dirty flags to the new parent
1228         markParentDirty(/*updateBoundingRect=*/true);
1229 
1230         // Inherit ancestor flags from the new parent.
1231         updateAncestorFlags();
1232 
1233         // Update item visible / enabled.
1234         if (parent->d_ptr->visible != visible) {
1235             if (!parent->d_ptr->visible || !explicitlyHidden)
1236                 setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ false);
1237         }
1238         if (parent->isEnabled() != enabled) {
1239             if (!parent->d_ptr->enabled || !explicitlyDisabled)
1240                 setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ false);
1241         }
1242 
1243         // Auto-activate if visible and the parent is active.
1244         if (visible && parent->isActive())
1245             q->setActive(true);
1246     } else {
1247         // Inherit ancestor flags from the new parent.
1248         updateAncestorFlags();
1249 
1250         if (!inDestructor) {
1251             // Update item visible / enabled.
1252             if (!visible && !explicitlyHidden)
1253                 setVisibleHelper(true, /* explicit = */ false);
1254             if (!enabled && !explicitlyDisabled)
1255                 setEnabledHelper(true, /* explicit = */ false);
1256         }
1257     }
1258 
1259     dirtySceneTransform = 1;
1260     if (!inDestructor && (transformData || (newParent && newParent->d_ptr->transformData)))
1261         transformChanged();
1262 
1263     // Reparenting is finished, now safe to notify the previous focusScopeItem about changes
1264     if (parentFocusScopeItem)
1265       parentFocusScopeItem->d_ptr->focusScopeItemChange(false);
1266 
1267     // Restore the sub focus chain.
1268     if (subFocusItem) {
1269         subFocusItem->d_ptr->setSubFocus(newParent);
1270         if (parent && parent->isActive())
1271             subFocusItem->setFocus();
1272     }
1273 
1274     // Deliver post-change notification
1275     if (newParentVariant)
1276         q->itemChange(QGraphicsItem::ItemParentHasChanged, *newParentVariant);
1277 
1278     if (isObject)
1279         emit static_cast<QGraphicsObject *>(q)->parentChanged();
1280 }
1281 
1282 /*!
1283     \internal
1284 
1285     Returns the bounding rect of this item's children (excluding itself).
1286 */
childrenBoundingRectHelper(QTransform * x,QRectF * rect,QGraphicsItem * topMostEffectItem)1287 void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem)
1288 {
1289     Q_Q(QGraphicsItem);
1290 
1291     QRectF childrenRect;
1292     QRectF *result = rect;
1293     rect = &childrenRect;
1294     const bool setTopMostEffectItem = !topMostEffectItem;
1295 
1296     for (int i = 0; i < children.size(); ++i) {
1297         QGraphicsItem *child = children.at(i);
1298         QGraphicsItemPrivate *childd = child->d_ptr.data();
1299         if (setTopMostEffectItem)
1300             topMostEffectItem = child;
1301         bool hasPos = !childd->pos.isNull();
1302         if (hasPos || childd->transformData) {
1303             // COMBINE
1304             QTransform matrix = childd->transformToParent();
1305             if (x)
1306                 matrix *= *x;
1307             *rect |= matrix.mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
1308             if (!childd->children.isEmpty())
1309                 childd->childrenBoundingRectHelper(&matrix, rect, topMostEffectItem);
1310         } else {
1311             if (x)
1312                 *rect |= x->mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
1313             else
1314                 *rect |= child->d_ptr->effectiveBoundingRect(topMostEffectItem);
1315             if (!childd->children.isEmpty())
1316                 childd->childrenBoundingRectHelper(x, rect, topMostEffectItem);
1317         }
1318     }
1319 
1320     if (flags & QGraphicsItem::ItemClipsChildrenToShape){
1321         if (x)
1322             *rect &= x->mapRect(q->boundingRect());
1323         else
1324             *rect &= q->boundingRect();
1325     }
1326 
1327     *result |= *rect;
1328 }
1329 
initStyleOption(QStyleOptionGraphicsItem * option,const QTransform & worldTransform,const QRegion & exposedRegion,bool allItems) const1330 void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
1331                                            const QRegion &exposedRegion, bool allItems) const
1332 {
1333     Q_ASSERT(option);
1334     Q_Q(const QGraphicsItem);
1335 
1336     // Initialize standard QStyleOption values.
1337     const QRectF brect = q->boundingRect();
1338     option->state = QStyle::State_None;
1339     option->rect = brect.toRect();
1340     option->levelOfDetail = 1;
1341     option->exposedRect = brect;
1342     if (selected)
1343         option->state |= QStyle::State_Selected;
1344     if (enabled)
1345         option->state |= QStyle::State_Enabled;
1346     if (q->hasFocus())
1347         option->state |= QStyle::State_HasFocus;
1348     if (scene) {
1349         if (scene->d_func()->hoverItems.contains(q_ptr))
1350             option->state |= QStyle::State_MouseOver;
1351         if (q == scene->mouseGrabberItem())
1352             option->state |= QStyle::State_Sunken;
1353     }
1354 
1355     if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption))
1356         return;
1357 
1358     // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect).
1359     option->matrix = worldTransform.toAffine(); //### discards perspective
1360 
1361     if (!allItems) {
1362         // Determine the item's exposed area
1363         option->exposedRect = QRectF();
1364         const QTransform reverseMap = worldTransform.inverted();
1365         const QVector<QRect> exposedRects(exposedRegion.rects());
1366         for (int i = 0; i < exposedRects.size(); ++i) {
1367             option->exposedRect |= reverseMap.mapRect(QRectF(exposedRects.at(i)));
1368             if (option->exposedRect.contains(brect))
1369                 break;
1370         }
1371         option->exposedRect &= brect;
1372     }
1373 }
1374 
1375 /*!
1376     \internal
1377 
1378     Empty all cached pixmaps from the pixmap cache.
1379 */
purge()1380 void QGraphicsItemCache::purge()
1381 {
1382     QPixmapCache::remove(key);
1383     key = QPixmapCache::Key();
1384     QMutableMapIterator<QPaintDevice *, DeviceData> it(deviceData);
1385     while (it.hasNext()) {
1386         DeviceData &data = it.next().value();
1387         QPixmapCache::remove(data.key);
1388         data.cacheIndent = QPoint();
1389     }
1390     deviceData.clear();
1391     allExposed = true;
1392     exposed.clear();
1393 }
1394 
1395 /*!
1396     Constructs a QGraphicsItem with the given \a parent item.
1397     It does not modify the parent object returned by QObject::parent().
1398 
1399     If \a parent is 0, you can add the item to a scene by calling
1400     QGraphicsScene::addItem(). The item will then become a top-level item.
1401 
1402     \sa QGraphicsScene::addItem(), setParentItem()
1403 */
QGraphicsItem(QGraphicsItem * parent,QGraphicsScene * scene)1404 QGraphicsItem::QGraphicsItem(QGraphicsItem *parent
1405 #ifndef Q_QDOC
1406                              // obsolete argument
1407                              , QGraphicsScene *scene
1408 #endif
1409     )
1410     : d_ptr(new QGraphicsItemPrivate)
1411 {
1412     d_ptr->q_ptr = this;
1413     setParentItem(parent);
1414 
1415     if (scene && parent && parent->scene() != scene) {
1416         qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is"
1417                  " different from parent's scene (%p)",
1418                  scene, parent->scene());
1419         return;
1420     }
1421     if (scene && !parent)
1422         scene->addItem(this);
1423 }
1424 
1425 /*!
1426     \internal
1427 */
QGraphicsItem(QGraphicsItemPrivate & dd,QGraphicsItem * parent,QGraphicsScene * scene)1428 QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent,
1429                              QGraphicsScene *scene)
1430     : d_ptr(&dd)
1431 {
1432     d_ptr->q_ptr = this;
1433     setParentItem(parent);
1434 
1435     if (scene && parent && parent->scene() != scene) {
1436         qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is"
1437                  " different from parent's scene (%p)",
1438                  scene, parent->scene());
1439         return;
1440     }
1441     if (scene && !parent)
1442         scene->addItem(this);
1443 }
1444 
1445 /*!
1446     Destroys the QGraphicsItem and all its children. If this item is currently
1447     associated with a scene, the item will be removed from the scene before it
1448     is deleted.
1449 
1450     \note It is more efficient to remove the item from the QGraphicsScene before
1451     destroying the item.
1452 */
~QGraphicsItem()1453 QGraphicsItem::~QGraphicsItem()
1454 {
1455     if (d_ptr->isObject) {
1456         QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
1457         QObjectPrivate *p = QObjectPrivate::get(o);
1458         p->wasDeleted = true;
1459         if (p->declarativeData) {
1460             QAbstractDeclarativeData::destroyed(p->declarativeData, o);
1461             p->declarativeData = 0;
1462         }
1463     }
1464 
1465     d_ptr->inDestructor = 1;
1466     d_ptr->removeExtraItemCache();
1467 
1468 #ifndef QT_NO_GESTURES
1469     if (d_ptr->isObject && !d_ptr->gestureContext.isEmpty()) {
1470         QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
1471         if (QGestureManager *manager = QGestureManager::instance()) {
1472             foreach (Qt::GestureType type, d_ptr->gestureContext.keys())
1473                 manager->cleanupCachedGestures(o, type);
1474         }
1475     }
1476 #endif
1477 
1478     clearFocus();
1479 
1480     // Update focus scope item ptr.
1481     QGraphicsItem *p = d_ptr->parent;
1482     while (p) {
1483         if (p->flags() & ItemIsFocusScope) {
1484             if (p->d_ptr->focusScopeItem == this)
1485                 p->d_ptr->focusScopeItem = 0;
1486             break;
1487         }
1488         p = p->d_ptr->parent;
1489     }
1490 
1491     if (!d_ptr->children.isEmpty()) {
1492         while (!d_ptr->children.isEmpty())
1493             delete d_ptr->children.first();
1494         Q_ASSERT(d_ptr->children.isEmpty());
1495     }
1496 
1497     if (d_ptr->scene) {
1498         d_ptr->scene->d_func()->removeItemHelper(this);
1499     } else {
1500         d_ptr->resetFocusProxy();
1501         setParentItem(0);
1502     }
1503 
1504 #ifndef QT_NO_GRAPHICSEFFECT
1505     delete d_ptr->graphicsEffect;
1506 #endif //QT_NO_GRAPHICSEFFECT
1507     if (d_ptr->transformData) {
1508         for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
1509             QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
1510             static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
1511             delete t;
1512         }
1513     }
1514     delete d_ptr->transformData;
1515 
1516     if (QGraphicsItemCustomDataStore *dataStore = qt_dataStore())
1517         dataStore->data.remove(this);
1518 }
1519 
1520 /*!
1521     Returns the current scene for the item, or 0 if the item is not stored in
1522     a scene.
1523 
1524     To add or move an item to a scene, call QGraphicsScene::addItem().
1525 */
scene() const1526 QGraphicsScene *QGraphicsItem::scene() const
1527 {
1528     return d_ptr->scene;
1529 }
1530 
1531 /*!
1532     Returns a pointer to this item's item group, or 0 if this item is not
1533     member of a group.
1534 
1535     \sa QGraphicsItemGroup, QGraphicsScene::createItemGroup()
1536 */
group() const1537 QGraphicsItemGroup *QGraphicsItem::group() const
1538 {
1539     if (!d_ptr->isMemberOfGroup)
1540         return 0;
1541     QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
1542     while ((parent = parent->d_ptr->parent)) {
1543         if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(parent))
1544             return group;
1545     }
1546     // Unreachable; if d_ptr->isMemberOfGroup is != 0, then one parent of this
1547     // item is a group item.
1548     return 0;
1549 }
1550 
1551 /*!
1552     Adds this item to the item group \a group. If \a group is 0, this item is
1553     removed from any current group and added as a child of the previous
1554     group's parent.
1555 
1556     \sa group(), QGraphicsScene::createItemGroup()
1557 */
setGroup(QGraphicsItemGroup * group)1558 void QGraphicsItem::setGroup(QGraphicsItemGroup *group)
1559 {
1560     if (!group) {
1561         if (QGraphicsItemGroup *group = this->group())
1562             group->removeFromGroup(this);
1563     } else {
1564         group->addToGroup(this);
1565     }
1566 }
1567 
1568 /*!
1569     Returns a pointer to this item's parent item. If this item does not have a
1570     parent, 0 is returned.
1571 
1572     \sa setParentItem(), childItems()
1573 */
parentItem() const1574 QGraphicsItem *QGraphicsItem::parentItem() const
1575 {
1576     return d_ptr->parent;
1577 }
1578 
1579 /*!
1580     Returns this item's top-level item. The top-level item is the item's
1581     topmost ancestor item whose parent is 0. If an item has no parent, its own
1582     pointer is returned (i.e., a top-level item is its own top-level item).
1583 
1584     \sa parentItem()
1585 */
topLevelItem() const1586 QGraphicsItem *QGraphicsItem::topLevelItem() const
1587 {
1588     QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
1589     while (QGraphicsItem *grandPa = parent->parentItem())
1590         parent = grandPa;
1591     return parent;
1592 }
1593 
1594 /*!
1595     \since 4.6
1596 
1597     Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item
1598     is not a QGraphicsObject.
1599 
1600     \sa parentItem(), childItems()
1601 */
parentObject() const1602 QGraphicsObject *QGraphicsItem::parentObject() const
1603 {
1604     QGraphicsItem *p = d_ptr->parent;
1605     return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : 0;
1606 }
1607 
1608 /*!
1609     \since 4.4
1610 
1611     Returns a pointer to the item's parent widget. The item's parent widget is
1612     the closest parent item that is a widget.
1613 
1614     \sa parentItem(), childItems()
1615 */
parentWidget() const1616 QGraphicsWidget *QGraphicsItem::parentWidget() const
1617 {
1618     QGraphicsItem *p = parentItem();
1619     while (p && !p->isWidget())
1620         p = p->parentItem();
1621     return (p && p->isWidget()) ? static_cast<QGraphicsWidget *>(p) : 0;
1622 }
1623 
1624 /*!
1625     \since 4.4
1626 
1627     Returns a pointer to the item's top level widget (i.e., the item's
1628     ancestor whose parent is 0, or whose parent is not a widget), or 0 if this
1629     item does not have a top level widget. If the item is its own top level
1630     widget, this function returns a pointer to the item itself.
1631 */
topLevelWidget() const1632 QGraphicsWidget *QGraphicsItem::topLevelWidget() const
1633 {
1634     if (const QGraphicsWidget *p = parentWidget())
1635         return p->topLevelWidget();
1636     return isWidget() ? static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)) : 0;
1637 }
1638 
1639 /*!
1640     \since 4.4
1641 
1642     Returns the item's window, or 0 if this item does not have a window. If
1643     the item is a window, it will return itself.  Otherwise it will return the
1644     closest ancestor that is a window.
1645 
1646     \sa QGraphicsWidget::isWindow()
1647 */
window() const1648 QGraphicsWidget *QGraphicsItem::window() const
1649 {
1650     QGraphicsItem *p = panel();
1651     if (p && p->isWindow())
1652         return static_cast<QGraphicsWidget *>(p);
1653     return 0;
1654 }
1655 
1656 /*!
1657     \since 4.6
1658 
1659     Returns the item's panel, or 0 if this item does not have a panel. If the
1660     item is a panel, it will return itself. Otherwise it will return the
1661     closest ancestor that is a panel.
1662 
1663     \sa isPanel(), ItemIsPanel
1664 */
panel() const1665 QGraphicsItem *QGraphicsItem::panel() const
1666 {
1667     if (d_ptr->flags & ItemIsPanel)
1668         return const_cast<QGraphicsItem *>(this);
1669     return d_ptr->parent ? d_ptr->parent->panel() : 0;
1670 }
1671 
1672 /*!
1673   \since 4.6
1674 
1675   Return the graphics item cast to a QGraphicsObject, if the class is actually a
1676   graphics object, 0 otherwise.
1677 */
toGraphicsObject()1678 QGraphicsObject *QGraphicsItem::toGraphicsObject()
1679 {
1680     return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : 0;
1681 }
1682 
1683 /*!
1684   \since 4.6
1685 
1686   Return the graphics item cast to a QGraphicsObject, if the class is actually a
1687   graphics object, 0 otherwise.
1688 */
toGraphicsObject() const1689 const QGraphicsObject *QGraphicsItem::toGraphicsObject() const
1690 {
1691     return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0;
1692 }
1693 
1694 /*!
1695   Sets this item's parent item to \a newParent. If this item already
1696   has a parent, it is first removed from the previous parent. If \a
1697   newParent is 0, this item will become a top-level item.
1698 
1699   Note that this implicitly adds this graphics item to the scene of
1700   the parent. You should not \l{QGraphicsScene::addItem()}{add} the
1701   item to the scene yourself.
1702 
1703   Calling this function on an item that is an ancestor of \a newParent
1704   have undefined behaviour.
1705 
1706   \sa parentItem(), childItems()
1707 */
setParentItem(QGraphicsItem * newParent)1708 void QGraphicsItem::setParentItem(QGraphicsItem *newParent)
1709 {
1710     if (newParent == this) {
1711         qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
1712         return;
1713     }
1714     if (newParent == d_ptr->parent)
1715         return;
1716 
1717     const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange,
1718                                                QVariant::fromValue<QGraphicsItem *>(newParent)));
1719     newParent = qvariant_cast<QGraphicsItem *>(newParentVariant);
1720     if (newParent == d_ptr->parent)
1721         return;
1722 
1723     const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this));
1724     d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant);
1725 }
1726 
1727 /*!
1728     \obsolete
1729 
1730     Use childItems() instead.
1731 
1732     \sa setParentItem()
1733 */
children() const1734 QList<QGraphicsItem *> QGraphicsItem::children() const
1735 {
1736     return childItems();
1737 }
1738 
1739 /*!
1740     \since 4.4
1741 
1742     Returns a list of this item's children.
1743 
1744     The items are sorted by stacking order. This takes into account both the
1745     items' insertion order and their Z-values.
1746 
1747     \sa setParentItem(), zValue(), {QGraphicsItem#Sorting}{Sorting}
1748 */
childItems() const1749 QList<QGraphicsItem *> QGraphicsItem::childItems() const
1750 {
1751     const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren();
1752     return d_ptr->children;
1753 }
1754 
1755 /*!
1756     \since 4.4
1757     Returns true if this item is a widget (i.e., QGraphicsWidget); otherwise,
1758     returns false.
1759 */
isWidget() const1760 bool QGraphicsItem::isWidget() const
1761 {
1762     return d_ptr->isWidget;
1763 }
1764 
1765 /*!
1766     \since 4.4
1767     Returns true if the item is a QGraphicsWidget window, otherwise returns
1768     false.
1769 
1770     \sa QGraphicsWidget::windowFlags()
1771 */
isWindow() const1772 bool QGraphicsItem::isWindow() const
1773 {
1774     return d_ptr->isWidget && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
1775 }
1776 
1777 /*!
1778     \since 4.6
1779     Returns true if the item is a panel; otherwise returns false.
1780 
1781     \sa QGraphicsItem::panel(), ItemIsPanel
1782 */
isPanel() const1783 bool QGraphicsItem::isPanel() const
1784 {
1785     return d_ptr->flags & ItemIsPanel;
1786 }
1787 
1788 /*!
1789     Returns this item's flags. The flags describe what configurable features
1790     of the item are enabled and not. For example, if the flags include
1791     ItemIsFocusable, the item can accept input focus.
1792 
1793     By default, no flags are enabled.
1794 
1795     \sa setFlags(), setFlag()
1796 */
flags() const1797 QGraphicsItem::GraphicsItemFlags QGraphicsItem::flags() const
1798 {
1799     return GraphicsItemFlags(d_ptr->flags);
1800 }
1801 
1802 /*!
1803     If \a enabled is true, the item flag \a flag is enabled; otherwise, it is
1804     disabled.
1805 
1806     \sa flags(), setFlags()
1807 */
setFlag(GraphicsItemFlag flag,bool enabled)1808 void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled)
1809 {
1810     if (enabled)
1811         setFlags(GraphicsItemFlags(d_ptr->flags) | flag);
1812     else
1813         setFlags(GraphicsItemFlags(d_ptr->flags) & ~flag);
1814 }
1815 
1816 /*!
1817     \internal
1818 
1819     Sets the flag \a flag on \a item and all its children, to \a enabled.
1820 */
_q_qgraphicsItemSetFlag(QGraphicsItem * item,QGraphicsItem::GraphicsItemFlag flag,bool enabled)1821 static void _q_qgraphicsItemSetFlag(QGraphicsItem *item, QGraphicsItem::GraphicsItemFlag flag,
1822                                     bool enabled)
1823 {
1824     if (item->flags() & flag) {
1825         // If this item already has the correct flag set, we don't have to
1826         // propagate it.
1827         return;
1828     }
1829     item->setFlag(flag, enabled);
1830     foreach (QGraphicsItem *child, item->children())
1831         _q_qgraphicsItemSetFlag(child, flag, enabled);
1832 }
1833 
1834 /*!
1835     Sets the item flags to \a flags. All flags in \a flags are enabled; all
1836     flags not in \a flags are disabled.
1837 
1838     If the item had focus and \a flags does not enable ItemIsFocusable, the
1839     item loses focus as a result of calling this function. Similarly, if the
1840     item was selected, and \a flags does not enabled ItemIsSelectable, the
1841     item is automatically unselected.
1842 
1843     By default, no flags are enabled. (QGraphicsWidget enables the
1844     ItemSendsGeometryChanges flag by default in order to track position
1845     changes.)
1846 
1847     \sa flags(), setFlag()
1848 */
setFlags(GraphicsItemFlags flags)1849 void QGraphicsItem::setFlags(GraphicsItemFlags flags)
1850 {
1851     // Notify change and check for adjustment.
1852     if (quint32(d_ptr->flags) == quint32(flags))
1853         return;
1854     flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt());
1855     if (quint32(d_ptr->flags) == quint32(flags))
1856         return;
1857     if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
1858         d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, &flags);
1859 
1860     // Flags that alter the geometry of the item (or its children).
1861     const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable);
1862     bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
1863     if (fullUpdate)
1864         d_ptr->updatePaintedViewBoundingRects(/*children=*/true);
1865 
1866     // Keep the old flags to compare the diff.
1867     GraphicsItemFlags oldFlags = GraphicsItemFlags(d_ptr->flags);
1868 
1869     // Update flags.
1870     d_ptr->flags = flags;
1871 
1872     if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
1873         // Clear focus on the item if it has focus when the focusable flag
1874         // is unset.
1875         clearFocus();
1876     }
1877 
1878     if (!(d_ptr->flags & ItemIsSelectable) && isSelected()) {
1879         // Unselect the item if it is selected when the selectable flag is
1880         // unset.
1881         setSelected(false);
1882     }
1883 
1884     if ((flags & ItemClipsChildrenToShape) != (oldFlags & ItemClipsChildrenToShape)) {
1885         // Item children clipping changes. Propagate the ancestor flag to
1886         // all children.
1887         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
1888         // The childrenBoundingRect is clipped to the boundingRect in case of ItemClipsChildrenToShape,
1889         // which means we have to invalidate the cached childrenBoundingRect whenever this flag changes.
1890         d_ptr->dirtyChildrenBoundingRect = 1;
1891         d_ptr->markParentDirty(true);
1892     }
1893 
1894     if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
1895         // Item children clipping changes. Propagate the ancestor flag to
1896         // all children.
1897         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
1898     }
1899 
1900     if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) {
1901         // NB! We change the flags directly here, so we must also update d_ptr->flags.
1902         // Note that this has do be done before the ItemStacksBehindParent check
1903         // below; otherwise we will loose the change.
1904 
1905         // Update stack-behind.
1906         if (d_ptr->z < qreal(0.0))
1907             flags |= ItemStacksBehindParent;
1908         else
1909             flags &= ~ItemStacksBehindParent;
1910         d_ptr->flags = flags;
1911     }
1912 
1913     if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
1914         // NB! This check has to come after the ItemNegativeZStacksBehindParent
1915         // check above. Be careful.
1916 
1917         // Ensure child item sorting is up to date when toggling this flag.
1918         if (d_ptr->parent)
1919             d_ptr->parent->d_ptr->needSortChildren = 1;
1920         else if (d_ptr->scene)
1921             d_ptr->scene->d_func()->needSortTopLevelItems = 1;
1922     }
1923 
1924     if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) {
1925         // Update input method sensitivity in any views.
1926         if (d_ptr->scene)
1927             d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
1928     }
1929 
1930 
1931     if ((d_ptr->panelModality != NonModal)
1932         && d_ptr->scene
1933         && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
1934         // update the panel's modal state
1935         if (flags & ItemIsPanel)
1936             d_ptr->scene->d_func()->enterModal(this);
1937         else
1938             d_ptr->scene->d_func()->leaveModal(this);
1939     }
1940 
1941     if (d_ptr->scene) {
1942         if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) {
1943             if (flags & ItemSendsScenePositionChanges)
1944                 d_ptr->scene->d_func()->registerScenePosItem(this);
1945             else
1946                 d_ptr->scene->d_func()->unregisterScenePosItem(this);
1947         }
1948         d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
1949     }
1950 
1951     // Notify change.
1952     itemChange(ItemFlagsHaveChanged, quint32(flags));
1953 }
1954 
1955 /*!
1956     \since 4.4
1957     Returns the cache mode for this item. The default mode is NoCache (i.e.,
1958     cache is disabled and all painting is immediate).
1959 
1960     \sa setCacheMode()
1961 */
cacheMode() const1962 QGraphicsItem::CacheMode QGraphicsItem::cacheMode() const
1963 {
1964     return QGraphicsItem::CacheMode(d_ptr->cacheMode);
1965 }
1966 
1967 /*!
1968     \since 4.4
1969     Sets the item's cache mode to \a mode.
1970 
1971     The optional \a logicalCacheSize argument is used only by
1972     ItemCoordinateCache mode, and describes the resolution of the cache
1973     buffer; if \a logicalCacheSize is (100, 100), QGraphicsItem will fit the
1974     item into 100x100 pixels in graphics memory, regardless of the logical
1975     size of the item itself. By default QGraphicsItem uses the size of
1976     boundingRect(). For all other cache modes than ItemCoordinateCache, \a
1977     logicalCacheSize is ignored.
1978 
1979     Caching can speed up rendering if your item spends a significant time
1980     redrawing itself. In some cases the cache can also slow down rendering, in
1981     particular when the item spends less time redrawing than QGraphicsItem
1982     spends redrawing from the cache. When enabled, the item's paint() function
1983     will be called only once for each call to update(); for any subsequent
1984     repaint requests, the Graphics View framework will redraw from the
1985     cache. This approach works particularly well with QGLWidget, which stores
1986     all the cache as OpenGL textures.
1987 
1988     Be aware that QPixmapCache's cache limit may need to be changed to obtain
1989     optimal performance.
1990 
1991     You can read more about the different cache modes in the CacheMode
1992     documentation.
1993 
1994     \sa CacheMode, QPixmapCache::setCacheLimit()
1995 */
setCacheMode(CacheMode mode,const QSize & logicalCacheSize)1996 void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
1997 {
1998     CacheMode lastMode = CacheMode(d_ptr->cacheMode);
1999     d_ptr->cacheMode = mode;
2000     bool noVisualChange = (mode == NoCache && lastMode == NoCache)
2001                           || (mode == NoCache && lastMode == DeviceCoordinateCache)
2002                           || (mode == DeviceCoordinateCache && lastMode == NoCache)
2003                           || (mode == DeviceCoordinateCache && lastMode == DeviceCoordinateCache);
2004     if (mode == NoCache) {
2005         d_ptr->removeExtraItemCache();
2006     } else {
2007         QGraphicsItemCache *cache = d_ptr->extraItemCache();
2008 
2009         // Reset old cache
2010         cache->purge();
2011 
2012         if (mode == ItemCoordinateCache) {
2013             if (lastMode == mode && cache->fixedSize == logicalCacheSize)
2014                 noVisualChange = true;
2015             cache->fixedSize = logicalCacheSize;
2016         }
2017     }
2018     if (!noVisualChange)
2019         update();
2020 }
2021 
2022 /*!
2023     \since 4.6
2024 
2025     Returns the modality for this item.
2026 */
panelModality() const2027 QGraphicsItem::PanelModality QGraphicsItem::panelModality() const
2028 {
2029     return d_ptr->panelModality;
2030 }
2031 
2032 /*!
2033     \since 4.6
2034 
2035     Sets the modality for this item to \a panelModality.
2036 
2037     Changing the modality of a visible item takes effect immediately.
2038 */
setPanelModality(PanelModality panelModality)2039 void QGraphicsItem::setPanelModality(PanelModality panelModality)
2040 {
2041     if (d_ptr->panelModality == panelModality)
2042         return;
2043 
2044     PanelModality previousModality = d_ptr->panelModality;
2045     bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible());
2046     if (enterLeaveModal && panelModality == NonModal)
2047         d_ptr->scene->d_func()->leaveModal(this);
2048     d_ptr->panelModality = panelModality;
2049     if (enterLeaveModal && d_ptr->panelModality != NonModal)
2050         d_ptr->scene->d_func()->enterModal(this, previousModality);
2051 }
2052 
2053 /*!
2054     \since 4.6
2055 
2056     Returns true if this item is blocked by a modal panel, false otherwise. If \a blockingPanel is
2057     non-zero, \a blockingPanel will be set to the modal panel that is blocking this item. If this
2058     item is not blocked, \a blockingPanel will not be set by this function.
2059 
2060     This function always returns false for items not in a scene.
2061 
2062     \sa panelModality() setPanelModality() PanelModality
2063 */
isBlockedByModalPanel(QGraphicsItem ** blockingPanel) const2064 bool QGraphicsItem::isBlockedByModalPanel(QGraphicsItem **blockingPanel) const
2065 {
2066     if (!d_ptr->scene)
2067         return false;
2068 
2069 
2070     QGraphicsItem *dummy = 0;
2071     if (!blockingPanel)
2072         blockingPanel = &dummy;
2073 
2074     QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func();
2075     if (scene_d->modalPanels.isEmpty())
2076         return false;
2077 
2078     // ###
2079     if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this)
2080         return false;
2081 
2082     for (int i = 0; i < scene_d->modalPanels.count(); ++i) {
2083         QGraphicsItem *modalPanel = scene_d->modalPanels.at(i);
2084         if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
2085             // Scene modal panels block all non-descendents.
2086             if (modalPanel != this && !modalPanel->isAncestorOf(this)) {
2087                 *blockingPanel = modalPanel;
2088                 return true;
2089             }
2090         } else {
2091             // Window modal panels block ancestors and siblings/cousins.
2092             if (modalPanel != this
2093                 && !modalPanel->isAncestorOf(this)
2094                 && commonAncestorItem(modalPanel)) {
2095                 *blockingPanel = modalPanel;
2096                 return true;
2097             }
2098         }
2099     }
2100     return false;
2101 }
2102 
2103 #ifndef QT_NO_TOOLTIP
2104 /*!
2105     Returns the item's tool tip, or an empty QString if no tool tip has been
2106     set.
2107 
2108     \sa setToolTip(), QToolTip
2109 */
toolTip() const2110 QString QGraphicsItem::toolTip() const
2111 {
2112     return d_ptr->extra(QGraphicsItemPrivate::ExtraToolTip).toString();
2113 }
2114 
2115 /*!
2116     Sets the item's tool tip to \a toolTip. If \a toolTip is empty, the item's
2117     tool tip is cleared.
2118 
2119     \sa toolTip(), QToolTip
2120 */
setToolTip(const QString & toolTip)2121 void QGraphicsItem::setToolTip(const QString &toolTip)
2122 {
2123     const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip));
2124     d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString());
2125     itemChange(ItemToolTipHasChanged, toolTipVariant);
2126 }
2127 #endif // QT_NO_TOOLTIP
2128 
2129 #ifndef QT_NO_CURSOR
2130 /*!
2131     Returns the current cursor shape for the item. The mouse cursor
2132     will assume this shape when it's over this item. See the \link
2133     Qt::CursorShape list of predefined cursor objects\endlink for a
2134     range of useful shapes.
2135 
2136     An editor item might want to use an I-beam cursor:
2137 
2138     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 2
2139 
2140     If no cursor has been set, the cursor of the item beneath is used.
2141 
2142     \sa setCursor(), hasCursor(), unsetCursor(), QWidget::cursor,
2143     QApplication::overrideCursor()
2144 */
cursor() const2145 QCursor QGraphicsItem::cursor() const
2146 {
2147     return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor));
2148 }
2149 
2150 /*!
2151     Sets the current cursor shape for the item to \a cursor. The mouse cursor
2152     will assume this shape when it's over this item. See the \link
2153     Qt::CursorShape list of predefined cursor objects\endlink for a range of
2154     useful shapes.
2155 
2156     An editor item might want to use an I-beam cursor:
2157 
2158     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 3
2159 
2160     If no cursor has been set, the cursor of the item beneath is used.
2161 
2162     \sa cursor(), hasCursor(), unsetCursor(), QWidget::cursor,
2163     QApplication::overrideCursor()
2164 */
setCursor(const QCursor & cursor)2165 void QGraphicsItem::setCursor(const QCursor &cursor)
2166 {
2167     const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor)));
2168     d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant));
2169     d_ptr->hasCursor = 1;
2170     if (d_ptr->scene) {
2171         d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
2172         foreach (QGraphicsView *view, d_ptr->scene->views()) {
2173             view->viewport()->setMouseTracking(true);
2174             // Note: Some of this logic is duplicated in QGraphicsView's mouse events.
2175             if (view->underMouse()) {
2176                 foreach (QGraphicsItem *itemUnderCursor, view->items(view->mapFromGlobal(QCursor::pos()))) {
2177                     if (itemUnderCursor->hasCursor()) {
2178                         QMetaObject::invokeMethod(view, "_q_setViewportCursor",
2179                                                   Q_ARG(QCursor, itemUnderCursor->cursor()));
2180                         break;
2181                     }
2182                 }
2183                 break;
2184             }
2185         }
2186     }
2187     itemChange(ItemCursorHasChanged, cursorVariant);
2188 }
2189 
2190 /*!
2191     Returns true if this item has a cursor set; otherwise, false is returned.
2192 
2193     By default, items don't have any cursor set. cursor() will return a
2194     standard pointing arrow cursor.
2195 
2196     \sa unsetCursor()
2197 */
hasCursor() const2198 bool QGraphicsItem::hasCursor() const
2199 {
2200     return d_ptr->hasCursor;
2201 }
2202 
2203 /*!
2204     Clears the cursor from this item.
2205 
2206     \sa hasCursor(), setCursor()
2207 */
unsetCursor()2208 void QGraphicsItem::unsetCursor()
2209 {
2210     d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraCursor);
2211     d_ptr->hasCursor = 0;
2212     if (d_ptr->scene) {
2213         foreach (QGraphicsView *view, d_ptr->scene->views()) {
2214             if (view->underMouse() && view->itemAt(view->mapFromGlobal(QCursor::pos())) == this) {
2215                 QMetaObject::invokeMethod(view, "_q_unsetViewportCursor");
2216                 break;
2217             }
2218         }
2219     }
2220 }
2221 
2222 #endif // QT_NO_CURSOR
2223 
2224 /*!
2225    Returns true if the item is visible; otherwise, false is returned.
2226 
2227    Note that the item's general visibility is unrelated to whether or not it
2228    is actually being visualized by a QGraphicsView.
2229 
2230    \sa setVisible()
2231 */
isVisible() const2232 bool QGraphicsItem::isVisible() const
2233 {
2234     return d_ptr->visible;
2235 }
2236 
2237 /*!
2238     \since 4.4
2239     Returns true if the item is visible to \a parent; otherwise, false is
2240     returned. \a parent can be 0, in which case this function will return
2241     whether the item is visible to the scene or not.
2242 
2243     An item may not be visible to its ancestors even if isVisible() is true. It
2244     may also be visible to its ancestors even if isVisible() is false. If
2245     any ancestor is hidden, the item itself will be implicitly hidden, in which
2246     case this function will return false.
2247 
2248     \sa isVisible(), setVisible()
2249 */
isVisibleTo(const QGraphicsItem * parent) const2250 bool QGraphicsItem::isVisibleTo(const QGraphicsItem *parent) const
2251 {
2252     const QGraphicsItem *p = this;
2253     if (d_ptr->explicitlyHidden)
2254         return false;
2255     do {
2256         if (p == parent)
2257             return true;
2258         if (p->d_ptr->explicitlyHidden)
2259             return false;
2260     } while ((p = p->d_ptr->parent));
2261     return parent == 0;
2262 }
2263 
2264 /*!
2265     \internal
2266 
2267     Sets this item's visibility to \a newVisible. If \a explicitly is true,
2268     this item will be "explicitly" \a newVisible; otherwise, it.. will not be.
2269 */
setVisibleHelper(bool newVisible,bool explicitly,bool update)2270 void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bool update)
2271 {
2272     Q_Q(QGraphicsItem);
2273 
2274     // Update explicit bit.
2275     if (explicitly)
2276         explicitlyHidden = newVisible ? 0 : 1;
2277 
2278     // Check if there's nothing to do.
2279     if (visible == quint32(newVisible))
2280         return;
2281 
2282     // Don't show child if parent is not visible
2283     if (parent && newVisible && !parent->d_ptr->visible)
2284         return;
2285 
2286     // Modify the property.
2287     const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange,
2288                                                        quint32(newVisible)));
2289     newVisible = newVisibleVariant.toBool();
2290     if (visible == quint32(newVisible))
2291         return;
2292     visible = newVisible;
2293 
2294     // Schedule redrawing
2295     if (update) {
2296         QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
2297         if (c)
2298             c->purge();
2299         if (scene) {
2300 #ifndef QT_NO_GRAPHICSEFFECT
2301             invalidateParentGraphicsEffectsRecursively();
2302 #endif //QT_NO_GRAPHICSEFFECT
2303             scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
2304         }
2305     }
2306 
2307     // Certain properties are dropped as an item becomes invisible.
2308     bool hasFocus = q_ptr->hasFocus();
2309     if (!newVisible) {
2310         if (scene) {
2311             if (scene->d_func()->mouseGrabberItems.contains(q))
2312                 q->ungrabMouse();
2313             if (scene->d_func()->keyboardGrabberItems.contains(q))
2314                 q->ungrabKeyboard();
2315             if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
2316                 scene->d_func()->leaveModal(q_ptr);
2317         }
2318         if (hasFocus && scene) {
2319             // Hiding the closest non-panel ancestor of the focus item
2320             QGraphicsItem *focusItem = scene->focusItem();
2321             if (isWidget && !focusItem->isPanel()) {
2322                 do {
2323                     if (focusItem == q_ptr) {
2324                         static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
2325                         break;
2326                     }
2327                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
2328             }
2329             // Clear focus if previous steps didn't move it to another widget
2330             if (q_ptr->hasFocus())
2331                 clearFocusHelper(/* giveFocusToParent = */ false);
2332         }
2333         if (q_ptr->isSelected())
2334             q_ptr->setSelected(false);
2335     } else {
2336         geometryChanged = 1;
2337         paintedViewBoundingRectsNeedRepaint = 1;
2338         if (scene) {
2339             if (isWidget) {
2340                 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
2341                 if (widget->windowType() == Qt::Popup)
2342                     scene->d_func()->addPopup(widget);
2343             }
2344             if (q->isPanel() && panelModality != QGraphicsItem::NonModal) {
2345                 scene->d_func()->enterModal(q_ptr);
2346             }
2347         }
2348     }
2349 
2350     // Update children with explicitly = false.
2351     const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape)
2352                                             && !(flags & QGraphicsItem::ItemHasNoContents));
2353     foreach (QGraphicsItem *child, children) {
2354         if (!newVisible || !child->d_ptr->explicitlyHidden)
2355             child->d_ptr->setVisibleHelper(newVisible, false, updateChildren);
2356     }
2357 
2358     // Update activation
2359     if (scene && q->isPanel()) {
2360         if (newVisible) {
2361             if (parent && parent->isActive())
2362                 q->setActive(true);
2363         } else {
2364             if (q->isActive())
2365                 scene->setActivePanel(parent);
2366         }
2367     }
2368 
2369     // Enable subfocus
2370     if (scene) {
2371         if (newVisible) {
2372             // Item is shown
2373             QGraphicsItem *p = parent;
2374             bool done = false;
2375             while (p) {
2376                 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
2377                     QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
2378                     if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
2379                         done = true;
2380                         while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
2381                             fsi = fsi->d_ptr->focusScopeItem;
2382                         fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
2383                                                    /* focusFromHide = */ false);
2384                     }
2385                     break;
2386                 }
2387                 p = p->d_ptr->parent;
2388             }
2389             if (!done) {
2390                 QGraphicsItem *fi = subFocusItem;
2391                 if (fi && fi != scene->focusItem()) {
2392                     scene->setFocusItem(fi);
2393                 } else if (flags & QGraphicsItem::ItemIsFocusScope &&
2394                            !scene->focusItem() &&
2395                            q->isAncestorOf(scene->d_func()->lastFocusItem)) {
2396                     q_ptr->setFocus();
2397                 }
2398             }
2399         } else {
2400             // Item is hidden
2401             if (hasFocus) {
2402                 QGraphicsItem *p = parent;
2403                 while (p) {
2404                     if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
2405                         if (p->d_ptr->visible) {
2406                             p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
2407                                                      /* focusFromHide = */ true);
2408                         }
2409                         break;
2410                     }
2411                     p = p->d_ptr->parent;
2412                 }
2413             }
2414         }
2415     }
2416 
2417     // Deliver post-change notification.
2418     q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant);
2419 
2420     if (isObject)
2421         emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged();
2422 }
2423 
2424 /*!
2425     If \a visible is true, the item is made visible. Otherwise, the item is
2426     made invisible. Invisible items are not painted, nor do they receive any
2427     events. In particular, mouse events pass right through invisible items,
2428     and are delivered to any item that may be behind. Invisible items are also
2429     unselectable, they cannot take input focus, and are not detected by
2430     QGraphicsScene's item location functions.
2431 
2432     If an item becomes invisible while grabbing the mouse, (i.e., while it is
2433     receiving mouse events,) it will automatically lose the mouse grab, and
2434     the grab is not regained by making the item visible again; it must receive
2435     a new mouse press to regain the mouse grab.
2436 
2437     Similarly, an invisible item cannot have focus, so if the item has focus
2438     when it becomes invisible, it will lose focus, and the focus is not
2439     regained by simply making the item visible again.
2440 
2441     If you hide a parent item, all its children will also be hidden. If you
2442     show a parent item, all children will be shown, unless they have been
2443     explicitly hidden (i.e., if you call setVisible(false) on a child, it will
2444     not be reshown even if its parent is hidden, and then shown again).
2445 
2446     Items are visible by default; it is unnecessary to call
2447     setVisible() on a new item.
2448 
2449     \sa isVisible(), show(), hide()
2450 */
setVisible(bool visible)2451 void QGraphicsItem::setVisible(bool visible)
2452 {
2453     d_ptr->setVisibleHelper(visible, /* explicit = */ true);
2454 }
2455 
2456 /*!
2457     \fn void QGraphicsItem::hide()
2458 
2459     Hides the item. (Items are visible by default.)
2460 
2461     This convenience function is equivalent to calling \c setVisible(false).
2462 
2463     \sa show(), setVisible()
2464 */
2465 
2466 /*!
2467     \fn void QGraphicsItem::show()
2468 
2469     Shows the item. (Items are visible by default.)
2470 
2471     This convenience function is equivalent to calling \c setVisible(true).
2472 
2473     \sa hide(), setVisible()
2474 */
2475 
2476 /*!
2477     Returns true if the item is enabled; otherwise, false is returned.
2478 
2479     \sa setEnabled()
2480 */
isEnabled() const2481 bool QGraphicsItem::isEnabled() const
2482 {
2483     return d_ptr->enabled;
2484 }
2485 
2486 /*!
2487     \internal
2488 
2489     Sets this item's visibility to \a newEnabled. If \a explicitly is true,
2490     this item will be "explicitly" \a newEnabled; otherwise, it.. will not be.
2491 */
setEnabledHelper(bool newEnabled,bool explicitly,bool update)2492 void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bool update)
2493 {
2494     // Update explicit bit.
2495     if (explicitly)
2496         explicitlyDisabled = newEnabled ? 0 : 1;
2497 
2498     // Check if there's nothing to do.
2499     if (enabled == quint32(newEnabled))
2500         return;
2501 
2502     // Certain properties are dropped when an item is disabled.
2503     if (!newEnabled) {
2504         if (scene && scene->mouseGrabberItem() == q_ptr)
2505             q_ptr->ungrabMouse();
2506         if (q_ptr->hasFocus()) {
2507             // Disabling the closest non-panel ancestor of the focus item
2508             // causes focus to pop to the next item, otherwise it's cleared.
2509             QGraphicsItem *focusItem = scene->focusItem();
2510             if (isWidget && !focusItem->isPanel() && q_ptr->isAncestorOf(focusItem)) {
2511                 do {
2512                     if (focusItem == q_ptr) {
2513                         static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
2514                         break;
2515                     }
2516                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
2517             }
2518             // Clear focus if previous steps didn't move it to another widget
2519             if (q_ptr->hasFocus())
2520                 q_ptr->clearFocus();
2521         }
2522         if (q_ptr->isSelected())
2523             q_ptr->setSelected(false);
2524     }
2525 
2526     // Modify the property.
2527     const QVariant newEnabledVariant(q_ptr->itemChange(QGraphicsItem::ItemEnabledChange,
2528                                                        quint32(newEnabled)));
2529     enabled = newEnabledVariant.toBool();
2530 
2531     // Schedule redraw.
2532     if (update)
2533         q_ptr->update();
2534 
2535     foreach (QGraphicsItem *child, children) {
2536         if (!newEnabled || !child->d_ptr->explicitlyDisabled)
2537             child->d_ptr->setEnabledHelper(newEnabled, /* explicitly = */ false);
2538     }
2539 
2540     // Deliver post-change notification.
2541     q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant);
2542 
2543     if (isObject)
2544         emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged();
2545 }
2546 
2547 /*!
2548     If \a enabled is true, the item is enabled; otherwise, it is disabled.
2549 
2550     Disabled items are visible, but they do not receive any events, and cannot
2551     take focus nor be selected. Mouse events are discarded; they are not
2552     propagated unless the item is also invisible, or if it does not accept
2553     mouse events (see acceptedMouseButtons()). A disabled item cannot become the
2554     mouse grabber, and as a result of this, an item loses the grab if it
2555     becomes disabled when grabbing the mouse, just like it loses focus if it
2556     had focus when it was disabled.
2557 
2558     Disabled items are traditionally drawn using grayed-out colors (see \l
2559     QPalette::Disabled).
2560 
2561     If you disable a parent item, all its children will also be disabled. If
2562     you enable a parent item, all children will be enabled, unless they have
2563     been explicitly disabled (i.e., if you call setEnabled(false) on a child,
2564     it will not be reenabled if its parent is disabled, and then enabled
2565     again).
2566 
2567     Items are enabled by default.
2568 
2569     \note If you install an event filter, you can still intercept events
2570     before they are delivered to items; this mechanism disregards the item's
2571     enabled state.
2572 
2573     \sa isEnabled()
2574 */
setEnabled(bool enabled)2575 void QGraphicsItem::setEnabled(bool enabled)
2576 {
2577     d_ptr->setEnabledHelper(enabled, /* explicitly = */ true);
2578 }
2579 
2580 /*!
2581     Returns true if this item is selected; otherwise, false is returned.
2582 
2583     Items that are in a group inherit the group's selected state.
2584 
2585     Items are not selected by default.
2586 
2587     \sa setSelected(), QGraphicsScene::setSelectionArea()
2588 */
isSelected() const2589 bool QGraphicsItem::isSelected() const
2590 {
2591     if (QGraphicsItemGroup *group = this->group())
2592         return group->isSelected();
2593     return d_ptr->selected;
2594 }
2595 
2596 /*!
2597     If \a selected is true and this item is selectable, this item is selected;
2598     otherwise, it is unselected.
2599 
2600     If the item is in a group, the whole group's selected state is toggled by
2601     this function. If the group is selected, all items in the group are also
2602     selected, and if the group is not selected, no item in the group is
2603     selected.
2604 
2605     Only visible, enabled, selectable items can be selected.  If \a selected
2606     is true and this item is either invisible or disabled or unselectable,
2607     this function does nothing.
2608 
2609     By default, items cannot be selected. To enable selection, set the
2610     ItemIsSelectable flag.
2611 
2612     This function is provided for convenience, allowing individual toggling of
2613     the selected state of an item. However, a more common way of selecting
2614     items is to call QGraphicsScene::setSelectionArea(), which will call this
2615     function for all visible, enabled, and selectable items within a specified
2616     area on the scene.
2617 
2618     \sa isSelected(), QGraphicsScene::selectedItems()
2619 */
setSelected(bool selected)2620 void QGraphicsItem::setSelected(bool selected)
2621 {
2622     if (QGraphicsItemGroup *group = this->group()) {
2623         group->setSelected(selected);
2624         return;
2625     }
2626 
2627     if (!(d_ptr->flags & ItemIsSelectable) || !d_ptr->enabled || !d_ptr->visible)
2628         selected = false;
2629     if (d_ptr->selected == selected)
2630         return;
2631     const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected)));
2632     bool newSelected = newSelectedVariant.toBool();
2633     if (d_ptr->selected == newSelected)
2634         return;
2635     d_ptr->selected = newSelected;
2636 
2637     update();
2638     if (d_ptr->scene) {
2639         QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
2640         if (selected) {
2641             sceneD->selectedItems << this;
2642         } else {
2643             // QGraphicsScene::selectedItems() lazily pulls out all items that are
2644             // no longer selected.
2645         }
2646         if (!sceneD->selectionChanging)
2647             emit d_ptr->scene->selectionChanged();
2648     }
2649 
2650     // Deliver post-change notification.
2651     itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant);
2652 }
2653 
2654 /*!
2655     \since 4.5
2656 
2657     Returns this item's local opacity, which is between 0.0 (transparent) and
2658     1.0 (opaque). This value is combined with parent and ancestor values into
2659     the effectiveOpacity(). The effective opacity decides how the item is
2660     rendered.
2661 
2662     The opacity property decides the state of the painter passed to the
2663     paint() function. If the item is cached, i.e., ItemCoordinateCache or
2664     DeviceCoordinateCache, the effective property will be applied to the item's
2665     cache as it is rendered.
2666 
2667     The default opacity is 1.0; fully opaque.
2668 
2669     \sa setOpacity(), paint(), ItemIgnoresParentOpacity,
2670     ItemDoesntPropagateOpacityToChildren
2671 */
opacity() const2672 qreal QGraphicsItem::opacity() const
2673 {
2674     return d_ptr->opacity;
2675 }
2676 
2677 /*!
2678     \since 4.5
2679 
2680     Returns this item's \e effective opacity, which is between 0.0
2681     (transparent) and 1.0 (opaque). This value is a combination of this item's
2682     local opacity, and its parent and ancestors' opacities. The effective
2683     opacity decides how the item is rendered.
2684 
2685     \sa opacity(), setOpacity(), paint(), ItemIgnoresParentOpacity,
2686     ItemDoesntPropagateOpacityToChildren
2687 */
effectiveOpacity() const2688 qreal QGraphicsItem::effectiveOpacity() const
2689 {
2690     return d_ptr->effectiveOpacity();
2691 }
2692 
2693 /*!
2694     \since 4.5
2695 
2696     Sets this item's local \a opacity, between 0.0 (transparent) and 1.0
2697     (opaque). The item's local opacity is combined with parent and ancestor
2698     opacities into the effectiveOpacity().
2699 
2700     By default, opacity propagates from parent to child, so if a parent's
2701     opacity is 0.5 and the child is also 0.5, the child's effective opacity
2702     will be 0.25.
2703 
2704     The opacity property decides the state of the painter passed to the
2705     paint() function. If the item is cached, i.e., ItemCoordinateCache or
2706     DeviceCoordinateCache, the effective property will be applied to the
2707     item's cache as it is rendered.
2708 
2709     There are two item flags that affect how the item's opacity is combined
2710     with the parent: ItemIgnoresParentOpacity and
2711     ItemDoesntPropagateOpacityToChildren.
2712 
2713     \sa opacity(), effectiveOpacity()
2714 */
setOpacity(qreal opacity)2715 void QGraphicsItem::setOpacity(qreal opacity)
2716 {
2717     // Notify change.
2718     const QVariant newOpacityVariant(itemChange(ItemOpacityChange, opacity));
2719 
2720     // Normalized opacity
2721     qreal newOpacity = qBound(qreal(0), newOpacityVariant.toReal(), qreal(1));
2722 
2723     // No change? Done.
2724     if (newOpacity == d_ptr->opacity)
2725         return;
2726 
2727     bool wasFullyTransparent = d_ptr->isOpacityNull();
2728     d_ptr->opacity = newOpacity;
2729 
2730     // Notify change.
2731     itemChange(ItemOpacityHasChanged, newOpacityVariant);
2732 
2733     // Update.
2734     if (d_ptr->scene) {
2735 #ifndef QT_NO_GRAPHICSEFFECT
2736         d_ptr->invalidateParentGraphicsEffectsRecursively();
2737         if (!(d_ptr->flags & ItemDoesntPropagateOpacityToChildren))
2738             d_ptr->invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::OpacityChanged);
2739 #endif //QT_NO_GRAPHICSEFFECT
2740         d_ptr->scene->d_func()->markDirty(this, QRectF(),
2741                                           /*invalidateChildren=*/true,
2742                                           /*force=*/false,
2743                                           /*ignoreOpacity=*/d_ptr->isOpacityNull());
2744         if (wasFullyTransparent)
2745             d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
2746     }
2747 
2748     if (d_ptr->isObject)
2749         emit static_cast<QGraphicsObject *>(this)->opacityChanged();
2750 }
2751 
2752 /*!
2753     Returns a pointer to this item's effect if it has one; otherwise 0.
2754 
2755     \since 4.6
2756 */
2757 #ifndef QT_NO_GRAPHICSEFFECT
graphicsEffect() const2758 QGraphicsEffect *QGraphicsItem::graphicsEffect() const
2759 {
2760     return d_ptr->graphicsEffect;
2761 }
2762 
2763 /*!
2764     Sets \a effect as the item's effect. If there already is an effect installed
2765     on this item, QGraphicsItem will delete the existing effect before installing
2766     the new \a effect.
2767 
2768     If \a effect is the installed on a different item, setGraphicsEffect() will remove
2769     the effect from the item and install it on this item.
2770 
2771     QGraphicsItem takes ownership of \a effect.
2772 
2773     \note This function will apply the effect on itself and all its children.
2774 
2775     \since 4.6
2776 */
setGraphicsEffect(QGraphicsEffect * effect)2777 void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
2778 {
2779     if (d_ptr->graphicsEffect == effect)
2780         return;
2781 
2782     if (d_ptr->graphicsEffect) {
2783         delete d_ptr->graphicsEffect;
2784         d_ptr->graphicsEffect = 0;
2785     } else if (d_ptr->parent) {
2786         d_ptr->parent->d_ptr->updateChildWithGraphicsEffectFlagRecursively();
2787     }
2788 
2789     if (effect) {
2790         // Set new effect.
2791         QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
2792         QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
2793         d_ptr->graphicsEffect = effect;
2794         effect->d_func()->setGraphicsEffectSource(source);
2795         prepareGeometryChange();
2796     }
2797 }
2798 #endif //QT_NO_GRAPHICSEFFECT
2799 
updateChildWithGraphicsEffectFlagRecursively()2800 void QGraphicsItemPrivate::updateChildWithGraphicsEffectFlagRecursively()
2801 {
2802 #ifndef QT_NO_GRAPHICSEFFECT
2803     QGraphicsItemPrivate *itemPrivate = this;
2804     do {
2805         // parent chain already notified?
2806         if (itemPrivate->mayHaveChildWithGraphicsEffect)
2807             return;
2808         itemPrivate->mayHaveChildWithGraphicsEffect = 1;
2809     } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
2810 #endif
2811 }
2812 
2813 /*!
2814     \internal
2815     \since 4.6
2816     Returns the effective bounding rect of the given item space rect.
2817     If the item has no effect, the rect is returned unmodified.
2818     If the item has an effect, the effective rect can be extend beyond the
2819     item's bounding rect, depending on the effect.
2820 
2821     \sa boundingRect()
2822 */
effectiveBoundingRect(const QRectF & rect) const2823 QRectF QGraphicsItemPrivate::effectiveBoundingRect(const QRectF &rect) const
2824 {
2825 #ifndef QT_NO_GRAPHICSEFFECT
2826     Q_Q(const QGraphicsItem);
2827     QGraphicsEffect *effect = graphicsEffect;
2828     if (scene && effect && effect->isEnabled()) {
2829         if (scene->d_func()->views.isEmpty())
2830             return effect->boundingRectFor(rect);
2831         QRectF sceneRect = q->mapRectToScene(rect);
2832         QRectF sceneEffectRect;
2833         foreach (QGraphicsView *view, scene->views()) {
2834             QRectF deviceRect = view->d_func()->mapRectFromScene(sceneRect);
2835             QRect deviceEffectRect = effect->boundingRectFor(deviceRect).toAlignedRect();
2836             sceneEffectRect |= view->d_func()->mapRectToScene(deviceEffectRect);
2837         }
2838         return q->mapRectFromScene(sceneEffectRect);
2839     }
2840 #endif //QT_NO_GRAPHICSEFFECT
2841     return rect;
2842 }
2843 
2844 /*!
2845     \internal
2846     \since 4.6
2847     Returns the effective bounding rect of the item.
2848     If the item has no effect, this is the same as the item's bounding rect.
2849     If the item has an effect, the effective rect can be larger than the item's
2850     bouding rect, depending on the effect.
2851 
2852     \sa boundingRect()
2853 */
effectiveBoundingRect(QGraphicsItem * topMostEffectItem) const2854 QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectItem) const
2855 {
2856 #ifndef QT_NO_GRAPHICSEFFECT
2857     Q_Q(const QGraphicsItem);
2858     QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
2859     if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren || topMostEffectItem == q)
2860         return brect;
2861 
2862     const QGraphicsItem *effectParent = parent;
2863     while (effectParent) {
2864         QGraphicsEffect *effect = effectParent->d_ptr->graphicsEffect;
2865         if (scene && effect && effect->isEnabled()) {
2866             const QRectF brectInParentSpace = q->mapRectToItem(effectParent, brect);
2867             const QRectF effectRectInParentSpace = effectParent->d_ptr->effectiveBoundingRect(brectInParentSpace);
2868             brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
2869         }
2870         if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
2871             || topMostEffectItem == effectParent) {
2872             return brect;
2873         }
2874         effectParent = effectParent->d_ptr->parent;
2875     }
2876 
2877     return brect;
2878 #else //QT_NO_GRAPHICSEFFECT
2879     return q_ptr->boundingRect();
2880 #endif //QT_NO_GRAPHICSEFFECT
2881 
2882 }
2883 
2884 /*!
2885     \internal
2886     \since 4.6
2887     Returns the effective bounding rect of this item in scene coordinates,
2888     by combining sceneTransform() with boundingRect(), taking into account
2889     the effect that the item might have.
2890 
2891     If the item has no effect, this is the same as sceneBoundingRect().
2892 
2893     \sa effectiveBoundingRect(), sceneBoundingRect()
2894 */
sceneEffectiveBoundingRect() const2895 QRectF QGraphicsItemPrivate::sceneEffectiveBoundingRect() const
2896 {
2897     // Find translate-only offset
2898     // COMBINE
2899     QPointF offset;
2900     const QGraphicsItem *parentItem = q_ptr;
2901     const QGraphicsItemPrivate *itemd;
2902     do {
2903         itemd = parentItem->d_ptr.data();
2904         if (itemd->transformData)
2905             break;
2906         offset += itemd->pos;
2907     } while ((parentItem = itemd->parent));
2908 
2909     QRectF br = effectiveBoundingRect();
2910     br.translate(offset);
2911     return !parentItem ? br : parentItem->sceneTransform().mapRect(br);
2912 }
2913 
2914 /*!
2915    Returns true if this item can accept drag and drop events; otherwise,
2916    returns false. By default, items do not accept drag and drop events; items
2917    are transparent to drag and drop.
2918 
2919    \sa setAcceptDrops()
2920 */
acceptDrops() const2921 bool QGraphicsItem::acceptDrops() const
2922 {
2923     return d_ptr->acceptDrops;
2924 }
2925 
2926 /*!
2927     If \a on is true, this item will accept drag and drop events; otherwise,
2928     it is transparent for drag and drop events. By default, items do not
2929     accept drag and drop events.
2930 
2931     \sa acceptDrops()
2932 */
setAcceptDrops(bool on)2933 void QGraphicsItem::setAcceptDrops(bool on)
2934 {
2935     d_ptr->acceptDrops = on;
2936 }
2937 
2938 /*!
2939     Returns the mouse buttons that this item accepts mouse events for.  By
2940     default, all mouse buttons are accepted.
2941 
2942     If an item accepts a mouse button, it will become the mouse
2943     grabber item when a mouse press event is delivered for that mouse
2944     button. However, if the item does not accept the button,
2945     QGraphicsScene will forward the mouse events to the first item
2946     beneath it that does.
2947 
2948     \sa setAcceptedMouseButtons(), mousePressEvent()
2949 */
acceptedMouseButtons() const2950 Qt::MouseButtons QGraphicsItem::acceptedMouseButtons() const
2951 {
2952     return Qt::MouseButtons(d_ptr->acceptedMouseButtons);
2953 }
2954 
2955 /*!
2956     Sets the mouse \a buttons that this item accepts mouse events for.
2957 
2958     By default, all mouse buttons are accepted. If an item accepts a
2959     mouse button, it will become the mouse grabber item when a mouse
2960     press event is delivered for that button. However, if the item
2961     does not accept the mouse button, QGraphicsScene will forward the
2962     mouse events to the first item beneath it that does.
2963 
2964     To disable mouse events for an item (i.e., make it transparent for mouse
2965     events), call setAcceptedMouseButtons(0).
2966 
2967     \sa acceptedMouseButtons(), mousePressEvent()
2968 */
setAcceptedMouseButtons(Qt::MouseButtons buttons)2969 void QGraphicsItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
2970 {
2971     if (Qt::MouseButtons(d_ptr->acceptedMouseButtons) != buttons) {
2972         if (buttons == 0 && d_ptr->scene && d_ptr->scene->mouseGrabberItem() == this
2973             && d_ptr->scene->d_func()->lastMouseGrabberItemHasImplicitMouseGrab) {
2974             ungrabMouse();
2975         }
2976         d_ptr->acceptedMouseButtons = quint32(buttons);
2977     }
2978 }
2979 
2980 /*!
2981     \since 4.4
2982 
2983     Returns true if an item accepts hover events
2984     (QGraphicsSceneHoverEvent); otherwise, returns false. By default,
2985     items do not accept hover events.
2986 
2987     \sa setAcceptedMouseButtons()
2988 */
acceptHoverEvents() const2989 bool QGraphicsItem::acceptHoverEvents() const
2990 {
2991     return d_ptr->acceptsHover;
2992 }
2993 
2994 /*!
2995     \obsolete
2996 
2997     Call acceptHoverEvents() instead.
2998 */
acceptsHoverEvents() const2999 bool QGraphicsItem::acceptsHoverEvents() const
3000 {
3001     return d_ptr->acceptsHover;
3002 }
3003 
3004 /*!
3005     \since 4.4
3006 
3007     If \a enabled is true, this item will accept hover events;
3008     otherwise, it will ignore them. By default, items do not accept
3009     hover events.
3010 
3011     Hover events are delivered when there is no current mouse grabber
3012     item.  They are sent when the mouse cursor enters an item, when it
3013     moves around inside the item, and when the cursor leaves an
3014     item. Hover events are commonly used to highlight an item when
3015     it's entered, and for tracking the mouse cursor as it hovers over
3016     the item (equivalent to QWidget::mouseTracking).
3017 
3018     Parent items receive hover enter events before their children, and
3019     leave events after their children. The parent does not receive a
3020     hover leave event if the cursor enters a child, though; the parent
3021     stays "hovered" until the cursor leaves its area, including its
3022     children's areas.
3023 
3024     If a parent item handles child events, it will receive hover move,
3025     drag move, and drop events as the cursor passes through its
3026     children, but it does not receive hover enter and hover leave, nor
3027     drag enter and drag leave events on behalf of its children.
3028 
3029     A QGraphicsWidget with window decorations will accept hover events
3030     regardless of the value of acceptHoverEvents().
3031 
3032     \sa acceptHoverEvents(), hoverEnterEvent(), hoverMoveEvent(),
3033     hoverLeaveEvent()
3034 */
setAcceptHoverEvents(bool enabled)3035 void QGraphicsItem::setAcceptHoverEvents(bool enabled)
3036 {
3037     if (d_ptr->acceptsHover == quint32(enabled))
3038         return;
3039     d_ptr->acceptsHover = quint32(enabled);
3040     if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) {
3041         d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false;
3042         d_ptr->scene->d_func()->enableMouseTrackingOnViews();
3043     }
3044 }
3045 
3046 /*!
3047     \obsolete
3048 
3049     Use setAcceptHoverEvents(\a enabled) instead.
3050 */
setAcceptsHoverEvents(bool enabled)3051 void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
3052 {
3053     setAcceptHoverEvents(enabled);
3054 }
3055 
3056 /*! \since 4.6
3057 
3058     Returns true if an item accepts \l{QTouchEvent}{touch events};
3059     otherwise, returns false. By default, items do not accept touch events.
3060 
3061     \sa setAcceptTouchEvents()
3062 */
acceptTouchEvents() const3063 bool QGraphicsItem::acceptTouchEvents() const
3064 {
3065     return d_ptr->acceptTouchEvents;
3066 }
3067 
3068 /*!
3069     \since 4.6
3070 
3071     If \a enabled is true, this item will accept \l{QTouchEvent}{touch events};
3072     otherwise, it will ignore them. By default, items do not accept
3073     touch events.
3074 */
setAcceptTouchEvents(bool enabled)3075 void QGraphicsItem::setAcceptTouchEvents(bool enabled)
3076 {
3077     if (d_ptr->acceptTouchEvents == quint32(enabled))
3078         return;
3079     d_ptr->acceptTouchEvents = quint32(enabled);
3080     if (d_ptr->acceptTouchEvents && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreTouchEvents) {
3081         d_ptr->scene->d_func()->allItemsIgnoreTouchEvents = false;
3082         d_ptr->scene->d_func()->enableTouchEventsOnViews();
3083     }
3084 }
3085 
3086 /*!
3087     \since 4.6
3088 
3089     Returns true if this item filters child events (i.e., all events
3090     intended for any of its children are instead sent to this item);
3091     otherwise, false is returned.
3092 
3093     The default value is false; child events are not filtered.
3094 
3095     \sa setFiltersChildEvents()
3096 */
filtersChildEvents() const3097 bool QGraphicsItem::filtersChildEvents() const
3098 {
3099     return d_ptr->filtersDescendantEvents;
3100 }
3101 
3102 /*!
3103     \since 4.6
3104 
3105     If \a enabled is true, this item is set to filter all events for
3106     all its children (i.e., all events intented for any of its
3107     children are instead sent to this item); otherwise, if \a enabled
3108     is false, this item will only handle its own events. The default
3109     value is false.
3110 
3111     \sa filtersChildEvents()
3112 */
setFiltersChildEvents(bool enabled)3113 void QGraphicsItem::setFiltersChildEvents(bool enabled)
3114 {
3115     if (d_ptr->filtersDescendantEvents == enabled)
3116         return;
3117 
3118     d_ptr->filtersDescendantEvents = enabled;
3119     d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
3120 }
3121 
3122 /*!
3123     \obsolete
3124 
3125     Returns true if this item handles child events (i.e., all events
3126     intended for any of its children are instead sent to this item);
3127     otherwise, false is returned.
3128 
3129     This property is useful for item groups; it allows one item to
3130     handle events on behalf of its children, as opposed to its
3131     children handling their events individually.
3132 
3133     The default is to return false; children handle their own events.
3134     The exception for this is if the item is a QGraphicsItemGroup, then
3135     it defaults to return true.
3136 
3137     \sa setHandlesChildEvents()
3138 */
handlesChildEvents() const3139 bool QGraphicsItem::handlesChildEvents() const
3140 {
3141     return d_ptr->handlesChildEvents;
3142 }
3143 
3144 /*!
3145     \obsolete
3146 
3147     If \a enabled is true, this item is set to handle all events for
3148     all its children (i.e., all events intented for any of its
3149     children are instead sent to this item); otherwise, if \a enabled
3150     is false, this item will only handle its own events. The default
3151     value is false.
3152 
3153     This property is useful for item groups; it allows one item to
3154     handle events on behalf of its children, as opposed to its
3155     children handling their events individually.
3156 
3157     If a child item accepts hover events, its parent will receive
3158     hover move events as the cursor passes through the child, but it
3159     does not receive hover enter and hover leave events on behalf of
3160     its child.
3161 
3162     \sa handlesChildEvents()
3163 */
setHandlesChildEvents(bool enabled)3164 void QGraphicsItem::setHandlesChildEvents(bool enabled)
3165 {
3166     if (d_ptr->handlesChildEvents == enabled)
3167         return;
3168 
3169     d_ptr->handlesChildEvents = enabled;
3170     d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
3171 }
3172 /*!
3173     \since 4.6
3174     Returns true if this item is active; otherwise returns false.
3175 
3176     An item can only be active if the scene is active. An item is active
3177     if it is, or is a descendent of, an active panel. Items in non-active
3178     panels are not active.
3179 
3180     Items that are not part of a panel follow scene activation when the
3181     scene has no active panel.
3182 
3183     Only active items can gain input focus.
3184 
3185     \sa QGraphicsScene::isActive(), QGraphicsScene::activePanel(), panel(), isPanel()
3186 */
isActive() const3187 bool QGraphicsItem::isActive() const
3188 {
3189     if (!d_ptr->scene || !d_ptr->scene->isActive())
3190         return false;
3191     return panel() == d_ptr->scene->activePanel();
3192 }
3193 
3194 /*!
3195     \since 4.6
3196 
3197     If \a active is true, and the scene is active, this item's panel will be
3198     activated. Otherwise, the panel is deactivated.
3199 
3200     If the item is not part of an active scene, \a active will decide what
3201     happens to the panel when the scene becomes active or the item is added to
3202     the scene. If true, the item's panel will be activated when the item is
3203     either added to the scene or the scene is activated. Otherwise, the item
3204     will stay inactive independent of the scene's activated state.
3205 
3206     \sa isPanel(), QGraphicsScene::setActivePanel(), QGraphicsScene::isActive()
3207 */
setActive(bool active)3208 void QGraphicsItem::setActive(bool active)
3209 {
3210     d_ptr->explicitActivate = 1;
3211     d_ptr->wantsActive = active;
3212     if (d_ptr->scene) {
3213         if (active) {
3214             // Activate this item.
3215             d_ptr->scene->setActivePanel(this);
3216         } else {
3217             // Deactivate this item, and reactivate the last active item
3218             // (if any).
3219             QGraphicsItem *lastActive = d_ptr->scene->d_func()->lastActivePanel;
3220             d_ptr->scene->setActivePanel(lastActive != this ? lastActive : 0);
3221         }
3222     }
3223 }
3224 
3225 /*!
3226     Returns true if this item is active, and it or its \l{focusProxy()}{focus
3227     proxy} has keyboard input focus; otherwise, returns false.
3228 
3229     \sa focusItem(), setFocus(), QGraphicsScene::setFocusItem(), isActive()
3230 */
hasFocus() const3231 bool QGraphicsItem::hasFocus() const
3232 {
3233     if (!d_ptr->scene || !d_ptr->scene->isActive())
3234         return false;
3235 
3236     if (d_ptr->focusProxy)
3237         return d_ptr->focusProxy->hasFocus();
3238 
3239     if (d_ptr->scene->d_func()->focusItem != this)
3240         return false;
3241 
3242     return panel() == d_ptr->scene->d_func()->activePanel;
3243 }
3244 
3245 /*!
3246     Gives keyboard input focus to this item. The \a focusReason argument will
3247     be passed into any \l{QFocusEvent}{focus event} generated by this function;
3248     it is used to give an explanation of what caused the item to get focus.
3249 
3250     Only enabled items that set the ItemIsFocusable flag can accept keyboard
3251     focus.
3252 
3253     If this item is not visible, not active, or not associated with a scene,
3254     it will not gain immediate input focus. However, it will be registered as
3255     the preferred focus item for its subtree of items, should it later become
3256     visible.
3257 
3258     As a result of calling this function, this item will receive a
3259     \l{focusInEvent()}{focus in event} with \a focusReason. If another item
3260     already has focus, that item will first receive a \l{focusOutEvent()}
3261     {focus out event} indicating that it has lost input focus.
3262 
3263     \sa clearFocus(), hasFocus(), focusItem(), focusProxy()
3264 */
setFocus(Qt::FocusReason focusReason)3265 void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
3266 {
3267     d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromHide = */ false);
3268 }
3269 
3270 /*!
3271     \internal
3272 */
setFocusHelper(Qt::FocusReason focusReason,bool climb,bool focusFromHide)3273 void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide)
3274 {
3275     // Disabled / unfocusable items cannot accept focus.
3276     if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable))
3277         return;
3278 
3279     // Find focus proxy.
3280     QGraphicsItem *f = q_ptr;
3281     while (f->d_ptr->focusProxy)
3282         f = f->d_ptr->focusProxy;
3283 
3284     // Return if it already has focus.
3285     if (scene && scene->focusItem() == f)
3286         return;
3287 
3288     // Update focus scope item ptr.
3289     QGraphicsItem *p = parent;
3290     while (p) {
3291         if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
3292             QGraphicsItem *oldFocusScopeItem = p->d_ptr->focusScopeItem;
3293             p->d_ptr->focusScopeItem = q_ptr;
3294             if (oldFocusScopeItem)
3295                 oldFocusScopeItem->d_ptr->focusScopeItemChange(false);
3296             focusScopeItemChange(true);
3297             if (!p->focusItem() && !focusFromHide) {
3298                 // Calling setFocus() on a child of a focus scope that does
3299                 // not have focus changes only the focus scope pointer,
3300                 // so that focus is restored the next time the scope gains
3301                 // focus.
3302                 return;
3303             }
3304             break;
3305         }
3306         p = p->d_ptr->parent;
3307     }
3308 
3309     if (climb) {
3310         while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible())
3311             f = f->d_ptr->focusScopeItem;
3312     }
3313 
3314     // Update the child focus chain.
3315     QGraphicsItem *commonAncestor = 0;
3316     if (scene && scene->focusItem()) {
3317         commonAncestor = scene->focusItem()->commonAncestorItem(f);
3318         scene->focusItem()->d_ptr->clearSubFocus(scene->focusItem(), commonAncestor);
3319     }
3320 
3321     f->d_ptr->setSubFocus(f, commonAncestor);
3322 
3323     // Update the scene's focus item.
3324     if (scene) {
3325         QGraphicsItem *p = q_ptr->panel();
3326         if ((!p && scene->isActive()) || (p && p->isActive())) {
3327             // Visible items immediately gain focus from scene.
3328             scene->d_func()->setFocusItemHelper(f, focusReason);
3329         }
3330     }
3331 }
3332 
3333 /*!
3334     Takes keyboard input focus from the item.
3335 
3336     If it has focus, a \l{focusOutEvent()}{focus out event} is sent to this
3337     item to tell it that it is about to lose the focus.
3338 
3339     Only items that set the ItemIsFocusable flag, or widgets that set an
3340     appropriate focus policy, can accept keyboard focus.
3341 
3342     \sa setFocus(), hasFocus(), QGraphicsWidget::focusPolicy
3343 */
clearFocus()3344 void QGraphicsItem::clearFocus()
3345 {
3346     d_ptr->clearFocusHelper(/* giveFocusToParent = */ true);
3347 }
3348 
3349 /*!
3350     \internal
3351 */
clearFocusHelper(bool giveFocusToParent)3352 void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent)
3353 {
3354     QGraphicsItem *subFocusItem = q_ptr;
3355     if (flags & QGraphicsItem::ItemIsFocusScope) {
3356         while (subFocusItem->d_ptr->focusScopeItem)
3357             subFocusItem = subFocusItem->d_ptr->focusScopeItem;
3358     }
3359 
3360     if (giveFocusToParent) {
3361         // Pass focus to the closest parent focus scope
3362         if (!inDestructor) {
3363             QGraphicsItem *p = parent;
3364             while (p) {
3365                 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
3366                     if (p->d_ptr->focusScopeItem == q_ptr) {
3367                         p->d_ptr->focusScopeItem = 0;
3368                         if (!subFocusItem->hasFocus()) //if it has focus, focusScopeItemChange is called elsewhere
3369                             focusScopeItemChange(false);
3370                     }
3371                     if (subFocusItem->hasFocus())
3372                         p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
3373                                                  /* focusFromHide = */ false);
3374                     return;
3375                 }
3376                 p = p->d_ptr->parent;
3377             }
3378         }
3379     }
3380 
3381     if (subFocusItem->hasFocus()) {
3382         // Invisible items with focus must explicitly clear subfocus.
3383         clearSubFocus(q_ptr);
3384 
3385         // If this item has the scene's input focus, clear it.
3386         scene->setFocusItem(0);
3387     }
3388 }
3389 
3390 /*!
3391     \since 4.6
3392 
3393     Returns this item's focus proxy, or 0 if this item has no
3394     focus proxy.
3395 
3396     \sa setFocusProxy(), setFocus(), hasFocus()
3397 */
focusProxy() const3398 QGraphicsItem *QGraphicsItem::focusProxy() const
3399 {
3400     return d_ptr->focusProxy;
3401 }
3402 
3403 /*!
3404     \since 4.6
3405 
3406     Sets the item's focus proxy to \a item.
3407 
3408     If an item has a focus proxy, the focus proxy will receive
3409     input focus when the item gains input focus. The item itself
3410     will still have focus (i.e., hasFocus() will return true),
3411     but only the focus proxy will receive the keyboard input.
3412 
3413     A focus proxy can itself have a focus proxy, and so on. In
3414     such case, keyboard input will be handled by the outermost
3415     focus proxy.
3416 
3417     The focus proxy \a item must belong to the same scene as
3418     this item.
3419 
3420     \sa focusProxy(), setFocus(), hasFocus()
3421 */
setFocusProxy(QGraphicsItem * item)3422 void QGraphicsItem::setFocusProxy(QGraphicsItem *item)
3423 {
3424     if (item == d_ptr->focusProxy)
3425         return;
3426     if (item == this) {
3427         qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
3428         return;
3429     }
3430     if (item) {
3431         if (item->d_ptr->scene != d_ptr->scene) {
3432             qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
3433             return;
3434         }
3435         for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) {
3436             if (f == this) {
3437                 qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item);
3438                 return;
3439             }
3440         }
3441     }
3442 
3443     QGraphicsItem *lastFocusProxy = d_ptr->focusProxy;
3444     if (lastFocusProxy)
3445         lastFocusProxy->d_ptr->focusProxyRefs.removeOne(&d_ptr->focusProxy);
3446     d_ptr->focusProxy = item;
3447     if (item)
3448         item->d_ptr->focusProxyRefs << &d_ptr->focusProxy;
3449 }
3450 
3451 /*!
3452     \since 4.6
3453 
3454     If this item, a child or descendant of this item currently has input
3455     focus, this function will return a pointer to that item. If
3456     no descendant has input focus, 0 is returned.
3457 
3458     \sa hasFocus(), setFocus(), QWidget::focusWidget()
3459 */
focusItem() const3460 QGraphicsItem *QGraphicsItem::focusItem() const
3461 {
3462     return d_ptr->subFocusItem;
3463 }
3464 
3465 /*!
3466     \internal
3467 
3468     Returns this item's focus scope item.
3469 */
focusScopeItem() const3470 QGraphicsItem *QGraphicsItem::focusScopeItem() const
3471 {
3472     return d_ptr->focusScopeItem;
3473 }
3474 
3475 /*!
3476     \since 4.4
3477     Grabs the mouse input.
3478 
3479     This item will receive all mouse events for the scene until any of the
3480     following events occurs:
3481 
3482     \list
3483     \o The item becomes invisible
3484     \o The item is removed from the scene
3485     \o The item is deleted
3486     \o The item call ungrabMouse()
3487     \o Another item calls grabMouse(); the item will regain the mouse grab
3488     when the other item calls ungrabMouse().
3489     \endlist
3490 
3491     When an item gains the mouse grab, it receives a QEvent::GrabMouse
3492     event. When it loses the mouse grab, it receives a QEvent::UngrabMouse
3493     event. These events can be used to detect when your item gains or loses
3494     the mouse grab through other means than receiving mouse button events.
3495 
3496     It is almost never necessary to explicitly grab the mouse in Qt, as Qt
3497     grabs and releases it sensibly. In particular, Qt grabs the mouse when you
3498     press a mouse button, and keeps the mouse grabbed until you release the
3499     last mouse button. Also, Qt::Popup widgets implicitly call grabMouse()
3500     when shown, and ungrabMouse() when hidden.
3501 
3502     Note that only visible items can grab mouse input. Calling grabMouse() on
3503     an invisible item has no effect.
3504 
3505     Keyboard events are not affected.
3506 
3507     \sa QGraphicsScene::mouseGrabberItem(), ungrabMouse(), grabKeyboard()
3508 */
grabMouse()3509 void QGraphicsItem::grabMouse()
3510 {
3511     if (!d_ptr->scene) {
3512         qWarning("QGraphicsItem::grabMouse: cannot grab mouse without scene");
3513         return;
3514     }
3515     if (!d_ptr->visible) {
3516         qWarning("QGraphicsItem::grabMouse: cannot grab mouse while invisible");
3517         return;
3518     }
3519     d_ptr->scene->d_func()->grabMouse(this);
3520 }
3521 
3522 /*!
3523     \since 4.4
3524     Releases the mouse grab.
3525 
3526     \sa grabMouse(), ungrabKeyboard()
3527 */
ungrabMouse()3528 void QGraphicsItem::ungrabMouse()
3529 {
3530     if (!d_ptr->scene) {
3531         qWarning("QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene");
3532         return;
3533     }
3534     d_ptr->scene->d_func()->ungrabMouse(this);
3535 }
3536 
3537 /*!
3538     \since 4.4
3539     Grabs the keyboard input.
3540 
3541     The item will receive all keyboard input to the scene until one of the
3542     following events occur:
3543 
3544     \list
3545     \o The item becomes invisible
3546     \o The item is removed from the scene
3547     \o The item is deleted
3548     \o The item calls ungrabKeyboard()
3549     \o Another item calls grabKeyboard(); the item will regain the keyboard grab
3550     when the other item calls ungrabKeyboard().
3551     \endlist
3552 
3553     When an item gains the keyboard grab, it receives a QEvent::GrabKeyboard
3554     event. When it loses the keyboard grab, it receives a
3555     QEvent::UngrabKeyboard event. These events can be used to detect when your
3556     item gains or loses the keyboard grab through other means than gaining
3557     input focus.
3558 
3559     It is almost never necessary to explicitly grab the keyboard in Qt, as Qt
3560     grabs and releases it sensibly. In particular, Qt grabs the keyboard when
3561     your item gains input focus, and releases it when your item loses input
3562     focus, or when the item is hidden.
3563 
3564     Note that only visible items can grab keyboard input. Calling
3565     grabKeyboard() on an invisible item has no effect.
3566 
3567     Keyboard events are not affected.
3568 
3569     \sa ungrabKeyboard(), grabMouse(), setFocus()
3570 */
grabKeyboard()3571 void QGraphicsItem::grabKeyboard()
3572 {
3573     if (!d_ptr->scene) {
3574         qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard without scene");
3575         return;
3576     }
3577     if (!d_ptr->visible) {
3578         qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard while invisible");
3579         return;
3580     }
3581     d_ptr->scene->d_func()->grabKeyboard(this);
3582 }
3583 
3584 /*!
3585     \since 4.4
3586     Releases the keyboard grab.
3587 
3588     \sa grabKeyboard(), ungrabMouse()
3589 */
ungrabKeyboard()3590 void QGraphicsItem::ungrabKeyboard()
3591 {
3592     if (!d_ptr->scene) {
3593         qWarning("QGraphicsItem::ungrabKeyboard: cannot ungrab keyboard without scene");
3594         return;
3595     }
3596     d_ptr->scene->d_func()->ungrabKeyboard(this);
3597 }
3598 
3599 /*!
3600     Returns the position of the item in parent coordinates. If the item has no
3601     parent, its position is given in scene coordinates.
3602 
3603     The position of the item describes its origin (local coordinate
3604     (0, 0)) in parent coordinates; this function returns the same as
3605     mapToParent(0, 0).
3606 
3607     For convenience, you can also call scenePos() to determine the
3608     item's position in scene coordinates, regardless of its parent.
3609 
3610     \sa x(), y(), setPos(), transform(), {The Graphics View Coordinate System}
3611 */
pos() const3612 QPointF QGraphicsItem::pos() const
3613 {
3614     return d_ptr->pos;
3615 }
3616 
3617 /*!
3618     \fn QGraphicsItem::x() const
3619 
3620     This convenience function is equivalent to calling pos().x().
3621 
3622     \sa y()
3623 */
3624 
3625 /*!
3626     \since 4.6
3627 
3628     Set's the \a x coordinate of the item's position. Equivalent to
3629     calling setPos(x, y()).
3630 
3631     \sa x(), setPos()
3632 */
setX(qreal x)3633 void QGraphicsItem::setX(qreal x)
3634 {
3635     if (d_ptr->inDestructor)
3636         return;
3637 
3638     if (qIsNaN(x))
3639         return;
3640 
3641     setPos(QPointF(x, d_ptr->pos.y()));
3642 }
3643 
3644 /*!
3645     \fn QGraphicsItem::y() const
3646 
3647     This convenience function is equivalent to calling pos().y().
3648 
3649     \sa x()
3650 */
3651 
3652 /*!
3653     \since 4.6
3654 
3655     Set's the \a y coordinate of the item's position. Equivalent to
3656     calling setPos(x(), y).
3657 
3658     \sa x(), setPos()
3659 */
setY(qreal y)3660 void QGraphicsItem::setY(qreal y)
3661 {
3662     if (d_ptr->inDestructor)
3663         return;
3664 
3665     if (qIsNaN(y))
3666         return;
3667 
3668     setPos(QPointF(d_ptr->pos.x(), y));
3669 }
3670 
3671 /*!
3672     Returns the item's position in scene coordinates. This is
3673     equivalent to calling \c mapToScene(0, 0).
3674 
3675     \sa pos(), sceneTransform(), {The Graphics View Coordinate System}
3676 */
scenePos() const3677 QPointF QGraphicsItem::scenePos() const
3678 {
3679     return mapToScene(0, 0);
3680 }
3681 
3682 /*!
3683     \internal
3684 
3685     Sets the position \a pos.
3686 */
setPosHelper(const QPointF & pos)3687 void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
3688 {
3689     Q_Q(QGraphicsItem);
3690     inSetPosHelper = 1;
3691     if (scene)
3692         q->prepareGeometryChange();
3693     QPointF oldPos = this->pos;
3694     this->pos = pos;
3695     dirtySceneTransform = 1;
3696     inSetPosHelper = 0;
3697     if (isObject) {
3698         if (pos.x() != oldPos.x())
3699             emit static_cast<QGraphicsObject *>(q_ptr)->xChanged();
3700         if (pos.y() != oldPos.y())
3701             emit static_cast<QGraphicsObject *>(q_ptr)->yChanged();
3702     }
3703 }
3704 
3705 /*!
3706     \internal
3707 
3708     Sets the transform \a transform.
3709 */
setTransformHelper(const QTransform & transform)3710 void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform)
3711 {
3712     q_ptr->prepareGeometryChange();
3713     transformData->transform = transform;
3714     dirtySceneTransform = 1;
3715     transformChanged();
3716 }
3717 
3718 /*!
3719     Sets the position of the item to \a pos, which is in parent
3720     coordinates.  For items with no parent, \a pos is in scene
3721     coordinates.
3722 
3723     The position of the item describes its origin (local coordinate
3724     (0, 0)) in parent coordinates.
3725 
3726     \sa pos(), scenePos(), {The Graphics View Coordinate System}
3727 */
setPos(const QPointF & pos)3728 void QGraphicsItem::setPos(const QPointF &pos)
3729 {
3730     if (d_ptr->pos == pos)
3731         return;
3732 
3733     if (d_ptr->inDestructor)
3734         return;
3735 
3736     // Update and repositition.
3737     if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) {
3738         d_ptr->setPosHelper(pos);
3739         if (d_ptr->isWidget)
3740             static_cast<QGraphicsWidget *>(this)->d_func()->setGeometryFromSetPos();
3741         if (d_ptr->scenePosDescendants)
3742             d_ptr->sendScenePosChange();
3743         return;
3744     }
3745 
3746     // Notify the item that the position is changing.
3747     const QVariant newPosVariant(itemChange(ItemPositionChange, QVariant::fromValue<QPointF>(pos)));
3748     QPointF newPos = newPosVariant.toPointF();
3749     if (newPos == d_ptr->pos)
3750         return;
3751 
3752     // Update and repositition.
3753     d_ptr->setPosHelper(newPos);
3754 
3755     // Send post-notification.
3756     itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
3757     d_ptr->sendScenePosChange();
3758 }
3759 
3760 /*!
3761     \fn void QGraphicsItem::setPos(qreal x, qreal y)
3762     \overload
3763 
3764     This convenience function is equivalent to calling setPos(QPointF(\a x, \a
3765     y)).
3766 */
3767 
3768 /*!
3769     \fn void QGraphicsItem::moveBy(qreal dx, qreal dy)
3770 
3771     Moves the item by \a dx points horizontally, and \a dy point
3772     vertically. This function is equivalent to calling setPos(pos() +
3773     QPointF(\a dx, \a dy)).
3774 */
3775 
3776 /*!
3777     If this item is part of a scene that is viewed by a QGraphicsView, this
3778     convenience function will attempt to scroll the view to ensure that \a
3779     rect is visible inside the view's viewport. If \a rect is a null rect (the
3780     default), QGraphicsItem will default to the item's bounding rect. \a xmargin
3781     and \a ymargin are the number of pixels the view should use for margins.
3782 
3783     If the specified rect cannot be reached, the contents are scrolled to the
3784     nearest valid position.
3785 
3786     If this item is not viewed by a QGraphicsView, this function does nothing.
3787 
3788     \sa QGraphicsView::ensureVisible()
3789 */
ensureVisible(const QRectF & rect,int xmargin,int ymargin)3790 void QGraphicsItem::ensureVisible(const QRectF &rect, int xmargin, int ymargin)
3791 {
3792     if (d_ptr->scene) {
3793         QRectF sceneRect;
3794         if (!rect.isNull())
3795             sceneRect = sceneTransform().mapRect(rect);
3796         else
3797             sceneRect = sceneBoundingRect();
3798         foreach (QGraphicsView *view, d_ptr->scene->d_func()->views)
3799             view->ensureVisible(sceneRect, xmargin, ymargin);
3800     }
3801 }
3802 
3803 /*!
3804     \fn void QGraphicsItem::ensureVisible(qreal x, qreal y, qreal w, qreal h,
3805     int xmargin = 50, int ymargin = 50)
3806 
3807     This convenience function is equivalent to calling
3808     ensureVisible(QRectF(\a x, \a y, \a w, \a h), \a xmargin, \a ymargin):
3809 */
3810 
3811 /*!
3812     \obsolete
3813 
3814     Returns the item's affine transformation matrix. This is a subset or the
3815     item's full transformation matrix, and might not represent the item's full
3816     transformation.
3817 
3818     Use transform() instead.
3819 
3820     \sa setTransform(), sceneTransform()
3821 */
matrix() const3822 QMatrix QGraphicsItem::matrix() const
3823 {
3824     return transform().toAffine();
3825 }
3826 
3827 /*!
3828     \since 4.3
3829 
3830     Returns this item's transformation matrix.
3831 
3832     The transformation matrix is combined with the item's rotation(), scale()
3833     and transformations() into a combined transformations for the item.
3834 
3835     The default transformation matrix is an identity matrix.
3836 
3837     \sa setTransform(), sceneTransform()
3838 */
transform() const3839 QTransform QGraphicsItem::transform() const
3840 {
3841     if (!d_ptr->transformData)
3842         return QTransform();
3843     return d_ptr->transformData->transform;
3844 }
3845 
3846 /*!
3847     \since 4.6
3848 
3849     Returns the clockwise rotation, in degrees, around the Z axis. The default
3850     value is 0 (i.e., the item is not rotated).
3851 
3852     The rotation is combined with the item's scale(), transform() and
3853     transformations() to map the item's coordinate system to the parent item.
3854 
3855     \sa setRotation(), transformOriginPoint(), {Transformations}
3856 */
rotation() const3857 qreal QGraphicsItem::rotation() const
3858 {
3859     if (!d_ptr->transformData)
3860         return 0;
3861     return d_ptr->transformData->rotation;
3862 }
3863 
3864 /*!
3865     \since 4.6
3866 
3867     Sets the clockwise rotation \a angle, in degrees, around the Z axis. The
3868     default value is 0 (i.e., the item is not rotated). Assigning a negative
3869     value will rotate the item counter-clockwise. Normally the rotation angle
3870     is in the range (-360, 360), but it's also possible to assign values
3871     outside of this range (e.g., a rotation of 370 degrees is the same as a
3872     rotation of 10 degrees).
3873 
3874     The item is rotated around its transform origin point, which by default
3875     is (0, 0). You can select a different transformation origin by calling
3876     setTransformOriginPoint().
3877 
3878     The rotation is combined with the item's scale(), transform() and
3879     transformations() to map the item's coordinate system to the parent item.
3880 
3881     \sa rotation(), setTransformOriginPoint(), {Transformations}
3882 */
setRotation(qreal angle)3883 void QGraphicsItem::setRotation(qreal angle)
3884 {
3885     prepareGeometryChange();
3886     qreal newRotation = angle;
3887 
3888     if (d_ptr->flags & ItemSendsGeometryChanges) {
3889         // Notify the item that the rotation is changing.
3890         const QVariant newRotationVariant(itemChange(ItemRotationChange, angle));
3891         newRotation = newRotationVariant.toReal();
3892     }
3893 
3894     if (!d_ptr->transformData)
3895         d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
3896 
3897     if (d_ptr->transformData->rotation == newRotation)
3898         return;
3899 
3900     d_ptr->transformData->rotation = newRotation;
3901     d_ptr->transformData->onlyTransform = false;
3902     d_ptr->dirtySceneTransform = 1;
3903 
3904     // Send post-notification.
3905     if (d_ptr->flags & ItemSendsGeometryChanges)
3906         itemChange(ItemRotationHasChanged, newRotation);
3907 
3908     if (d_ptr->isObject)
3909         emit static_cast<QGraphicsObject *>(this)->rotationChanged();
3910 
3911     d_ptr->transformChanged();
3912 }
3913 
3914 /*!
3915     \since 4.6
3916 
3917     Returns the scale factor of the item. The default scale factor is 1.0
3918     (i.e., the item is not scaled).
3919 
3920     The scale is combined with the item's rotation(), transform() and
3921     transformations() to map the item's coordinate system to the parent item.
3922 
3923     \sa setScale(), rotation(), {Transformations}
3924 */
scale() const3925 qreal QGraphicsItem::scale() const
3926 {
3927     if (!d_ptr->transformData)
3928         return 1.;
3929     return d_ptr->transformData->scale;
3930 }
3931 
3932 /*!
3933     \since 4.6
3934 
3935     Sets the scale \a factor of the item. The default scale factor is 1.0
3936     (i.e., the item is not scaled). A scale factor of 0.0 will collapse the
3937     item to a single point. If you provide a negative scale factor, the
3938     item will be flipped and mirrored (i.e., rotated 180 degrees).
3939 
3940     The item is scaled around its transform origin point, which by default
3941     is (0, 0). You can select a different transformation origin by calling
3942     setTransformOriginPoint().
3943 
3944     The scale is combined with the item's rotation(), transform() and
3945     transformations() to map the item's coordinate system to the parent item.
3946 
3947     \sa scale(), setTransformOriginPoint(), {Transformations Example}
3948 */
setScale(qreal factor)3949 void QGraphicsItem::setScale(qreal factor)
3950 {
3951     prepareGeometryChange();
3952     qreal newScale = factor;
3953 
3954     if (d_ptr->flags & ItemSendsGeometryChanges) {
3955         // Notify the item that the scale is changing.
3956         const QVariant newScaleVariant(itemChange(ItemScaleChange, factor));
3957         newScale = newScaleVariant.toReal();
3958     }
3959 
3960     if (!d_ptr->transformData)
3961         d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
3962 
3963     if (d_ptr->transformData->scale == newScale)
3964         return;
3965 
3966     d_ptr->transformData->scale = newScale;
3967     d_ptr->transformData->onlyTransform = false;
3968     d_ptr->dirtySceneTransform = 1;
3969 
3970     // Send post-notification.
3971     if (d_ptr->flags & ItemSendsGeometryChanges)
3972         itemChange(ItemScaleHasChanged, newScale);
3973 
3974     if (d_ptr->isObject)
3975         emit static_cast<QGraphicsObject *>(this)->scaleChanged();
3976 
3977     d_ptr->transformChanged();
3978 }
3979 
3980 
3981 /*!
3982     \since 4.6
3983 
3984     Returns a list of graphics transforms that currently apply to this item.
3985 
3986     QGraphicsTransform is for applying and controlling a chain of individual
3987     transformation operations on an item. It's particularly useful in
3988     animations, where each transform operation needs to be interpolated
3989     independently, or differently.
3990 
3991     The transformations are combined with the item's rotation(), scale() and
3992     transform() to map the item's coordinate system to the parent item.
3993 
3994     \sa scale(), rotation(), transformOriginPoint(), {Transformations}
3995 */
transformations() const3996 QList<QGraphicsTransform *> QGraphicsItem::transformations() const
3997 {
3998     if (!d_ptr->transformData)
3999         return QList<QGraphicsTransform *>();
4000     return d_ptr->transformData->graphicsTransforms;
4001 }
4002 
4003 /*!
4004     \since 4.6
4005 
4006     Sets a list of graphics \a transformations (QGraphicsTransform) that
4007     currently apply to this item.
4008 
4009     If all you want is to rotate or scale an item, you should call setRotation()
4010     or setScale() instead. If you want to set an arbitrary transformation on
4011     an item, you can call setTransform().
4012 
4013     QGraphicsTransform is for applying and controlling a chain of individual
4014     transformation operations on an item. It's particularly useful in
4015     animations, where each transform operation needs to be interpolated
4016     independently, or differently.
4017 
4018     The transformations are combined with the item's rotation(), scale() and
4019     transform() to map the item's coordinate system to the parent item.
4020 
4021     \sa scale(), setTransformOriginPoint(), {Transformations}
4022 */
setTransformations(const QList<QGraphicsTransform * > & transformations)4023 void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transformations)
4024 {
4025     prepareGeometryChange();
4026     if (!d_ptr->transformData)
4027         d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
4028     d_ptr->transformData->graphicsTransforms = transformations;
4029     for (int i = 0; i < transformations.size(); ++i)
4030         transformations.at(i)->d_func()->setItem(this);
4031     d_ptr->transformData->onlyTransform = false;
4032     d_ptr->dirtySceneTransform = 1;
4033     d_ptr->transformChanged();
4034 }
4035 
4036 /*!
4037     \internal
4038 */
prependGraphicsTransform(QGraphicsTransform * t)4039 void QGraphicsItemPrivate::prependGraphicsTransform(QGraphicsTransform *t)
4040 {
4041     if (!transformData)
4042         transformData = new QGraphicsItemPrivate::TransformData;
4043     if (!transformData->graphicsTransforms.contains(t))
4044         transformData->graphicsTransforms.prepend(t);
4045 
4046     Q_Q(QGraphicsItem);
4047     t->d_func()->setItem(q);
4048     transformData->onlyTransform = false;
4049     dirtySceneTransform = 1;
4050     transformChanged();
4051 }
4052 
4053 /*!
4054     \internal
4055 */
appendGraphicsTransform(QGraphicsTransform * t)4056 void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t)
4057 {
4058     if (!transformData)
4059         transformData = new QGraphicsItemPrivate::TransformData;
4060     if (!transformData->graphicsTransforms.contains(t))
4061         transformData->graphicsTransforms.append(t);
4062 
4063     Q_Q(QGraphicsItem);
4064     t->d_func()->setItem(q);
4065     transformData->onlyTransform = false;
4066     dirtySceneTransform = 1;
4067     transformChanged();
4068 }
4069 
4070 /*!
4071     \since 4.6
4072 
4073     Returns the origin point for the transformation in item coordinates.
4074 
4075     The default is QPointF(0,0).
4076 
4077     \sa setTransformOriginPoint(), {Transformations}
4078 */
transformOriginPoint() const4079 QPointF QGraphicsItem::transformOriginPoint() const
4080 {
4081     if (!d_ptr->transformData)
4082         return QPointF(0,0);
4083     return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin);
4084 }
4085 
4086 /*!
4087     \since 4.6
4088 
4089     Sets the \a origin point for the transformation in item coordinates.
4090 
4091     \sa transformOriginPoint(), {Transformations}
4092 */
setTransformOriginPoint(const QPointF & origin)4093 void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
4094 {
4095     prepareGeometryChange();
4096     QPointF newOrigin = origin;
4097 
4098     if (d_ptr->flags & ItemSendsGeometryChanges) {
4099         // Notify the item that the origin point is changing.
4100         const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange,
4101                                                    QVariant::fromValue<QPointF>(origin)));
4102         newOrigin = newOriginVariant.toPointF();
4103     }
4104 
4105     if (!d_ptr->transformData)
4106         d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
4107 
4108     if (d_ptr->transformData->xOrigin == newOrigin.x()
4109         && d_ptr->transformData->yOrigin == newOrigin.y()) {
4110         return;
4111     }
4112 
4113     d_ptr->transformData->xOrigin = newOrigin.x();
4114     d_ptr->transformData->yOrigin = newOrigin.y();
4115     d_ptr->transformData->onlyTransform = false;
4116     d_ptr->dirtySceneTransform = 1;
4117 
4118     // Send post-notification.
4119     if (d_ptr->flags & ItemSendsGeometryChanges)
4120         itemChange(ItemTransformOriginPointHasChanged, QVariant::fromValue<QPointF>(newOrigin));
4121 }
4122 
4123 /*!
4124     \fn void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y)
4125 
4126     \since 4.6
4127     \overload
4128 
4129     Sets the origin point for the transformation in item coordinates.
4130     This is equivalent to calling setTransformOriginPoint(QPointF(\a x, \a y)).
4131 
4132     \sa setTransformOriginPoint(), {Transformations}
4133 */
4134 
4135 
4136 /*!
4137     \obsolete
4138 
4139     Use sceneTransform() instead.
4140 
4141     \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}
4142 */
sceneMatrix() const4143 QMatrix QGraphicsItem::sceneMatrix() const
4144 {
4145     d_ptr->ensureSceneTransform();
4146     return d_ptr->sceneTransform.toAffine();
4147 }
4148 
4149 
4150 /*!
4151     \since 4.3
4152 
4153     Returns this item's scene transformation matrix. This matrix can be used
4154     to map coordinates and geometrical shapes from this item's local
4155     coordinate system to the scene's coordinate system. To map coordinates
4156     from the scene, you must first invert the returned matrix.
4157 
4158     Example:
4159 
4160     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 4
4161 
4162     Unlike transform(), which returns only an item's local transformation, this
4163     function includes the item's (and any parents') position, and all the transfomation properties.
4164 
4165     \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations}
4166 */
sceneTransform() const4167 QTransform QGraphicsItem::sceneTransform() const
4168 {
4169     d_ptr->ensureSceneTransform();
4170     return d_ptr->sceneTransform;
4171 }
4172 
4173 /*!
4174     \since 4.3
4175 
4176     Returns this item's device transformation matrix, using \a
4177     viewportTransform to map from scene to device coordinates. This matrix can
4178     be used to map coordinates and geometrical shapes from this item's local
4179     coordinate system to the viewport's (or any device's) coordinate
4180     system. To map coordinates from the viewport, you must first invert the
4181     returned matrix.
4182 
4183     Example:
4184 
4185     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 5
4186 
4187     This function is the same as combining this item's scene transform with
4188     the view's viewport transform, but it also understands the
4189     ItemIgnoresTransformations flag. The device transform can be used to do
4190     accurate coordinate mapping (and collision detection) for untransformable
4191     items.
4192 
4193     \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate
4194     System}, itemTransform()
4195 */
deviceTransform(const QTransform & viewportTransform) const4196 QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const
4197 {
4198     // Ensure we return the standard transform if we're not untransformable.
4199     if (!d_ptr->itemIsUntransformable()) {
4200         d_ptr->ensureSceneTransform();
4201         return d_ptr->sceneTransform * viewportTransform;
4202     }
4203 
4204     // Find the topmost item that ignores view transformations.
4205     const QGraphicsItem *untransformedAncestor = this;
4206     QList<const QGraphicsItem *> parents;
4207     while (untransformedAncestor && ((untransformedAncestor->d_ptr->ancestorFlags
4208                                      & QGraphicsItemPrivate::AncestorIgnoresTransformations))) {
4209         parents.prepend(untransformedAncestor);
4210         untransformedAncestor = untransformedAncestor->parentItem();
4211     }
4212 
4213     if (!untransformedAncestor) {
4214         // Assert in debug mode, continue in release.
4215         Q_ASSERT_X(untransformedAncestor, "QGraphicsItem::deviceTransform",
4216                    "Invalid object structure!");
4217         return QTransform();
4218     }
4219 
4220     // Determine the inherited origin. Find the parent of the topmost untransformable.
4221     // Use its scene transform to map the position of the untransformable. Then use
4222     // that viewport position as the anchoring point for the untransformable subtree.
4223     QGraphicsItem *parentOfUntransformedAncestor = untransformedAncestor->parentItem();
4224     QTransform inheritedMatrix;
4225     if (parentOfUntransformedAncestor)
4226         inheritedMatrix = parentOfUntransformedAncestor->sceneTransform();
4227     QPointF mappedPoint = (inheritedMatrix * viewportTransform).map(untransformedAncestor->pos());
4228 
4229     // COMBINE
4230     QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y());
4231     if (untransformedAncestor->d_ptr->transformData)
4232         matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform(&matrix);
4233 
4234     // Then transform and translate all children.
4235     for (int i = 0; i < parents.size(); ++i) {
4236         const QGraphicsItem *parent = parents.at(i);
4237         parent->d_ptr->combineTransformFromParent(&matrix);
4238     }
4239 
4240     return matrix;
4241 }
4242 
4243 /*!
4244     \since 4.5
4245 
4246     Returns a QTransform that maps coordinates from this item to \a other. If
4247     \a ok is not null, and if there is no such transform, the boolean pointed
4248     to by \a ok will be set to false; otherwise it will be set to true.
4249 
4250     This transform provides an alternative to the mapToItem() or mapFromItem()
4251     functions, by returning the appropriate transform so that you can map
4252     shapes and coordinates yourself. It also helps you write more efficient
4253     code when repeatedly mapping between the same two items.
4254 
4255     \note In rare circumstances, there is no transform that maps between two
4256     items.
4257 
4258     \sa mapToItem(), mapFromItem(), deviceTransform()
4259 */
itemTransform(const QGraphicsItem * other,bool * ok) const4260 QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) const
4261 {
4262     // Catch simple cases first.
4263     if (other == 0) {
4264         qWarning("QGraphicsItem::itemTransform: null pointer passed");
4265         return QTransform();
4266     }
4267     if (other == this) {
4268         if (ok)
4269             *ok = true;
4270         return QTransform();
4271     }
4272 
4273     QGraphicsItem *parent = d_ptr->parent;
4274     const QGraphicsItem *otherParent = other->d_ptr->parent;
4275 
4276     // This is other's child
4277     if (parent == other) {
4278         if (ok)
4279             *ok = true;
4280         QTransform x;
4281         d_ptr->combineTransformFromParent(&x);
4282         return x;
4283     }
4284 
4285     // This is other's parent
4286     if (otherParent == this) {
4287         const QPointF &otherPos = other->d_ptr->pos;
4288         if (other->d_ptr->transformData) {
4289             QTransform otherToParent;
4290             other->d_ptr->combineTransformFromParent(&otherToParent);
4291             return otherToParent.inverted(ok);
4292         }
4293         if (ok)
4294             *ok = true;
4295         return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
4296     }
4297 
4298     // Siblings
4299     if (parent == otherParent) {
4300         // COMBINE
4301         const QPointF &itemPos = d_ptr->pos;
4302         const QPointF &otherPos = other->d_ptr->pos;
4303         if (!d_ptr->transformData && !other->d_ptr->transformData) {
4304             QPointF delta = itemPos - otherPos;
4305             if (ok)
4306                 *ok = true;
4307             return QTransform::fromTranslate(delta.x(), delta.y());
4308         }
4309 
4310         QTransform itemToParent;
4311         d_ptr->combineTransformFromParent(&itemToParent);
4312         QTransform otherToParent;
4313         other->d_ptr->combineTransformFromParent(&otherToParent);
4314         return itemToParent * otherToParent.inverted(ok);
4315     }
4316 
4317     // Find the closest common ancestor. If the two items don't share an
4318     // ancestor, then the only way is to combine their scene transforms.
4319     const QGraphicsItem *commonAncestor = commonAncestorItem(other);
4320     if (!commonAncestor) {
4321         d_ptr->ensureSceneTransform();
4322         other->d_ptr->ensureSceneTransform();
4323         return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok);
4324     }
4325 
4326     // If the two items are cousins (in sibling branches), map both to the
4327     // common ancestor, and combine the two transforms.
4328     bool cousins = other != commonAncestor && this != commonAncestor;
4329     if (cousins) {
4330         bool good = false;
4331         QTransform thisToScene = itemTransform(commonAncestor, &good);
4332         QTransform otherToScene(Qt::Uninitialized);
4333         if (good)
4334             otherToScene = other->itemTransform(commonAncestor, &good);
4335         if (!good) {
4336             if (ok)
4337                 *ok = false;
4338             return QTransform();
4339         }
4340         return thisToScene * otherToScene.inverted(ok);
4341     }
4342 
4343     // One is an ancestor of the other; walk the chain.
4344     bool parentOfOther = isAncestorOf(other);
4345     const QGraphicsItem *child = parentOfOther ? other : this;
4346     const QGraphicsItem *root = parentOfOther ? this : other;
4347 
4348     QTransform x;
4349     const QGraphicsItem *p = child;
4350     do {
4351         p->d_ptr.data()->combineTransformToParent(&x);
4352     } while ((p = p->d_ptr->parent) && p != root);
4353     if (parentOfOther)
4354         return x.inverted(ok);
4355     if (ok)
4356         *ok = true;
4357     return x;
4358 }
4359 
4360 /*!
4361     \obsolete
4362 
4363     Sets the item's affine transformation matrix. This is a subset or the
4364     item's full transformation matrix, and might not represent the item's full
4365     transformation.
4366 
4367     Use setTransform() instead.
4368 
4369     \sa transform(), {The Graphics View Coordinate System}
4370 */
setMatrix(const QMatrix & matrix,bool combine)4371 void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
4372 {
4373     if (!d_ptr->transformData)
4374         d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
4375 
4376     QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix));
4377     if (d_ptr->transformData->transform == newTransform)
4378         return;
4379 
4380     // Update and set the new transformation.
4381     if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
4382         d_ptr->setTransformHelper(newTransform);
4383         return;
4384     }
4385 
4386     // Notify the item that the transformation matrix is changing.
4387     const QVariant newMatrixVariant = QVariant::fromValue<QMatrix>(newTransform.toAffine());
4388     newTransform = QTransform(qvariant_cast<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant)));
4389     if (d_ptr->transformData->transform == newTransform)
4390         return;
4391 
4392     // Update and set the new transformation.
4393     d_ptr->setTransformHelper(newTransform);
4394 
4395     // Send post-notification.
4396     itemChange(ItemTransformHasChanged, QVariant::fromValue<QTransform>(newTransform));
4397 }
4398 
4399 /*!
4400     \since 4.3
4401 
4402     Sets the item's current transformation matrix to \a matrix.
4403 
4404     If \a combine is true, then \a matrix is combined with the current matrix;
4405     otherwise, \a matrix \e replaces the current matrix. \a combine is false
4406     by default.
4407 
4408     To simplify interation with items using a transformed view, QGraphicsItem
4409     provides mapTo... and mapFrom... functions that can translate between
4410     items' and the scene's coordinates. For example, you can call mapToScene()
4411     to map an item coordiate to a scene coordinate, or mapFromScene() to map
4412     from scene coordinates to item coordinates.
4413 
4414     The transformation matrix is combined with the item's rotation(), scale()
4415     and transformations() into a combined transformation that maps the item's
4416     coordinate system to its parent.
4417 
4418     \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations}
4419 */
setTransform(const QTransform & matrix,bool combine)4420 void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
4421 {
4422     if (!d_ptr->transformData)
4423         d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
4424 
4425     QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix);
4426     if (d_ptr->transformData->transform == newTransform)
4427         return;
4428 
4429     // Update and set the new transformation.
4430     if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) {
4431         d_ptr->setTransformHelper(newTransform);
4432         if (d_ptr->scenePosDescendants)
4433             d_ptr->sendScenePosChange();
4434         return;
4435     }
4436 
4437     // Notify the item that the transformation matrix is changing.
4438     const QVariant newTransformVariant(itemChange(ItemTransformChange,
4439                                                   QVariant::fromValue<QTransform>(newTransform)));
4440     newTransform = qvariant_cast<QTransform>(newTransformVariant);
4441     if (d_ptr->transformData->transform == newTransform)
4442         return;
4443 
4444     // Update and set the new transformation.
4445     d_ptr->setTransformHelper(newTransform);
4446 
4447     // Send post-notification.
4448     itemChange(ItemTransformHasChanged, newTransformVariant);
4449     d_ptr->sendScenePosChange();
4450 }
4451 
4452 /*!
4453     \obsolete
4454 
4455     Use resetTransform() instead.
4456 */
resetMatrix()4457 void QGraphicsItem::resetMatrix()
4458 {
4459     resetTransform();
4460 }
4461 
4462 /*!
4463     \since 4.3
4464 
4465     Resets this item's transformation matrix to the identity matrix or
4466     all the transformation properties to their default values.
4467     This is equivalent to calling \c setTransform(QTransform()).
4468 
4469     \sa setTransform(), transform()
4470 */
resetTransform()4471 void QGraphicsItem::resetTransform()
4472 {
4473     setTransform(QTransform(), false);
4474 }
4475 
4476 /*!
4477     \obsolete
4478 
4479     Use
4480 
4481     \code
4482     setRotation(rotation() + angle);
4483     \endcode
4484 
4485     instead.
4486 
4487     Rotates the current item transformation \a angle degrees clockwise around
4488     its origin. To translate around an arbitrary point (x, y), you need to
4489     combine translation and rotation with setTransform().
4490 
4491     Example:
4492 
4493     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 6
4494 
4495     \sa setTransform(), transform(), scale(), shear(), translate()
4496 */
rotate(qreal angle)4497 void QGraphicsItem::rotate(qreal angle)
4498 {
4499     setTransform(QTransform().rotate(angle), true);
4500 }
4501 
4502 /*!
4503     \obsolete
4504 
4505     Use
4506 
4507     \code
4508     setTransform(QTransform::fromScale(sx, sy), true);
4509     \endcode
4510 
4511     instead.
4512 
4513     Scales the current item transformation by (\a sx, \a sy) around its
4514     origin. To scale from an arbitrary point (x, y), you need to combine
4515     translation and scaling with setTransform().
4516 
4517     Example:
4518 
4519     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7
4520 
4521     \sa setTransform(), transform()
4522 */
scale(qreal sx,qreal sy)4523 void QGraphicsItem::scale(qreal sx, qreal sy)
4524 {
4525     setTransform(QTransform::fromScale(sx, sy), true);
4526 }
4527 
4528 /*!
4529     \obsolete
4530 
4531     Use
4532 
4533     \code
4534     setTransform(QTransform().shear(sh, sv), true);
4535     \endcode
4536 
4537     instead.
4538 
4539     Shears the current item transformation by (\a sh, \a sv).
4540 
4541     \sa setTransform(), transform()
4542 */
shear(qreal sh,qreal sv)4543 void QGraphicsItem::shear(qreal sh, qreal sv)
4544 {
4545     setTransform(QTransform().shear(sh, sv), true);
4546 }
4547 
4548 /*!
4549     \obsolete
4550 
4551     Use setPos() or setTransformOriginPoint() instead. For identical
4552     behavior, use
4553 
4554     \code
4555     setTransform(QTransform::fromTranslate(dx, dy), true);
4556     \endcode
4557 
4558     Translates the current item transformation by (\a dx, \a dy).
4559 
4560     If all you want is to move an item, you should call moveBy() or
4561     setPos() instead; this function changes the item's translation,
4562     which is conceptually separate from its position.
4563 
4564     \sa setTransform(), transform()
4565 */
translate(qreal dx,qreal dy)4566 void QGraphicsItem::translate(qreal dx, qreal dy)
4567 {
4568     setTransform(QTransform::fromTranslate(dx, dy), true);
4569 }
4570 
4571 /*!
4572     This virtual function is called twice for all items by the
4573     QGraphicsScene::advance() slot. In the first phase, all items are called
4574     with \a phase == 0, indicating that items on the scene are about to
4575     advance, and then all items are called with \a phase == 1. Reimplement
4576     this function to update your item if you need simple scene-controlled
4577     animation.
4578 
4579     The default implementation does nothing.
4580 
4581     For individual item animation, an alternative to this function is to
4582     either use QGraphicsItemAnimation, or to multiple-inherit from QObject and
4583     QGraphicsItem, and animate your item using QObject::startTimer() and
4584     QObject::timerEvent().
4585 
4586     \sa QGraphicsItemAnimation, QTimeLine
4587 */
advance(int phase)4588 void QGraphicsItem::advance(int phase)
4589 {
4590     Q_UNUSED(phase);
4591 }
4592 
4593 /*!
4594     Returns the Z-value of the item. The Z-value affects the stacking order of
4595     sibling (neighboring) items.
4596 
4597     The default Z-value is 0.
4598 
4599     \sa setZValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent
4600 */
zValue() const4601 qreal QGraphicsItem::zValue() const
4602 {
4603     return d_ptr->z;
4604 }
4605 
4606 /*!
4607     Sets the Z-value of the item to \a z. The Z value decides the stacking
4608     order of sibling (neighboring) items. A sibling item of high Z value will
4609     always be drawn on top of another sibling item with a lower Z value.
4610 
4611     If you restore the Z value, the item's insertion order will decide its
4612     stacking order.
4613 
4614     The Z-value does not affect the item's size in any way.
4615 
4616     The default Z-value is 0.
4617 
4618     \sa zValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent
4619 */
setZValue(qreal z)4620 void QGraphicsItem::setZValue(qreal z)
4621 {
4622     const QVariant newZVariant(itemChange(ItemZValueChange, z));
4623     qreal newZ = newZVariant.toReal();
4624     if (newZ == d_ptr->z)
4625         return;
4626 
4627     if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) {
4628         // Z Value has changed, we have to notify the index.
4629         d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, &newZ);
4630     }
4631 
4632     d_ptr->z = newZ;
4633     if (d_ptr->parent)
4634         d_ptr->parent->d_ptr->needSortChildren = 1;
4635     else if (d_ptr->scene)
4636         d_ptr->scene->d_func()->needSortTopLevelItems = 1;
4637 
4638     if (d_ptr->scene)
4639         d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
4640 
4641     itemChange(ItemZValueHasChanged, newZVariant);
4642 
4643     if (d_ptr->flags & ItemNegativeZStacksBehindParent)
4644         setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0));
4645 
4646     if (d_ptr->isObject)
4647         emit static_cast<QGraphicsObject *>(this)->zChanged();
4648 }
4649 
4650 /*!
4651     \internal
4652 
4653     Ensures that the list of children is sorted by insertion order, and that
4654     the siblingIndexes are packed (no gaps), and start at 0.
4655 
4656     ### This function is almost identical to
4657     QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes().
4658 */
ensureSequentialSiblingIndex()4659 void QGraphicsItemPrivate::ensureSequentialSiblingIndex()
4660 {
4661     if (!sequentialOrdering) {
4662         qSort(children.begin(), children.end(), insertionOrder);
4663         sequentialOrdering = 1;
4664         needSortChildren = 1;
4665     }
4666     if (holesInSiblingIndex) {
4667         holesInSiblingIndex = 0;
4668         for (int i = 0; i < children.size(); ++i)
4669             children[i]->d_ptr->siblingIndex = i;
4670     }
4671 }
4672 
4673 /*!
4674     \internal
4675 */
sendScenePosChange()4676 inline void QGraphicsItemPrivate::sendScenePosChange()
4677 {
4678     Q_Q(QGraphicsItem);
4679     if (scene) {
4680         if (flags & QGraphicsItem::ItemSendsScenePositionChanges)
4681             q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos());
4682         if (scenePosDescendants) {
4683             foreach (QGraphicsItem *item, scene->d_func()->scenePosItems) {
4684                 if (q->isAncestorOf(item))
4685                     item->itemChange(QGraphicsItem::ItemScenePositionHasChanged, item->scenePos());
4686             }
4687         }
4688     }
4689 }
4690 
4691 /*!
4692     \since 4.6
4693 
4694     Stacks this item before \a sibling, which must be a sibling item (i.e., the
4695     two items must share the same parent item, or must both be toplevel items).
4696     The \a sibling must have the same Z value as this item, otherwise calling
4697     this function will have no effect.
4698 
4699     By default, all sibling items are stacked by insertion order (i.e., the
4700     first item you add is drawn before the next item you add). If two items' Z
4701     values are different, then the item with the highest Z value is drawn on
4702     top. When the Z values are the same, the insertion order will decide the
4703     stacking order.
4704 
4705     \sa setZValue(), ItemStacksBehindParent, {QGraphicsItem#Sorting}{Sorting}
4706 */
stackBefore(const QGraphicsItem * sibling)4707 void QGraphicsItem::stackBefore(const QGraphicsItem *sibling)
4708 {
4709     if (sibling == this)
4710         return;
4711     if (!sibling || d_ptr->parent != sibling->parentItem()) {
4712         qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
4713         return;
4714     }
4715     QList<QGraphicsItem *> *siblings = d_ptr->parent
4716                                        ? &d_ptr->parent->d_ptr->children
4717                                        : (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : 0);
4718     if (!siblings) {
4719         qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
4720         return;
4721     }
4722 
4723     // First, make sure that the sibling indexes have no holes. This also
4724     // marks the children list for sorting.
4725     if (d_ptr->parent)
4726         d_ptr->parent->d_ptr->ensureSequentialSiblingIndex();
4727     else
4728         d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes();
4729 
4730     // Only move items with the same Z value, and that need moving.
4731     int siblingIndex = sibling->d_ptr->siblingIndex;
4732     int myIndex = d_ptr->siblingIndex;
4733     if (myIndex >= siblingIndex) {
4734         siblings->move(myIndex, siblingIndex);
4735         // Fixup the insertion ordering.
4736         for (int i = 0; i < siblings->size(); ++i) {
4737             int &index = siblings->at(i)->d_ptr->siblingIndex;
4738             if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
4739                 ++index;
4740         }
4741         d_ptr->siblingIndex = siblingIndex;
4742         for (int i = 0; i < siblings->size(); ++i) {
4743             int &index = siblings->at(i)->d_ptr->siblingIndex;
4744             if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
4745                 siblings->at(i)->d_ptr->siblingOrderChange();
4746         }
4747         d_ptr->siblingOrderChange();
4748     }
4749 }
4750 
4751 /*!
4752     Returns the bounding rect of this item's descendants (i.e., its
4753     children, their children, etc.) in local coordinates. The
4754     rectangle will contain all descendants after they have been mapped
4755     to local coordinates. If the item has no children, this function
4756     returns an empty QRectF.
4757 
4758     This does not include this item's own bounding rect; it only returns
4759     its descendants' accumulated bounding rect. If you need to include this
4760     item's bounding rect, you can add boundingRect() to childrenBoundingRect()
4761     using QRectF::operator|().
4762 
4763     This function is linear in complexity; it determines the size of the
4764     returned bounding rect by iterating through all descendants.
4765 
4766     \sa boundingRect(), sceneBoundingRect()
4767 */
childrenBoundingRect() const4768 QRectF QGraphicsItem::childrenBoundingRect() const
4769 {
4770     if (!d_ptr->dirtyChildrenBoundingRect)
4771         return d_ptr->childrenBoundingRect;
4772 
4773     d_ptr->childrenBoundingRect = QRectF();
4774     d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect, 0);
4775     d_ptr->dirtyChildrenBoundingRect = 0;
4776     return d_ptr->childrenBoundingRect;
4777 }
4778 
4779 /*!
4780     \fn virtual QRectF QGraphicsItem::boundingRect() const = 0
4781 
4782     This pure virtual function defines the outer bounds of the item as
4783     a rectangle; all painting must be restricted to inside an item's
4784     bounding rect. QGraphicsView uses this to determine whether the
4785     item requires redrawing.
4786 
4787     Although the item's shape can be arbitrary, the bounding rect is
4788     always rectangular, and it is unaffected by the items'
4789     transformation.
4790 
4791     If you want to change the item's bounding rectangle, you must first call
4792     prepareGeometryChange(). This notifies the scene of the imminent change,
4793     so that its can update its item geometry index; otherwise, the scene will
4794     be unaware of the item's new geometry, and the results are undefined
4795     (typically, rendering artifacts are left around in the view).
4796 
4797     Reimplement this function to let QGraphicsView determine what
4798     parts of the widget, if any, need to be redrawn.
4799 
4800     Note: For shapes that paint an outline / stroke, it is important
4801     to include half the pen width in the bounding rect. It is not
4802     necessary to compensate for antialiasing, though.
4803 
4804     Example:
4805 
4806     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 8
4807 
4808     \sa boundingRegion(), shape(), contains(), {The Graphics View Coordinate
4809     System}, prepareGeometryChange()
4810 */
4811 
4812 /*!
4813     Returns the bounding rect of this item in scene coordinates, by combining
4814     sceneTransform() with boundingRect().
4815 
4816     \sa boundingRect(), {The Graphics View Coordinate System}
4817 */
sceneBoundingRect() const4818 QRectF QGraphicsItem::sceneBoundingRect() const
4819 {
4820     // Find translate-only offset
4821     // COMBINE
4822     QPointF offset;
4823     const QGraphicsItem *parentItem = this;
4824     const QGraphicsItemPrivate *itemd;
4825     do {
4826         itemd = parentItem->d_ptr.data();
4827         if (itemd->transformData)
4828             break;
4829         offset += itemd->pos;
4830     } while ((parentItem = itemd->parent));
4831 
4832     QRectF br = boundingRect();
4833     br.translate(offset);
4834     if (!parentItem)
4835         return br;
4836     if (parentItem->d_ptr->hasTranslateOnlySceneTransform()) {
4837         br.translate(parentItem->d_ptr->sceneTransform.dx(), parentItem->d_ptr->sceneTransform.dy());
4838         return br;
4839     }
4840     return parentItem->d_ptr->sceneTransform.mapRect(br);
4841 }
4842 
4843 /*!
4844     Returns the shape of this item as a QPainterPath in local
4845     coordinates. The shape is used for many things, including collision
4846     detection, hit tests, and for the QGraphicsScene::items() functions.
4847 
4848     The default implementation calls boundingRect() to return a simple
4849     rectangular shape, but subclasses can reimplement this function to return
4850     a more accurate shape for non-rectangular items. For example, a round item
4851     may choose to return an elliptic shape for better collision detection. For
4852     example:
4853 
4854     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 9
4855 
4856     The outline of a shape can vary depending on the width and style of the
4857     pen used when drawing. If you want to include this outline in the item's
4858     shape, you can create a shape from the stroke using QPainterPathStroker.
4859 
4860     This function is called by the default implementations of contains() and
4861     collidesWithPath().
4862 
4863     \sa boundingRect(), contains(), prepareGeometryChange(), QPainterPathStroker
4864 */
shape() const4865 QPainterPath QGraphicsItem::shape() const
4866 {
4867     QPainterPath path;
4868     path.addRect(boundingRect());
4869     return path;
4870 }
4871 
4872 /*!
4873     Returns true if this item is clipped. An item is clipped if it has either
4874     set the \l ItemClipsToShape flag, or if it or any of its ancestors has set
4875     the \l ItemClipsChildrenToShape flag.
4876 
4877     Clipping affects the item's appearance (i.e., painting), as well as mouse
4878     and hover event delivery.
4879 
4880     \sa clipPath(), shape(), setFlags()
4881 */
isClipped() const4882 bool QGraphicsItem::isClipped() const
4883 {
4884     Q_D(const QGraphicsItem);
4885     return (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
4886         || (d->flags & QGraphicsItem::ItemClipsToShape);
4887 }
4888 
4889 /*!
4890     \since 4.5
4891 
4892     Returns this item's clip path, or an empty QPainterPath if this item is
4893     not clipped. The clip path constrains the item's appearance and
4894     interaction (i.e., restricts the area the item can draw, and it also
4895     restricts the area that the item receives events).
4896 
4897     You can enable clipping by setting the ItemClipsToShape or
4898     ItemClipsChildrenToShape flags. The item's clip path is calculated by
4899     intersecting all clipping ancestors' shapes. If the item sets
4900     ItemClipsToShape, the final clip is intersected with the item's own shape.
4901 
4902     \note Clipping introduces a performance penalty for all items involved;
4903     you should generally avoid using clipping if you can (e.g., if your items
4904     always draw inside boundingRect() or shape() boundaries, clipping is not
4905     necessary).
4906 
4907     \sa isClipped(), shape(), setFlags()
4908 */
clipPath() const4909 QPainterPath QGraphicsItem::clipPath() const
4910 {
4911     Q_D(const QGraphicsItem);
4912     if (!isClipped())
4913         return QPainterPath();
4914 
4915     const QRectF thisBoundingRect(boundingRect());
4916     if (thisBoundingRect.isEmpty())
4917         return QPainterPath();
4918 
4919     QPainterPath clip;
4920     // Start with the item's bounding rect.
4921     clip.addRect(thisBoundingRect);
4922 
4923     if (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
4924         const QGraphicsItem *parent = this;
4925         const QGraphicsItem *lastParent = this;
4926 
4927         // Intersect any in-between clips starting at the top and moving downwards.
4928         while ((parent = parent->d_ptr->parent)) {
4929             if (parent->d_ptr->flags & ItemClipsChildrenToShape) {
4930                 // Map clip to the current parent and intersect with its shape/clipPath
4931                 clip = lastParent->itemTransform(parent).map(clip);
4932                 clip = clip.intersected(parent->shape());
4933                 if (clip.isEmpty())
4934                     return clip;
4935                 lastParent = parent;
4936             }
4937 
4938             if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
4939                 break;
4940         }
4941 
4942         if (lastParent != this) {
4943             // Map clip back to the item's transform.
4944             // ### what if itemtransform fails
4945             clip = lastParent->itemTransform(this).map(clip);
4946         }
4947     }
4948 
4949     if (d->flags & ItemClipsToShape)
4950         clip = clip.intersected(shape());
4951 
4952     return clip;
4953 }
4954 
4955 /*!
4956     Returns true if this item contains \a point, which is in local
4957     coordinates; otherwise, false is returned. It is most often called from
4958     QGraphicsView to determine what item is under the cursor, and for that
4959     reason, the implementation of this function should be as light-weight as
4960     possible.
4961 
4962     By default, this function calls shape(), but you can reimplement it in a
4963     subclass to provide a (perhaps more efficient) implementation.
4964 
4965     \sa shape(), boundingRect(), collidesWithPath()
4966 */
contains(const QPointF & point) const4967 bool QGraphicsItem::contains(const QPointF &point) const
4968 {
4969     return isClipped() ? clipPath().contains(point) : shape().contains(point);
4970 }
4971 
4972 /*!
4973 
4974     Returns true if this item collides with \a other; otherwise
4975     returns false.
4976 
4977     The \a mode is applied to \a other, and the resulting shape or
4978     bounding rectangle is then compared to this item's shape. The
4979     default value for \a mode is Qt::IntersectsItemShape; \a other
4980     collides with this item if it either intersects, contains, or is
4981     contained by this item's shape (see Qt::ItemSelectionMode for
4982     details).
4983 
4984     The default implementation is based on shape intersection, and it calls
4985     shape() on both items. Because the complexity of arbitrary shape-shape
4986     intersection grows with an order of magnitude when the shapes are complex,
4987     this operation can be noticably time consuming. You have the option of
4988     reimplementing this function in a subclass of QGraphicsItem to provide a
4989     custom algorithm. This allows you to make use of natural constraints in
4990     the shapes of your own items, in order to improve the performance of the
4991     collision detection. For instance, two untransformed perfectly circular
4992     items' collision can be determined very efficiently by comparing their
4993     positions and radii.
4994 
4995     Keep in mind that when reimplementing this function and calling shape() or
4996     boundingRect() on \a other, the returned coordinates must be mapped to
4997     this item's coordinate system before any intersection can take place.
4998 
4999     \sa contains(), shape()
5000 */
collidesWithItem(const QGraphicsItem * other,Qt::ItemSelectionMode mode) const5001 bool QGraphicsItem::collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode) const
5002 {
5003     if (other == this)
5004         return true;
5005     if (!other)
5006         return false;
5007     // The items share the same clip if their closest clipper is the same, or
5008     // if one clips the other.
5009     bool clips = (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren);
5010     bool otherClips = (other->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren);
5011     if (clips || otherClips) {
5012         const QGraphicsItem *closestClipper = isAncestorOf(other) ? this : parentItem();
5013         while (closestClipper && !(closestClipper->flags() & ItemClipsChildrenToShape))
5014             closestClipper = closestClipper->parentItem();
5015         const QGraphicsItem *otherClosestClipper = other->isAncestorOf(this) ? other : other->parentItem();
5016         while (otherClosestClipper && !(otherClosestClipper->flags() & ItemClipsChildrenToShape))
5017             otherClosestClipper = otherClosestClipper->parentItem();
5018         if (closestClipper == otherClosestClipper) {
5019             d_ptr->localCollisionHack = 1;
5020             bool res = collidesWithPath(mapFromItem(other, other->shape()), mode);
5021             d_ptr->localCollisionHack = 0;
5022             return res;
5023         }
5024     }
5025 
5026     QPainterPath otherShape = other->isClipped() ? other->clipPath() : other->shape();
5027     return collidesWithPath(mapFromItem(other, otherShape), mode);
5028 }
5029 
5030 /*!
5031     Returns true if this item collides with \a path.
5032 
5033     The collision is determined by \a mode. The default value for \a mode is
5034     Qt::IntersectsItemShape; \a path collides with this item if it either
5035     intersects, contains, or is contained by this item's shape.
5036 
5037     Note that this function checks whether the item's shape or
5038     bounding rectangle (depending on \a mode) is contained within \a
5039     path, and not whether \a path is contained within the items shape
5040     or bounding rectangle.
5041 
5042     \sa collidesWithItem(), contains(), shape()
5043 */
collidesWithPath(const QPainterPath & path,Qt::ItemSelectionMode mode) const5044 bool QGraphicsItem::collidesWithPath(const QPainterPath &path, Qt::ItemSelectionMode mode) const
5045 {
5046     if (path.isEmpty()) {
5047         // No collision with empty paths.
5048         return false;
5049     }
5050 
5051     QRectF rectA(boundingRect());
5052     _q_adjustRect(&rectA);
5053     QRectF rectB(path.controlPointRect());
5054     _q_adjustRect(&rectB);
5055     if (!rectA.intersects(rectB)) {
5056         // This we can determine efficiently. If the two rects neither
5057         // intersect nor contain eachother, then the two items do not collide.
5058         return false;
5059     }
5060 
5061     // For further testing, we need this item's shape or bounding rect.
5062     QPainterPath thisShape;
5063     if (mode == Qt::IntersectsItemShape || mode == Qt::ContainsItemShape)
5064         thisShape = (isClipped() && !d_ptr->localCollisionHack) ? clipPath() : shape();
5065     else
5066         thisShape.addRect(rectA);
5067 
5068     if (thisShape == QPainterPath()) {
5069         // Empty shape? No collision.
5070         return false;
5071     }
5072 
5073     // Use QPainterPath boolean operations to determine the collision, O(N*logN).
5074     if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
5075         return path.intersects(thisShape);
5076     return path.contains(thisShape);
5077 }
5078 
5079 /*!
5080     Returns a list of all items that collide with this item.
5081 
5082     The way collisions are detected is determined by applying \a mode
5083     to items that are compared to this item, i.e., each item's shape
5084     or bounding rectangle is checked against this item's shape. The
5085     default value for \a mode is Qt::IntersectsItemShape.
5086 
5087     \sa collidesWithItem()
5088 */
collidingItems(Qt::ItemSelectionMode mode) const5089 QList<QGraphicsItem *> QGraphicsItem::collidingItems(Qt::ItemSelectionMode mode) const
5090 {
5091     if (d_ptr->scene)
5092         return d_ptr->scene->collidingItems(this, mode);
5093     return QList<QGraphicsItem *>();
5094 }
5095 
5096 /*!
5097     Returns true if this item's bounding rect is completely obscured by the
5098     opaque shape of any of colliding items above it (i.e., with a higher Z
5099     value than this item).
5100 
5101     Its implementation is based on calling isObscuredBy(), which you can
5102     reimplement to provide a custom obscurity algorithm.
5103 
5104   \sa opaqueArea()
5105 */
isObscured() const5106 bool QGraphicsItem::isObscured() const
5107 {
5108     return isObscured(QRectF());
5109 }
5110 
5111 /*!
5112     \internal
5113 
5114     Item obscurity helper function.
5115 
5116     Returns true if the subrect \a rect of \a item's bounding rect is obscured
5117     by \a other (i.e., \a other's opaque area covers \a item's \a rect
5118     completely. \a other is assumed to already be "on top of" \a item
5119     wrt. stacking order.
5120 */
qt_QGraphicsItem_isObscured(const QGraphicsItem * item,const QGraphicsItem * other,const QRectF & rect)5121 static bool qt_QGraphicsItem_isObscured(const QGraphicsItem *item,
5122                                         const QGraphicsItem *other,
5123                                         const QRectF &rect)
5124 {
5125     return other->mapToItem(item, other->opaqueArea()).contains(rect);
5126 }
5127 
5128 /*!
5129     \overload
5130     \since 4.3
5131 
5132     Returns true if \a rect is completely obscured by the opaque shape of any
5133     of colliding items above it (i.e., with a higher Z value than this item).
5134 
5135     Unlike the default isObscured() function, this function does not call
5136     isObscuredBy().
5137 
5138     \sa opaqueArea()
5139 */
isObscured(const QRectF & rect) const5140 bool QGraphicsItem::isObscured(const QRectF &rect) const
5141 {
5142     Q_D(const QGraphicsItem);
5143     if (!d->scene)
5144         return false;
5145 
5146     QRectF br = boundingRect();
5147     QRectF testRect = rect.isNull() ? br : rect;
5148 
5149     foreach (QGraphicsItem *item, d->scene->items(mapToScene(br), Qt::IntersectsItemBoundingRect)) {
5150         if (item == this)
5151             break;
5152         if (qt_QGraphicsItem_isObscured(this, item, testRect))
5153             return true;
5154     }
5155     return false;
5156 }
5157 
5158 /*!
5159     \fn bool QGraphicsItem::isObscured(qreal x, qreal y, qreal w, qreal h) const
5160     \since 4.3
5161 
5162     This convenience function is equivalent to calling isObscured(QRectF(\a x, \a y, \a w, \a h)).
5163 */
5164 
5165 /*!
5166     Returns true if this item's bounding rect is completely obscured by the
5167     opaque shape of \a item.
5168 
5169     The base implementation maps \a item's opaqueArea() to this item's
5170     coordinate system, and then checks if this item's boundingRect() is fully
5171     contained within the mapped shape.
5172 
5173     You can reimplement this function to provide a custom algorithm for
5174     determining whether this item is obscured by \a item.
5175 
5176     \sa opaqueArea(), isObscured()
5177 */
isObscuredBy(const QGraphicsItem * item) const5178 bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const
5179 {
5180     if (!item)
5181         return false;
5182     return qt_closestItemFirst(item, this)
5183         && qt_QGraphicsItem_isObscured(this, item, boundingRect());
5184 }
5185 
5186 /*!
5187     This virtual function returns a shape representing the area where this
5188     item is opaque. An area is opaque if it is filled using an opaque brush or
5189     color (i.e., not transparent).
5190 
5191     This function is used by isObscuredBy(), which is called by underlying
5192     items to determine if they are obscured by this item.
5193 
5194     The default implementation returns an empty QPainterPath, indicating that
5195     this item is completely transparent and does not obscure any other items.
5196 
5197     \sa isObscuredBy(), isObscured(), shape()
5198 */
opaqueArea() const5199 QPainterPath QGraphicsItem::opaqueArea() const
5200 {
5201     return QPainterPath();
5202 }
5203 
5204 /*!
5205     \since 4.4
5206 
5207     Returns the bounding region for this item. The coordinate space of the
5208     returned region depends on \a itemToDeviceTransform. If you pass an
5209     identity QTransform as a parameter, this function will return a local
5210     coordinate region.
5211 
5212     The bounding region describes a coarse outline of the item's visual
5213     contents. Although it's expensive to calculate, it's also more precise
5214     than boundingRect(), and it can help to avoid unnecessary repainting when
5215     an item is updated. This is particularly efficient for thin items (e.g.,
5216     lines or simple polygons). You can tune the granularity for the bounding
5217     region by calling setBoundingRegionGranularity(). The default granularity
5218     is 0; in which the item's bounding region is the same as its bounding
5219     rect.
5220 
5221     \a itemToDeviceTransform is the transformation from item coordinates to
5222     device coordinates. If you want this function to return a QRegion in scene
5223     coordinates, you can pass sceneTransform() as an argument.
5224 
5225     \sa boundingRegionGranularity()
5226 */
boundingRegion(const QTransform & itemToDeviceTransform) const5227 QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) const
5228 {
5229     // ### Ideally we would have a better way to generate this region,
5230     // preferably something in the lines of QPainterPath::toRegion(QTransform)
5231     // coupled with a way to generate a painter path from a set of painter
5232     // operations (e.g., QPicture::toPainterPath() or so). The current
5233     // approach generates a bitmap with the size of the item's bounding rect
5234     // in device coordinates, scaled by b.r.granularity, then paints the item
5235     // into the bitmap, converts the result to a QRegion and scales the region
5236     // back to device space with inverse granularity.
5237     qreal granularity = boundingRegionGranularity();
5238     QRect deviceRect = itemToDeviceTransform.mapRect(boundingRect()).toRect();
5239     _q_adjustRect(&deviceRect);
5240     if (granularity == 0.0)
5241         return QRegion(deviceRect);
5242 
5243     int pad = 1;
5244     QSize bitmapSize(qMax(1, int(deviceRect.width() * granularity) + pad * 2),
5245                      qMax(1, int(deviceRect.height() * granularity) + pad * 2));
5246     QImage mask(bitmapSize, QImage::Format_ARGB32_Premultiplied);
5247     mask.fill(0);
5248     QPainter p(&mask);
5249     p.setRenderHints(QPainter::Antialiasing);
5250 
5251     // Transform painter (### this code is from QGraphicsScene::drawItemHelper
5252     // and doesn't work properly with perspective transformations).
5253     QPointF viewOrigo = itemToDeviceTransform.map(QPointF(0,  0));
5254     QPointF offset = viewOrigo - deviceRect.topLeft();
5255     p.scale(granularity, granularity);
5256     p.translate(offset);
5257     p.translate(pad, pad);
5258     p.setWorldTransform(itemToDeviceTransform, true);
5259     p.translate(itemToDeviceTransform.inverted().map(QPointF(0, 0)));
5260 
5261     // Render
5262     QStyleOptionGraphicsItem option;
5263     const_cast<QGraphicsItem *>(this)->paint(&p, &option, 0);
5264     p.end();
5265 
5266     // Transform QRegion back to device space
5267     QTransform unscale = QTransform::fromScale(1 / granularity, 1 / granularity);
5268     QRegion r;
5269     QBitmap colorMask = QBitmap::fromImage(mask.createMaskFromColor(0));
5270     foreach (const QRect &rect, QRegion( colorMask ).rects()) {
5271         QRect xrect = unscale.mapRect(rect).translated(deviceRect.topLeft() - QPoint(pad, pad));
5272         r += xrect.adjusted(-1, -1, 1, 1) & deviceRect;
5273     }
5274     return r;
5275 }
5276 
5277 /*!
5278     \since 4.4
5279 
5280     Returns the item's bounding region granularity; a value between and
5281     including 0 and 1. The default value is 0 (i.e., the lowest granularity,
5282     where the bounding region corresponds to the item's bounding rectangle).
5283 
5284 \omit
5285 ### NOTE
5286 \endomit
5287 
5288     \sa setBoundingRegionGranularity()
5289 */
boundingRegionGranularity() const5290 qreal QGraphicsItem::boundingRegionGranularity() const
5291 {
5292     return d_ptr->hasBoundingRegionGranularity
5293         ? qvariant_cast<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity))
5294         : 0;
5295 }
5296 
5297 /*!
5298     \since 4.4
5299     Sets the bounding region granularity to \a granularity; a value between
5300     and including 0 and 1. The default value is 0 (i.e., the lowest
5301     granularity, where the bounding region corresponds to the item's bounding
5302     rectangle).
5303 
5304     The granularity is used by boundingRegion() to calculate how fine the
5305     bounding region of the item should be. The highest achievable granularity
5306     is 1, where boundingRegion() will return the finest outline possible for
5307     the respective device (e.g., for a QGraphicsView viewport, this gives you
5308     a pixel-perfect bounding region). The lowest possible granularity is
5309     0. The value of \a granularity describes the ratio between device
5310     resolution and the resolution of the bounding region (e.g., a value of
5311     0.25 will provide a region where each chunk corresponds to 4x4 device
5312     units / pixels).
5313 
5314     \sa boundingRegionGranularity()
5315 */
setBoundingRegionGranularity(qreal granularity)5316 void QGraphicsItem::setBoundingRegionGranularity(qreal granularity)
5317 {
5318     if (granularity < 0.0 || granularity > 1.0) {
5319         qWarning("QGraphicsItem::setBoundingRegionGranularity: invalid granularity %g", granularity);
5320         return;
5321     }
5322     if (granularity == 0.0) {
5323         d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity);
5324         d_ptr->hasBoundingRegionGranularity = 0;
5325         return;
5326     }
5327     d_ptr->hasBoundingRegionGranularity = 1;
5328     d_ptr->setExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity,
5329                     QVariant::fromValue<qreal>(granularity));
5330 }
5331 
5332 /*!
5333     \fn virtual void QGraphicsItem::paint(QPainter *painter, const
5334     QStyleOptionGraphicsItem *option, QWidget *widget = 0) = 0
5335 
5336     This function, which is usually called by QGraphicsView, paints the
5337     contents of an item in local coordinates.
5338 
5339     Reimplement this function in a QGraphicsItem subclass to provide the
5340     item's painting implementation, using \a painter. The \a option parameter
5341     provides style options for the item, such as its state, exposed area and
5342     its level-of-detail hints. The \a widget argument is optional. If
5343     provided, it points to the widget that is being painted on; otherwise, it
5344     is 0. For cached painting, \a widget is always 0.
5345 
5346     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 10
5347 
5348     The painter's pen is 0-width by default, and its pen is initialized to the
5349     QPalette::Text brush from the paint device's palette. The brush is
5350     initialized to QPalette::Window.
5351 
5352     Make sure to constrain all painting inside the boundaries of
5353     boundingRect() to avoid rendering artifacts (as QGraphicsView does not
5354     clip the painter for you). In particular, when QPainter renders the
5355     outline of a shape using an assigned QPen, half of the outline will be
5356     drawn outside, and half inside, the shape you're rendering (e.g., with a
5357     pen width of 2 units, you must draw outlines 1 unit inside
5358     boundingRect()). QGraphicsItem does not support use of cosmetic pens with
5359     a non-zero width.
5360 
5361     All painting is done in local coordinates.
5362 
5363     \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption
5364 */
5365 
5366 /*!
5367     \internal
5368     Returns true if we can discard an update request; otherwise false.
5369 */
discardUpdateRequest(bool ignoreVisibleBit,bool ignoreDirtyBit,bool ignoreOpacity) const5370 bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreVisibleBit, bool ignoreDirtyBit,
5371                                                 bool ignoreOpacity) const
5372 {
5373     // No scene, or if the scene is updating everything, means we have nothing
5374     // to do. The only exception is if the scene tracks the growing scene rect.
5375     return !scene
5376            || (!visible && !ignoreVisibleBit && !this->ignoreVisible)
5377            || (!ignoreDirtyBit && fullUpdatePending)
5378            || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent());
5379 }
5380 
5381 /*!
5382     \internal
5383 */
depth() const5384 int QGraphicsItemPrivate::depth() const
5385 {
5386     if (itemDepth == -1)
5387         const_cast<QGraphicsItemPrivate *>(this)->resolveDepth();
5388 
5389     return itemDepth;
5390 }
5391 
5392 /*!
5393     \internal
5394 */
5395 #ifndef QT_NO_GRAPHICSEFFECT
invalidateParentGraphicsEffectsRecursively()5396 void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively()
5397 {
5398     QGraphicsItemPrivate *itemPrivate = this;
5399     do {
5400         if (itemPrivate->graphicsEffect && !itemPrivate->updateDueToGraphicsEffect) {
5401             itemPrivate->notifyInvalidated = 1;
5402             static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
5403         }
5404     } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
5405 }
5406 
invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason)5407 void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason)
5408 {
5409     if (!mayHaveChildWithGraphicsEffect)
5410         return;
5411 
5412     for (int i = 0; i < children.size(); ++i) {
5413         QGraphicsItemPrivate *childPrivate = children.at(i)->d_ptr.data();
5414         if (reason == OpacityChanged && (childPrivate->flags & QGraphicsItem::ItemIgnoresParentOpacity))
5415             continue;
5416         if (childPrivate->graphicsEffect) {
5417             childPrivate->notifyInvalidated = 1;
5418             static_cast<QGraphicsItemEffectSourcePrivate *>(childPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
5419         }
5420 
5421         childPrivate->invalidateChildGraphicsEffectsRecursively(reason);
5422     }
5423 }
5424 #endif //QT_NO_GRAPHICSEFFECT
5425 
5426 /*!
5427     \internal
5428 */
invalidateDepthRecursively()5429 void QGraphicsItemPrivate::invalidateDepthRecursively()
5430 {
5431     if (itemDepth == -1)
5432         return;
5433 
5434     itemDepth = -1;
5435     for (int i = 0; i < children.size(); ++i)
5436         children.at(i)->d_ptr->invalidateDepthRecursively();
5437 }
5438 
5439 /*!
5440     \internal
5441 
5442     Resolves the stacking depth of this object and all its ancestors.
5443 */
resolveDepth()5444 void QGraphicsItemPrivate::resolveDepth()
5445 {
5446     if (!parent)
5447         itemDepth = 0;
5448     else {
5449         if (parent->d_ptr->itemDepth == -1)
5450             parent->d_ptr->resolveDepth();
5451         itemDepth = parent->d_ptr->itemDepth + 1;
5452     }
5453 }
5454 
5455 /*!
5456     \internal
5457 
5458     ### This function is almost identical to
5459     QGraphicsScenePrivate::registerTopLevelItem().
5460 */
addChild(QGraphicsItem * child)5461 void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
5462 {
5463     // Remove all holes from the sibling index list. Now the max index
5464     // number is equal to the size of the children list.
5465     ensureSequentialSiblingIndex();
5466     needSortChildren = 1; // ### maybe 0
5467     child->d_ptr->siblingIndex = children.size();
5468     children.append(child);
5469     if (isObject)
5470         emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
5471 }
5472 
5473 /*!
5474     \internal
5475 
5476     ### This function is almost identical to
5477     QGraphicsScenePrivate::unregisterTopLevelItem().
5478 */
removeChild(QGraphicsItem * child)5479 void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
5480 {
5481     // When removing elements in the middle of the children list,
5482     // there will be a "gap" in the list of sibling indexes (0,1,3,4).
5483     if (!holesInSiblingIndex)
5484         holesInSiblingIndex = child->d_ptr->siblingIndex != children.size() - 1;
5485     if (sequentialOrdering && !holesInSiblingIndex)
5486         children.removeAt(child->d_ptr->siblingIndex);
5487     else
5488         children.removeOne(child);
5489     // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because
5490     // the child is not guaranteed to be at the index after the list is sorted.
5491     // (see ensureSortedChildren()).
5492     child->d_ptr->siblingIndex = -1;
5493     if (isObject)
5494         emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
5495 }
5496 
5497 /*!
5498     \internal
5499 */
maybeExtraItemCache() const5500 QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const
5501 {
5502     return (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
5503 }
5504 
5505 /*!
5506     \internal
5507 */
extraItemCache() const5508 QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
5509 {
5510     QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
5511     if (!c) {
5512         QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this);
5513         c = new QGraphicsItemCache;
5514         that->setExtra(ExtraCacheData, QVariant::fromValue<void *>(c));
5515     }
5516     return c;
5517 }
5518 
5519 /*!
5520     \internal
5521 */
removeExtraItemCache()5522 void QGraphicsItemPrivate::removeExtraItemCache()
5523 {
5524     QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
5525     if (c) {
5526         c->purge();
5527         delete c;
5528     }
5529     unsetExtra(ExtraCacheData);
5530 }
5531 
updatePaintedViewBoundingRects(bool updateChildren)5532 void QGraphicsItemPrivate::updatePaintedViewBoundingRects(bool updateChildren)
5533 {
5534     if (!scene)
5535         return;
5536 
5537     for (int i = 0; i < scene->d_func()->views.size(); ++i) {
5538         QGraphicsViewPrivate *viewPrivate = scene->d_func()->views.at(i)->d_func();
5539         QRect rect = paintedViewBoundingRects.value(viewPrivate->viewport);
5540         rect.translate(viewPrivate->dirtyScrollOffset);
5541         viewPrivate->updateRect(rect);
5542     }
5543 
5544     if (updateChildren) {
5545         for (int i = 0; i < children.size(); ++i)
5546             children.at(i)->d_ptr->updatePaintedViewBoundingRects(true);
5547     }
5548 }
5549 
5550 // Traverses all the ancestors up to the top-level and updates the pointer to
5551 // always point to the top-most item that has a dirty scene transform.
5552 // It then backtracks to the top-most dirty item and start calculating the
5553 // scene transform by combining the item's transform (+pos) with the parent's
5554 // cached scene transform (which we at this point know for sure is valid).
ensureSceneTransformRecursive(QGraphicsItem ** topMostDirtyItem)5555 void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem)
5556 {
5557     Q_ASSERT(topMostDirtyItem);
5558 
5559     if (dirtySceneTransform)
5560         *topMostDirtyItem = q_ptr;
5561 
5562     if (parent)
5563         parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem);
5564 
5565     if (*topMostDirtyItem == q_ptr) {
5566         if (!dirtySceneTransform)
5567             return; // OK, neither my ancestors nor I have dirty scene transforms.
5568         *topMostDirtyItem = 0;
5569     } else if (*topMostDirtyItem) {
5570         return; // Continue backtrack.
5571     }
5572 
5573     // This item and all its descendants have dirty scene transforms.
5574     // We're about to validate this item's scene transform, so we have to
5575     // invalidate all the children; otherwise there's no way for the descendants
5576     // to detect that the ancestor has changed.
5577     invalidateChildrenSceneTransform();
5578 
5579     // COMBINE my transform with the parent's scene transform.
5580     updateSceneTransformFromParent();
5581     Q_ASSERT(!dirtySceneTransform);
5582 }
5583 
5584 /*!
5585     \internal
5586 */
setSubFocus(QGraphicsItem * rootItem,QGraphicsItem * stopItem)5587 void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem, QGraphicsItem *stopItem)
5588 {
5589     // Update focus child chain. Stop at panels, or if this item
5590     // is hidden, stop at the first item with a visible parent.
5591     QGraphicsItem *parent = rootItem ? rootItem : q_ptr;
5592     if (parent->panel() != q_ptr->panel())
5593         return;
5594 
5595     do {
5596         // Clear any existing ancestor's subFocusItem.
5597         if (parent != q_ptr && parent->d_ptr->subFocusItem) {
5598             if (parent->d_ptr->subFocusItem == q_ptr)
5599                 break;
5600             parent->d_ptr->subFocusItem->d_ptr->clearSubFocus(0, stopItem);
5601         }
5602         parent->d_ptr->subFocusItem = q_ptr;
5603         parent->d_ptr->subFocusItemChange();
5604     } while (!parent->isPanel() && (parent = parent->d_ptr->parent) && (visible || !parent->d_ptr->visible));
5605 
5606     if (scene && !scene->isActive()) {
5607         scene->d_func()->passiveFocusItem = subFocusItem;
5608         scene->d_func()->lastFocusItem = subFocusItem;
5609     }
5610 }
5611 
5612 /*!
5613     \internal
5614 */
clearSubFocus(QGraphicsItem * rootItem,QGraphicsItem * stopItem)5615 void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem, QGraphicsItem *stopItem)
5616 {
5617     // Reset sub focus chain.
5618     QGraphicsItem *parent = rootItem ? rootItem : q_ptr;
5619     do {
5620         if (parent->d_ptr->subFocusItem != q_ptr)
5621             break;
5622         parent->d_ptr->subFocusItem = 0;
5623         if (parent != stopItem && !parent->isAncestorOf(stopItem))
5624             parent->d_ptr->subFocusItemChange();
5625     } while (!parent->isPanel() && (parent = parent->d_ptr->parent));
5626 }
5627 
5628 /*!
5629     \internal
5630 
5631     Sets the focusProxy pointer to 0 for all items that have this item as their
5632     focusProxy. ### Qt 5: Use QPointer instead.
5633 */
resetFocusProxy()5634 void QGraphicsItemPrivate::resetFocusProxy()
5635 {
5636     for (int i = 0; i < focusProxyRefs.size(); ++i)
5637         *focusProxyRefs.at(i) = 0;
5638     focusProxyRefs.clear();
5639 }
5640 
5641 /*!
5642     \internal
5643 
5644     Subclasses can reimplement this function to be notified when subFocusItem
5645     changes.
5646 */
subFocusItemChange()5647 void QGraphicsItemPrivate::subFocusItemChange()
5648 {
5649 }
5650 
5651 /*!
5652     \internal
5653 
5654     Subclasses can reimplement this function to be notified when an item
5655     becomes a focusScopeItem (or is no longer a focusScopeItem).
5656 */
focusScopeItemChange(bool isSubFocusItem)5657 void QGraphicsItemPrivate::focusScopeItemChange(bool isSubFocusItem)
5658 {
5659     Q_UNUSED(isSubFocusItem);
5660 }
5661 
5662 /*!
5663     \internal
5664 
5665     Subclasses can reimplement this function to be notified when its
5666     siblingIndex order is changed.
5667 */
siblingOrderChange()5668 void QGraphicsItemPrivate::siblingOrderChange()
5669 {
5670 }
5671 
5672 /*!
5673     \internal
5674 
5675     Tells us if it is a proxy widget
5676 */
isProxyWidget() const5677 bool QGraphicsItemPrivate::isProxyWidget() const
5678 {
5679     return false;
5680 }
5681 
5682 /*!
5683     Schedules a redraw of the area covered by \a rect in this item. You can
5684     call this function whenever your item needs to be redrawn, such as if it
5685     changes appearance or size.
5686 
5687     This function does not cause an immediate paint; instead it schedules a
5688     paint request that is processed by QGraphicsView after control reaches the
5689     event loop. The item will only be redrawn if it is visible in any
5690     associated view.
5691 
5692     As a side effect of the item being repainted, other items that overlap the
5693     area \a rect may also be repainted.
5694 
5695     If the item is invisible (i.e., isVisible() returns false), this function
5696     does nothing.
5697 
5698     \sa paint(), boundingRect()
5699 */
update(const QRectF & rect)5700 void QGraphicsItem::update(const QRectF &rect)
5701 {
5702     if (rect.isEmpty() && !rect.isNull())
5703         return;
5704 
5705     // Make sure we notify effects about invalidated source.
5706 #ifndef QT_NO_GRAPHICSEFFECT
5707     d_ptr->invalidateParentGraphicsEffectsRecursively();
5708 #endif //QT_NO_GRAPHICSEFFECT
5709 
5710 #ifndef QT_NO_GRAPHICSEFFECT
5711     if (!d_ptr->updateDueToGraphicsEffect) {
5712 #endif
5713         if (CacheMode(d_ptr->cacheMode) != NoCache) {
5714             // Invalidate cache.
5715             QGraphicsItemCache *cache = d_ptr->extraItemCache();
5716             if (!cache->allExposed) {
5717                 if (rect.isNull()) {
5718                     cache->allExposed = true;
5719                     cache->exposed.clear();
5720                 } else {
5721                     cache->exposed.append(rect);
5722                 }
5723             }
5724             // Only invalidate cache; item is already dirty.
5725             if (d_ptr->fullUpdatePending)
5726                 return;
5727         }
5728 #ifndef QT_NO_GRAPHICSEFFECT
5729     }
5730 #endif
5731 
5732     if (d_ptr->scene)
5733         d_ptr->scene->d_func()->markDirty(this, rect);
5734 }
5735 
5736 /*!
5737     \since 4.4
5738     Scrolls the contents of \a rect by \a dx, \a dy. If \a rect is a null rect
5739     (the default), the item's bounding rect is scrolled.
5740 
5741     Scrolling provides a fast alternative to simply redrawing when the
5742     contents of the item (or parts of the item) are shifted vertically or
5743     horizontally. Depending on the current transformation and the capabilities
5744     of the paint device (i.e., the viewport), this operation may consist of
5745     simply moving pixels from one location to another using memmove(). In most
5746     cases this is faster than rerendering the entire area.
5747 
5748     After scrolling, the item will issue an update for the newly exposed
5749     areas. If scrolling is not supported (e.g., you are rendering to an OpenGL
5750     viewport, which does not benefit from scroll optimizations), this function
5751     is equivalent to calling update(\a rect).
5752 
5753     \bold{Note:} Scrolling is only supported when QGraphicsItem::ItemCoordinateCache
5754     is enabled; in all other cases calling this function is equivalent to calling
5755     update(\a rect). If you for sure know that the item is opaque and not overlapped
5756     by other items, you can map the \a rect to viewport coordinates and scroll the
5757     viewport.
5758 
5759     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 19
5760 
5761     \sa boundingRect()
5762 */
scroll(qreal dx,qreal dy,const QRectF & rect)5763 void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
5764 {
5765     Q_D(QGraphicsItem);
5766     if (dx == 0.0 && dy == 0.0)
5767         return;
5768     if (!d->scene)
5769         return;
5770 
5771     // Accelerated scrolling means moving pixels from one location to another
5772     // and only redraw the newly exposed area. The following requirements must
5773     // be fulfilled in order to do that:
5774     //
5775     // 1) Item is opaque.
5776     // 2) Item is not overlapped by other items.
5777     //
5778     // There's (yet) no way to detect whether an item is opaque or not, which means
5779     // we cannot do accelerated scrolling unless the cache is enabled. In case of using
5780     // DeviceCoordinate cache we also have to take the device transform into account in
5781     // order to determine whether we can do accelerated scrolling or not. That's left out
5782     // for simplicity here, but it is definitely something we can consider in the future
5783     // as a performance improvement.
5784     if (d->cacheMode != QGraphicsItem::ItemCoordinateCache
5785         || !qFuzzyIsNull(dx - int(dx)) || !qFuzzyIsNull(dy - int(dy))) {
5786         update(rect);
5787         return;
5788     }
5789 
5790     QGraphicsItemCache *cache = d->extraItemCache();
5791     if (cache->allExposed || cache->fixedSize.isValid()) {
5792         // Cache is either invalidated or item is scaled (see QGraphicsItem::setCacheMode).
5793         update(rect);
5794         return;
5795     }
5796 
5797     // Find pixmap in cache.
5798     QPixmap cachedPixmap;
5799     if (!QPixmapCache::find(cache->key, &cachedPixmap)) {
5800         update(rect);
5801         return;
5802     }
5803 
5804     QRect scrollRect = (rect.isNull() ? boundingRect() : rect).toAlignedRect();
5805     if (!scrollRect.intersects(cache->boundingRect))
5806         return; // Nothing to scroll.
5807 
5808     // Remove from cache to avoid deep copy when modifying.
5809     QPixmapCache::remove(cache->key);
5810 
5811     QRegion exposed;
5812     cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed);
5813 
5814     // Reinsert into cache.
5815     cache->key = QPixmapCache::insert(cachedPixmap);
5816 
5817     // Translate the existing expose.
5818     for (int i = 0; i < cache->exposed.size(); ++i) {
5819         QRectF &e = cache->exposed[i];
5820         if (!rect.isNull() && !e.intersects(rect))
5821             continue;
5822         e.translate(dx, dy);
5823     }
5824 
5825     // Append newly exposed areas. Note that the exposed region is currently
5826     // in pixmap coordinates, so we have to translate it to item coordinates.
5827     exposed.translate(cache->boundingRect.topLeft());
5828     const QVector<QRect> exposedRects = exposed.rects();
5829     for (int i = 0; i < exposedRects.size(); ++i)
5830         cache->exposed += exposedRects.at(i);
5831 
5832     // Trigger update. This will redraw the newly exposed area and make sure
5833     // the pixmap is re-blitted in case there are overlapping items.
5834     d->scene->d_func()->markDirty(this, rect);
5835 }
5836 
5837 /*!
5838     \fn void QGraphicsItem::update(qreal x, qreal y, qreal width, qreal height)
5839     \overload
5840 
5841     This convenience function is equivalent to calling update(QRectF(\a x, \a
5842     y, \a width, \a height)).
5843 */
5844 
5845 /*!
5846     Maps the point \a point, which is in this item's coordinate system, to \a
5847     item's coordinate system, and returns the mapped coordinate.
5848 
5849     If \a item is 0, this function returns the same as mapToScene().
5850 
5851     \sa itemTransform(), mapToParent(), mapToScene(), transform(), mapFromItem(), {The Graphics
5852     View Coordinate System}
5853 */
mapToItem(const QGraphicsItem * item,const QPointF & point) const5854 QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point) const
5855 {
5856     if (item)
5857         return itemTransform(item).map(point);
5858     return mapToScene(point);
5859 }
5860 
5861 /*!
5862     \fn QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, qreal x, qreal y) const
5863     \overload
5864 
5865     This convenience function is equivalent to calling mapToItem(\a item,
5866     QPointF(\a x, \a y)).
5867 */
5868 
5869 /*!
5870     Maps the point \a point, which is in this item's coordinate system, to its
5871     parent's coordinate system, and returns the mapped coordinate. If the item
5872     has no parent, \a point will be mapped to the scene's coordinate system.
5873 
5874     \sa mapToItem(), mapToScene(), transform(), mapFromParent(), {The Graphics
5875     View Coordinate System}
5876 */
mapToParent(const QPointF & point) const5877 QPointF QGraphicsItem::mapToParent(const QPointF &point) const
5878 {
5879     // COMBINE
5880     if (!d_ptr->transformData)
5881         return point + d_ptr->pos;
5882     return d_ptr->transformToParent().map(point);
5883 }
5884 
5885 /*!
5886     \fn QPointF QGraphicsItem::mapToParent(qreal x, qreal y) const
5887     \overload
5888 
5889     This convenience function is equivalent to calling mapToParent(QPointF(\a
5890     x, \a y)).
5891 */
5892 
5893 /*!
5894     Maps the point \a point, which is in this item's coordinate system, to the
5895     scene's coordinate system, and returns the mapped coordinate.
5896 
5897     \sa mapToItem(), mapToParent(), transform(), mapFromScene(), {The Graphics
5898     View Coordinate System}
5899 */
mapToScene(const QPointF & point) const5900 QPointF QGraphicsItem::mapToScene(const QPointF &point) const
5901 {
5902     if (d_ptr->hasTranslateOnlySceneTransform())
5903         return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy());
5904     return d_ptr->sceneTransform.map(point);
5905 }
5906 
5907 /*!
5908     \fn QPointF QGraphicsItem::mapToScene(qreal x, qreal y) const
5909     \overload
5910 
5911     This convenience function is equivalent to calling mapToScene(QPointF(\a
5912     x, \a y)).
5913 */
5914 
5915 /*!
5916     Maps the rectangle \a rect, which is in this item's coordinate system, to
5917     \a item's coordinate system, and returns the mapped rectangle as a polygon.
5918 
5919     If \a item is 0, this function returns the same as mapToScene().
5920 
5921     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
5922     Graphics View Coordinate System}
5923 */
mapToItem(const QGraphicsItem * item,const QRectF & rect) const5924 QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect) const
5925 {
5926     if (item)
5927         return itemTransform(item).map(rect);
5928     return mapToScene(rect);
5929 }
5930 
5931 /*!
5932     \fn QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const
5933     \since 4.3
5934 
5935     This convenience function is equivalent to calling mapToItem(item, QRectF(\a x, \a y, \a w, \a h)).
5936 */
5937 
5938 /*!
5939     Maps the rectangle \a rect, which is in this item's coordinate system, to
5940     its parent's coordinate system, and returns the mapped rectangle as a
5941     polygon. If the item has no parent, \a rect will be mapped to the scene's
5942     coordinate system.
5943 
5944     \sa mapToScene(), mapToItem(), mapFromParent(), {The Graphics View
5945     Coordinate System}
5946 */
mapToParent(const QRectF & rect) const5947 QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const
5948 {
5949     // COMBINE
5950     if (!d_ptr->transformData)
5951         return rect.translated(d_ptr->pos);
5952     return d_ptr->transformToParent().map(rect);
5953 }
5954 
5955 /*!
5956     \fn QPolygonF QGraphicsItem::mapToParent(qreal x, qreal y, qreal w, qreal h) const
5957     \since 4.3
5958 
5959     This convenience function is equivalent to calling mapToParent(QRectF(\a x, \a y, \a w, \a h)).
5960 */
5961 
5962 /*!
5963     Maps the rectangle \a rect, which is in this item's coordinate system, to
5964     the scene's coordinate system, and returns the mapped rectangle as a polygon.
5965 
5966     \sa mapToParent(), mapToItem(), mapFromScene(), {The Graphics View
5967     Coordinate System}
5968 */
mapToScene(const QRectF & rect) const5969 QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const
5970 {
5971     if (d_ptr->hasTranslateOnlySceneTransform())
5972         return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
5973     return d_ptr->sceneTransform.map(rect);
5974 }
5975 
5976 /*!
5977     \fn QPolygonF QGraphicsItem::mapToScene(qreal x, qreal y, qreal w, qreal h) const
5978     \since 4.3
5979 
5980     This convenience function is equivalent to calling mapToScene(QRectF(\a x, \a y, \a w, \a h)).
5981 */
5982 
5983 /*!
5984     \since 4.5
5985 
5986     Maps the rectangle \a rect, which is in this item's coordinate system, to
5987     \a item's coordinate system, and returns the mapped rectangle as a new
5988     rectangle (i.e., the bounding rectangle of the resulting polygon).
5989 
5990     If \a item is 0, this function returns the same as mapRectToScene().
5991 
5992     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
5993     Graphics View Coordinate System}
5994 */
mapRectToItem(const QGraphicsItem * item,const QRectF & rect) const5995 QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rect) const
5996 {
5997     if (item)
5998         return itemTransform(item).mapRect(rect);
5999     return mapRectToScene(rect);
6000 }
6001 
6002 /*!
6003     \fn QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const
6004     \since 4.5
6005 
6006     This convenience function is equivalent to calling mapRectToItem(item, QRectF(\a x, \a y, \a w, \a h)).
6007 */
6008 
6009 /*!
6010     \since 4.5
6011 
6012     Maps the rectangle \a rect, which is in this item's coordinate system, to
6013     its parent's coordinate system, and returns the mapped rectangle as a new
6014     rectangle (i.e., the bounding rectangle of the resulting polygon).
6015 
6016     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
6017     Graphics View Coordinate System}
6018 */
mapRectToParent(const QRectF & rect) const6019 QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const
6020 {
6021     // COMBINE
6022     if (!d_ptr->transformData)
6023         return rect.translated(d_ptr->pos);
6024     return d_ptr->transformToParent().mapRect(rect);
6025 }
6026 
6027 /*!
6028     \fn QRectF QGraphicsItem::mapRectToParent(qreal x, qreal y, qreal w, qreal h) const
6029     \since 4.5
6030 
6031     This convenience function is equivalent to calling mapRectToParent(QRectF(\a x, \a y, \a w, \a h)).
6032 */
6033 
6034 /*!
6035     \since 4.5
6036 
6037     Maps the rectangle \a rect, which is in this item's coordinate system, to
6038     the scene coordinate system, and returns the mapped rectangle as a new
6039     rectangle (i.e., the bounding rectangle of the resulting polygon).
6040 
6041     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
6042     Graphics View Coordinate System}
6043 */
mapRectToScene(const QRectF & rect) const6044 QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const
6045 {
6046     if (d_ptr->hasTranslateOnlySceneTransform())
6047         return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
6048     return d_ptr->sceneTransform.mapRect(rect);
6049 }
6050 
6051 /*!
6052     \fn QRectF QGraphicsItem::mapRectToScene(qreal x, qreal y, qreal w, qreal h) const
6053     \since 4.5
6054 
6055     This convenience function is equivalent to calling mapRectToScene(QRectF(\a x, \a y, \a w, \a h)).
6056 */
6057 
6058 /*!
6059     \since 4.5
6060 
6061     Maps the rectangle \a rect, which is in \a item's coordinate system, to
6062     this item's coordinate system, and returns the mapped rectangle as a new
6063     rectangle (i.e., the bounding rectangle of the resulting polygon).
6064 
6065     If \a item is 0, this function returns the same as mapRectFromScene().
6066 
6067     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
6068     Graphics View Coordinate System}
6069 */
mapRectFromItem(const QGraphicsItem * item,const QRectF & rect) const6070 QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &rect) const
6071 {
6072     if (item)
6073         return item->itemTransform(this).mapRect(rect);
6074     return mapRectFromScene(rect);
6075 }
6076 
6077 /*!
6078     \fn QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const
6079     \since 4.5
6080 
6081     This convenience function is equivalent to calling mapRectFromItem(item, QRectF(\a x, \a y, \a w, \a h)).
6082 */
6083 
6084 /*!
6085     \since 4.5
6086 
6087     Maps the rectangle \a rect, which is in this item's parent's coordinate
6088     system, to this item's coordinate system, and returns the mapped rectangle
6089     as a new rectangle (i.e., the bounding rectangle of the resulting
6090     polygon).
6091 
6092     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
6093     Graphics View Coordinate System}
6094 */
mapRectFromParent(const QRectF & rect) const6095 QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const
6096 {
6097     // COMBINE
6098     if (!d_ptr->transformData)
6099         return rect.translated(-d_ptr->pos);
6100     return d_ptr->transformToParent().inverted().mapRect(rect);
6101 }
6102 
6103 /*!
6104     \fn QRectF QGraphicsItem::mapRectFromParent(qreal x, qreal y, qreal w, qreal h) const
6105     \since 4.5
6106 
6107     This convenience function is equivalent to calling mapRectFromParent(QRectF(\a x, \a y, \a w, \a h)).
6108 */
6109 
6110 /*!
6111     \since 4.5
6112 
6113     Maps the rectangle \a rect, which is in scene coordinates, to this item's
6114     coordinate system, and returns the mapped rectangle as a new rectangle
6115     (i.e., the bounding rectangle of the resulting polygon).
6116 
6117     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
6118     Graphics View Coordinate System}
6119 */
mapRectFromScene(const QRectF & rect) const6120 QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const
6121 {
6122     if (d_ptr->hasTranslateOnlySceneTransform())
6123         return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
6124     return d_ptr->sceneTransform.inverted().mapRect(rect);
6125 }
6126 
6127 /*!
6128     \fn QRectF QGraphicsItem::mapRectFromScene(qreal x, qreal y, qreal w, qreal h) const
6129     \since 4.5
6130 
6131     This convenience function is equivalent to calling mapRectFromScene(QRectF(\a x, \a y, \a w, \a h)).
6132 */
6133 
6134 /*!
6135     Maps the polygon \a polygon, which is in this item's coordinate system, to
6136     \a item's coordinate system, and returns the mapped polygon.
6137 
6138     If \a item is 0, this function returns the same as mapToScene().
6139 
6140     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
6141     Graphics View Coordinate System}
6142 */
mapToItem(const QGraphicsItem * item,const QPolygonF & polygon) const6143 QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &polygon) const
6144 {
6145     if (item)
6146         return itemTransform(item).map(polygon);
6147     return mapToScene(polygon);
6148 }
6149 
6150 /*!
6151     Maps the polygon \a polygon, which is in this item's coordinate system, to
6152     its parent's coordinate system, and returns the mapped polygon. If the
6153     item has no parent, \a polygon will be mapped to the scene's coordinate
6154     system.
6155 
6156     \sa mapToScene(), mapToItem(), mapFromParent(), {The Graphics View
6157     Coordinate System}
6158 */
mapToParent(const QPolygonF & polygon) const6159 QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
6160 {
6161     // COMBINE
6162     if (!d_ptr->transformData)
6163         return polygon.translated(d_ptr->pos);
6164     return d_ptr->transformToParent().map(polygon);
6165 }
6166 
6167 /*!
6168     Maps the polygon \a polygon, which is in this item's coordinate system, to
6169     the scene's coordinate system, and returns the mapped polygon.
6170 
6171     \sa mapToParent(), mapToItem(), mapFromScene(), {The Graphics View
6172     Coordinate System}
6173 */
mapToScene(const QPolygonF & polygon) const6174 QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const
6175 {
6176     if (d_ptr->hasTranslateOnlySceneTransform())
6177         return polygon.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
6178     return d_ptr->sceneTransform.map(polygon);
6179 }
6180 
6181 /*!
6182     Maps the path \a path, which is in this item's coordinate system, to
6183     \a item's coordinate system, and returns the mapped path.
6184 
6185     If \a item is 0, this function returns the same as mapToScene().
6186 
6187     \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
6188     Graphics View Coordinate System}
6189 */
mapToItem(const QGraphicsItem * item,const QPainterPath & path) const6190 QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterPath &path) const
6191 {
6192     if (item)
6193         return itemTransform(item).map(path);
6194     return mapToScene(path);
6195 }
6196 
6197 /*!
6198     Maps the path \a path, which is in this item's coordinate system, to
6199     its parent's coordinate system, and returns the mapped path. If the
6200     item has no parent, \a path will be mapped to the scene's coordinate
6201     system.
6202 
6203     \sa mapToScene(), mapToItem(), mapFromParent(), {The Graphics View
6204     Coordinate System}
6205 */
mapToParent(const QPainterPath & path) const6206 QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const
6207 {
6208     // COMBINE
6209     if (!d_ptr->transformData)
6210         return path.translated(d_ptr->pos);
6211     return d_ptr->transformToParent().map(path);
6212 }
6213 
6214 /*!
6215     Maps the path \a path, which is in this item's coordinate system, to
6216     the scene's coordinate system, and returns the mapped path.
6217 
6218     \sa mapToParent(), mapToItem(), mapFromScene(), {The Graphics View
6219     Coordinate System}
6220 */
mapToScene(const QPainterPath & path) const6221 QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const
6222 {
6223     if (d_ptr->hasTranslateOnlySceneTransform())
6224         return path.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
6225     return d_ptr->sceneTransform.map(path);
6226 }
6227 
6228 /*!
6229     Maps the point \a point, which is in \a item's coordinate system, to this
6230     item's coordinate system, and returns the mapped coordinate.
6231 
6232     If \a item is 0, this function returns the same as mapFromScene().
6233 
6234     \sa itemTransform(), mapFromParent(), mapFromScene(), transform(), mapToItem(), {The Graphics
6235     View Coordinate System}
6236 */
mapFromItem(const QGraphicsItem * item,const QPointF & point) const6237 QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &point) const
6238 {
6239     if (item)
6240         return item->itemTransform(this).map(point);
6241     return mapFromScene(point);
6242 }
6243 
6244 /*!
6245     \fn QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, qreal x, qreal y) const
6246     \overload
6247 
6248     This convenience function is equivalent to calling mapFromItem(\a item,
6249     QPointF(\a x, \a y)).
6250 */
6251 
6252 /*!
6253     Maps the point \a point, which is in this item's parent's coordinate
6254     system, to this item's coordinate system, and returns the mapped
6255     coordinate.
6256 
6257     \sa mapFromItem(), mapFromScene(), transform(), mapToParent(), {The Graphics
6258     View Coordinate System}
6259 */
mapFromParent(const QPointF & point) const6260 QPointF QGraphicsItem::mapFromParent(const QPointF &point) const
6261 {
6262     // COMBINE
6263     if (d_ptr->transformData)
6264         return d_ptr->transformToParent().inverted().map(point);
6265     return point - d_ptr->pos;
6266 }
6267 
6268 /*!
6269     \fn QPointF QGraphicsItem::mapFromParent(qreal x, qreal y) const
6270     \overload
6271 
6272     This convenience function is equivalent to calling
6273     mapFromParent(QPointF(\a x, \a y)).
6274 */
6275 
6276 /*!
6277     Maps the point \a point, which is in this item's scene's coordinate
6278     system, to this item's coordinate system, and returns the mapped
6279     coordinate.
6280 
6281     \sa mapFromItem(), mapFromParent(), transform(), mapToScene(), {The Graphics
6282     View Coordinate System}
6283 */
mapFromScene(const QPointF & point) const6284 QPointF QGraphicsItem::mapFromScene(const QPointF &point) const
6285 {
6286     if (d_ptr->hasTranslateOnlySceneTransform())
6287         return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy());
6288     return d_ptr->sceneTransform.inverted().map(point);
6289 }
6290 
6291 /*!
6292     \fn QPointF QGraphicsItem::mapFromScene(qreal x, qreal y) const
6293     \overload
6294 
6295     This convenience function is equivalent to calling mapFromScene(QPointF(\a
6296     x, \a y)).
6297 */
6298 
6299 /*!
6300     Maps the rectangle \a rect, which is in \a item's coordinate system, to
6301     this item's coordinate system, and returns the mapped rectangle as a
6302     polygon.
6303 
6304     If \a item is 0, this function returns the same as mapFromScene()
6305 
6306     \sa itemTransform(), mapToItem(), mapFromParent(), transform(), {The Graphics View Coordinate
6307     System}
6308 */
mapFromItem(const QGraphicsItem * item,const QRectF & rect) const6309 QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &rect) const
6310 {
6311     if (item)
6312         return item->itemTransform(this).map(rect);
6313     return mapFromScene(rect);
6314 }
6315 
6316 /*!
6317     \fn QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const
6318     \since 4.3
6319 
6320     This convenience function is equivalent to calling mapFromItem(item, QRectF(\a x, \a y, \a w, \a h)).
6321 */
6322 
6323 /*!
6324     Maps the rectangle \a rect, which is in this item's parent's coordinate
6325     system, to this item's coordinate system, and returns the mapped rectangle
6326     as a polygon.
6327 
6328     \sa mapToParent(), mapFromItem(), transform(), {The Graphics View Coordinate
6329     System}
6330 */
mapFromParent(const QRectF & rect) const6331 QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const
6332 {
6333     // COMBINE
6334     if (!d_ptr->transformData)
6335         return rect.translated(-d_ptr->pos);
6336     return d_ptr->transformToParent().inverted().map(rect);
6337 }
6338 
6339 /*!
6340     \fn QPolygonF QGraphicsItem::mapFromParent(qreal x, qreal y, qreal w, qreal h) const
6341     \since 4.3
6342 
6343     This convenience function is equivalent to calling mapFromItem(QRectF(\a x, \a y, \a w, \a h)).
6344 */
6345 
6346 /*!
6347     Maps the rectangle \a rect, which is in this item's scene's coordinate
6348     system, to this item's coordinate system, and returns the mapped rectangle
6349     as a polygon.
6350 
6351     \sa mapToScene(), mapFromItem(), transform(), {The Graphics View Coordinate
6352     System}
6353 */
mapFromScene(const QRectF & rect) const6354 QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const
6355 {
6356     if (d_ptr->hasTranslateOnlySceneTransform())
6357         return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
6358     return d_ptr->sceneTransform.inverted().map(rect);
6359 }
6360 
6361 /*!
6362     \fn QPolygonF QGraphicsItem::mapFromScene(qreal x, qreal y, qreal w, qreal h) const
6363     \since 4.3
6364 
6365     This convenience function is equivalent to calling mapFromScene(QRectF(\a x, \a y, \a w, \a h)).
6366 */
6367 
6368 /*!
6369     Maps the polygon \a polygon, which is in \a item's coordinate system, to
6370     this item's coordinate system, and returns the mapped polygon.
6371 
6372     If \a item is 0, this function returns the same as mapFromScene().
6373 
6374     \sa itemTransform(), mapToItem(), mapFromParent(), transform(), {The
6375     Graphics View Coordinate System}
6376 */
mapFromItem(const QGraphicsItem * item,const QPolygonF & polygon) const6377 QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPolygonF &polygon) const
6378 {
6379     if (item)
6380         return item->itemTransform(this).map(polygon);
6381     return mapFromScene(polygon);
6382 }
6383 
6384 /*!
6385     Maps the polygon \a polygon, which is in this item's parent's coordinate
6386     system, to this item's coordinate system, and returns the mapped polygon.
6387 
6388     \sa mapToParent(), mapToItem(), transform(), {The Graphics View Coordinate
6389     System}
6390 */
mapFromParent(const QPolygonF & polygon) const6391 QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const
6392 {
6393     // COMBINE
6394     if (!d_ptr->transformData)
6395         return polygon.translated(-d_ptr->pos);
6396     return d_ptr->transformToParent().inverted().map(polygon);
6397 }
6398 
6399 /*!
6400     Maps the polygon \a polygon, which is in this item's scene's coordinate
6401     system, to this item's coordinate system, and returns the mapped polygon.
6402 
6403     \sa mapToScene(), mapFromParent(), transform(), {The Graphics View Coordinate
6404     System}
6405 */
mapFromScene(const QPolygonF & polygon) const6406 QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const
6407 {
6408     if (d_ptr->hasTranslateOnlySceneTransform())
6409         return polygon.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
6410     return d_ptr->sceneTransform.inverted().map(polygon);
6411 }
6412 
6413 /*!
6414     Maps the path \a path, which is in \a item's coordinate system, to
6415     this item's coordinate system, and returns the mapped path.
6416 
6417     If \a item is 0, this function returns the same as mapFromScene().
6418 
6419     \sa itemTransform(), mapFromParent(), mapFromScene(), mapToItem(), {The
6420     Graphics View Coordinate System}
6421 */
mapFromItem(const QGraphicsItem * item,const QPainterPath & path) const6422 QPainterPath QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPainterPath &path) const
6423 {
6424     if (item)
6425         return item->itemTransform(this).map(path);
6426     return mapFromScene(path);
6427 }
6428 
6429 /*!
6430     Maps the path \a path, which is in this item's parent's coordinate
6431     system, to this item's coordinate system, and returns the mapped path.
6432 
6433     \sa mapFromScene(), mapFromItem(), mapToParent(), {The Graphics View
6434     Coordinate System}
6435 */
mapFromParent(const QPainterPath & path) const6436 QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const
6437 {
6438     // COMBINE
6439     if (!d_ptr->transformData)
6440             return path.translated(-d_ptr->pos);
6441     return d_ptr->transformToParent().inverted().map(path);
6442 }
6443 
6444 /*!
6445     Maps the path \a path, which is in this item's scene's coordinate
6446     system, to this item's coordinate system, and returns the mapped path.
6447 
6448     \sa mapFromParent(), mapFromItem(), mapToScene(), {The Graphics View
6449     Coordinate System}
6450 */
mapFromScene(const QPainterPath & path) const6451 QPainterPath QGraphicsItem::mapFromScene(const QPainterPath &path) const
6452 {
6453     if (d_ptr->hasTranslateOnlySceneTransform())
6454         return path.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
6455     return d_ptr->sceneTransform.inverted().map(path);
6456 }
6457 
6458 /*!
6459     Returns true if this item is an ancestor of \a child (i.e., if this item
6460     is \a child's parent, or one of \a child's parent's ancestors).
6461 
6462     \sa parentItem()
6463 */
isAncestorOf(const QGraphicsItem * child) const6464 bool QGraphicsItem::isAncestorOf(const QGraphicsItem *child) const
6465 {
6466     if (!child || child == this)
6467         return false;
6468     if (child->d_ptr->depth() < d_ptr->depth())
6469         return false;
6470     const QGraphicsItem *ancestor = child;
6471     while ((ancestor = ancestor->d_ptr->parent)) {
6472         if (ancestor == this)
6473             return true;
6474     }
6475     return false;
6476 }
6477 
6478 /*!
6479     \since 4.4
6480 
6481     Returns the closest common ancestor item of this item and \a other, or 0
6482     if either \a other is 0, or there is no common ancestor.
6483 
6484     \sa isAncestorOf()
6485 */
commonAncestorItem(const QGraphicsItem * other) const6486 QGraphicsItem *QGraphicsItem::commonAncestorItem(const QGraphicsItem *other) const
6487 {
6488     if (!other)
6489         return 0;
6490     if (other == this)
6491         return const_cast<QGraphicsItem *>(this);
6492     const QGraphicsItem *thisw = this;
6493     const QGraphicsItem *otherw = other;
6494     int thisDepth = d_ptr->depth();
6495     int otherDepth = other->d_ptr->depth();
6496     while (thisDepth > otherDepth) {
6497         thisw = thisw->d_ptr->parent;
6498         --thisDepth;
6499     }
6500     while (otherDepth > thisDepth) {
6501         otherw = otherw->d_ptr->parent;
6502         --otherDepth;
6503     }
6504     while (thisw && thisw != otherw) {
6505         thisw = thisw->d_ptr->parent;
6506         otherw = otherw->d_ptr->parent;
6507     }
6508     return const_cast<QGraphicsItem *>(thisw);
6509 }
6510 
6511 /*!
6512     \since 4,4
6513     Returns true if this item is currently under the mouse cursor in one of
6514     the views; otherwise, false is returned.
6515 
6516     \sa QGraphicsScene::views(), QCursor::pos()
6517 */
isUnderMouse() const6518 bool QGraphicsItem::isUnderMouse() const
6519 {
6520     Q_D(const QGraphicsItem);
6521     if (!d->scene)
6522         return false;
6523 
6524     QPoint cursorPos = QCursor::pos();
6525     foreach (QGraphicsView *view, d->scene->views()) {
6526         if (contains(mapFromScene(view->mapToScene(view->mapFromGlobal(cursorPos)))))
6527             return true;
6528     }
6529     return false;
6530 }
6531 
6532 /*!
6533     Returns this item's custom data for the key \a key as a QVariant.
6534 
6535     Custom item data is useful for storing arbitrary properties in any
6536     item. Example:
6537 
6538     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 11
6539 
6540     Qt does not use this feature for storing data; it is provided solely
6541     for the convenience of the user.
6542 
6543     \sa setData()
6544 */
data(int key) const6545 QVariant QGraphicsItem::data(int key) const
6546 {
6547     QGraphicsItemCustomDataStore *store = qt_dataStore();
6548     if (!store->data.contains(this))
6549         return QVariant();
6550     return store->data.value(this).value(key);
6551 }
6552 
6553 /*!
6554     Sets this item's custom data for the key \a key to \a value.
6555 
6556     Custom item data is useful for storing arbitrary properties for any
6557     item. Qt does not use this feature for storing data; it is provided solely
6558     for the convenience of the user.
6559 
6560     \sa data()
6561 */
setData(int key,const QVariant & value)6562 void QGraphicsItem::setData(int key, const QVariant &value)
6563 {
6564     qt_dataStore()->data[this][key] = value;
6565 }
6566 
6567 /*!
6568     \fn T qgraphicsitem_cast(QGraphicsItem *item)
6569     \relates QGraphicsItem
6570     \since 4.2
6571 
6572     Returns the given \a item cast to type T if \a item is of type T;
6573     otherwise, 0 is returned.
6574 
6575     \note To make this function work correctly with custom items, reimplement
6576     the \l{QGraphicsItem::}{type()} function for each custom QGraphicsItem
6577     subclass.
6578 
6579     \sa QGraphicsItem::type(), QGraphicsItem::UserType
6580 */
6581 
6582 /*!
6583     Returns the type of an item as an int. All standard graphicsitem classes
6584     are associated with a unique value; see QGraphicsItem::Type. This type
6585     information is used by qgraphicsitem_cast() to distinguish between types.
6586 
6587     The default implementation (in QGraphicsItem) returns UserType.
6588 
6589     To enable use of qgraphicsitem_cast() with a custom item, reimplement this
6590     function and declare a Type enum value equal to your custom item's type.
6591     Custom items must return a value larger than or equal to UserType (65536).
6592 
6593     For example:
6594 
6595     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp QGraphicsItem type
6596 
6597     \sa UserType
6598 */
type() const6599 int QGraphicsItem::type() const
6600 {
6601     return (int)UserType;
6602 }
6603 
6604 /*!
6605     Installs an event filter for this item on \a filterItem, causing
6606     all events for this item to first pass through \a filterItem's
6607     sceneEventFilter() function.
6608 
6609     To filter another item's events, install this item as an event filter
6610     for the other item. Example:
6611 
6612     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 12
6613 
6614     An item can only filter events for other items in the same
6615     scene. Also, an item cannot filter its own events; instead, you
6616     can reimplement sceneEvent() directly.
6617 
6618     Items must belong to a scene for scene event filters to be installed and
6619     used.
6620 
6621     \sa removeSceneEventFilter(), sceneEventFilter(), sceneEvent()
6622 */
installSceneEventFilter(QGraphicsItem * filterItem)6623 void QGraphicsItem::installSceneEventFilter(QGraphicsItem *filterItem)
6624 {
6625     if (!d_ptr->scene) {
6626         qWarning("QGraphicsItem::installSceneEventFilter: event filters can only be installed"
6627                  " on items in a scene.");
6628         return;
6629     }
6630     if (d_ptr->scene != filterItem->scene()) {
6631         qWarning("QGraphicsItem::installSceneEventFilter: event filters can only be installed"
6632                  " on items in the same scene.");
6633         return;
6634     }
6635     d_ptr->scene->d_func()->installSceneEventFilter(this, filterItem);
6636 }
6637 
6638 /*!
6639     Removes an event filter on this item from \a filterItem.
6640 
6641     \sa installSceneEventFilter()
6642 */
removeSceneEventFilter(QGraphicsItem * filterItem)6643 void QGraphicsItem::removeSceneEventFilter(QGraphicsItem *filterItem)
6644 {
6645     if (!d_ptr->scene || d_ptr->scene != filterItem->scene())
6646         return;
6647     d_ptr->scene->d_func()->removeSceneEventFilter(this, filterItem);
6648 }
6649 
6650 /*!
6651     Filters events for the item \a watched. \a event is the filtered
6652     event.
6653 
6654     Reimplementing this function in a subclass makes it possible
6655     for the item to be used as an event filter for other items,
6656     intercepting all the events send to those items before they are
6657     able to respond.
6658 
6659     Reimplementations must return true to prevent further processing of
6660     a given event, ensuring that it will not be delivered to the watched
6661     item, or return false to indicate that the event should be propagated
6662     further by the event system.
6663 
6664     \sa installSceneEventFilter()
6665 */
sceneEventFilter(QGraphicsItem * watched,QEvent * event)6666 bool QGraphicsItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
6667 {
6668     Q_UNUSED(watched);
6669     Q_UNUSED(event);
6670     return false;
6671 }
6672 
6673 /*!
6674     This virtual function receives events to this item. Reimplement
6675     this function to intercept events before they are dispatched to
6676     the specialized event handlers contextMenuEvent(), focusInEvent(),
6677     focusOutEvent(), hoverEnterEvent(), hoverMoveEvent(),
6678     hoverLeaveEvent(), keyPressEvent(), keyReleaseEvent(),
6679     mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(), and
6680     mouseDoubleClickEvent().
6681 
6682     Returns true if the event was recognized and handled; otherwise, (e.g., if
6683     the event type was not recognized,) false is returned.
6684 
6685     \a event is the intercepted event.
6686 */
sceneEvent(QEvent * event)6687 bool QGraphicsItem::sceneEvent(QEvent *event)
6688 {
6689     if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents) {
6690         if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave
6691             || event->type() == QEvent::DragEnter || event->type() == QEvent::DragLeave) {
6692             // Hover enter and hover leave events for children are ignored;
6693             // hover move events are forwarded.
6694             return true;
6695         }
6696 
6697         QGraphicsItem *handler = this;
6698         do {
6699             handler = handler->d_ptr->parent;
6700             Q_ASSERT(handler);
6701         } while (handler->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents);
6702         // Forward the event to the closest parent that handles child
6703         // events, mapping existing item-local coordinates to its
6704         // coordinate system.
6705         d_ptr->remapItemPos(event, handler);
6706         handler->sceneEvent(event);
6707         return true;
6708     }
6709 
6710     if (event->type() == QEvent::FocusOut) {
6711         focusOutEvent(static_cast<QFocusEvent *>(event));
6712         return true;
6713     }
6714 
6715     if (!d_ptr->visible) {
6716         // Eaten
6717         return true;
6718     }
6719 
6720     switch (event->type()) {
6721     case QEvent::FocusIn:
6722         focusInEvent(static_cast<QFocusEvent *>(event));
6723         break;
6724     case QEvent::GraphicsSceneContextMenu:
6725         contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent *>(event));
6726         break;
6727     case QEvent::GraphicsSceneDragEnter:
6728         dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
6729         break;
6730     case QEvent::GraphicsSceneDragMove:
6731         dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
6732         break;
6733     case QEvent::GraphicsSceneDragLeave:
6734         dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
6735         break;
6736     case QEvent::GraphicsSceneDrop:
6737         dropEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
6738         break;
6739     case QEvent::GraphicsSceneHoverEnter:
6740         hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
6741         break;
6742     case QEvent::GraphicsSceneHoverMove:
6743         hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
6744         break;
6745     case QEvent::GraphicsSceneHoverLeave:
6746         hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
6747         break;
6748     case QEvent::GraphicsSceneMouseMove:
6749         mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
6750         break;
6751     case QEvent::GraphicsSceneMousePress:
6752         mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
6753         break;
6754     case QEvent::GraphicsSceneMouseRelease:
6755         mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
6756         break;
6757     case QEvent::GraphicsSceneMouseDoubleClick:
6758         mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
6759         break;
6760     case QEvent::GraphicsSceneWheel:
6761         wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event));
6762         break;
6763     case QEvent::KeyPress: {
6764         QKeyEvent *k = static_cast<QKeyEvent *>(event);
6765         if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
6766             if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
6767                 bool res = false;
6768                 if (k->key() == Qt::Key_Backtab
6769                     || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
6770                     if (d_ptr->isWidget) {
6771                         res = static_cast<QGraphicsWidget *>(this)->focusNextPrevChild(false);
6772                     } else if (d_ptr->scene) {
6773                         res = d_ptr->scene->focusNextPrevChild(false);
6774                     }
6775                 } else if (k->key() == Qt::Key_Tab) {
6776                     if (d_ptr->isWidget) {
6777                         res = static_cast<QGraphicsWidget *>(this)->focusNextPrevChild(true);
6778                     } else if (d_ptr->scene) {
6779                         res = d_ptr->scene->focusNextPrevChild(true);
6780                     }
6781                 }
6782                 if (!res)
6783                     event->ignore();
6784                 return true;
6785             }
6786         }
6787         keyPressEvent(static_cast<QKeyEvent *>(event));
6788         break;
6789     }
6790     case QEvent::KeyRelease:
6791         keyReleaseEvent(static_cast<QKeyEvent *>(event));
6792         break;
6793     case QEvent::InputMethod:
6794         inputMethodEvent(static_cast<QInputMethodEvent *>(event));
6795         break;
6796     case QEvent::WindowActivate:
6797     case QEvent::WindowDeactivate:
6798         // Propagate panel activation.
6799         if (d_ptr->scene) {
6800             for (int i = 0; i < d_ptr->children.size(); ++i) {
6801                 QGraphicsItem *child = d_ptr->children.at(i);
6802                 if (child->isVisible() && !child->isPanel()) {
6803                     if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents))
6804                         d_ptr->scene->sendEvent(child, event);
6805                 }
6806             }
6807         }
6808         break;
6809     default:
6810         return false;
6811     }
6812 
6813     return true;
6814 }
6815 
6816 /*!
6817     This event handler can be reimplemented in a subclass to process context
6818     menu events. The \a event parameter contains details about the event to
6819     be handled.
6820 
6821     If you ignore the event, (i.e., by calling QEvent::ignore(),) \a event
6822     will propagate to any item beneath this item. If no items accept the
6823     event, it will be ignored by the scene, and propagate to the view.
6824 
6825     It's common to open a QMenu in response to receiving a context menu
6826     event. Example:
6827 
6828     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 13
6829 
6830     The default implementation ignores the event.
6831 
6832     \sa sceneEvent()
6833 */
contextMenuEvent(QGraphicsSceneContextMenuEvent * event)6834 void QGraphicsItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
6835 {
6836     event->ignore();
6837 }
6838 
6839 /*!
6840     This event handler, for event \a event, can be reimplemented to receive
6841     drag enter events for this item. Drag enter events are generated as the
6842     cursor enters the item's area.
6843 
6844     By accepting the event, (i.e., by calling QEvent::accept(),) the item will
6845     accept drop events, in addition to receiving drag move and drag
6846     leave. Otherwise, the event will be ignored and propagate to the item
6847     beneath. If the event is accepted, the item will receive a drag move event
6848     before control goes back to the event loop.
6849 
6850     A common implementation of dragEnterEvent accepts or ignores \a event
6851     depending on the associated mime data in \a event. Example:
6852 
6853     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 14
6854 
6855     Items do not receive drag and drop events by default; to enable this
6856     feature, call \c setAcceptDrops(true).
6857 
6858     The default implementation does nothing.
6859 
6860     \sa dropEvent(), dragMoveEvent(), dragLeaveEvent()
6861 */
dragEnterEvent(QGraphicsSceneDragDropEvent * event)6862 void QGraphicsItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
6863 {
6864     Q_D(QGraphicsItem);
6865     // binary compatibility workaround between 4.4 and 4.5
6866     if (d->isProxyWidget())
6867         static_cast<QGraphicsProxyWidget*>(this)->dragEnterEvent(event);
6868 }
6869 
6870 /*!
6871     This event handler, for event \a event, can be reimplemented to receive
6872     drag leave events for this item. Drag leave events are generated as the
6873     cursor leaves the item's area. Most often you will not need to reimplement
6874     this function, but it can be useful for resetting state in your item
6875     (e.g., highlighting).
6876 
6877     Calling QEvent::ignore() or QEvent::accept() on \a event has no effect.
6878 
6879     Items do not receive drag and drop events by default; to enable this
6880     feature, call \c setAcceptDrops(true).
6881 
6882     The default implementation does nothing.
6883 
6884     \sa dragEnterEvent(), dropEvent(), dragMoveEvent()
6885 */
dragLeaveEvent(QGraphicsSceneDragDropEvent * event)6886 void QGraphicsItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
6887 {
6888     Q_D(QGraphicsItem);
6889     // binary compatibility workaround between 4.4 and 4.5
6890     if (d->isProxyWidget())
6891         static_cast<QGraphicsProxyWidget*>(this)->dragLeaveEvent(event);
6892 }
6893 
6894 /*!
6895     This event handler, for event \a event, can be reimplemented to receive
6896     drag move events for this item. Drag move events are generated as the
6897     cursor moves around inside the item's area. Most often you will not need
6898     to reimplement this function; it is used to indicate that only parts of
6899     the item can accept drops.
6900 
6901     Calling QEvent::ignore() or QEvent::accept() on \a event toggles whether
6902     or not the item will accept drops at the position from the event. By
6903     default, \a event is accepted, indicating that the item allows drops at
6904     the specified position.
6905 
6906     Items do not receive drag and drop events by default; to enable this
6907     feature, call \c setAcceptDrops(true).
6908 
6909     The default implementation does nothing.
6910 
6911     \sa dropEvent(), dragEnterEvent(), dragLeaveEvent()
6912 */
dragMoveEvent(QGraphicsSceneDragDropEvent * event)6913 void QGraphicsItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
6914 {
6915     Q_D(QGraphicsItem);
6916     // binary compatibility workaround between 4.4 and 4.5
6917     if (d->isProxyWidget())
6918         static_cast<QGraphicsProxyWidget*>(this)->dragMoveEvent(event);
6919 }
6920 
6921 /*!
6922     This event handler, for event \a event, can be reimplemented to receive
6923     drop events for this item. Items can only receive drop events if the last
6924     drag move event was accepted.
6925 
6926     Calling QEvent::ignore() or QEvent::accept() on \a event has no effect.
6927 
6928     Items do not receive drag and drop events by default; to enable this
6929     feature, call \c setAcceptDrops(true).
6930 
6931     The default implementation does nothing.
6932 
6933     \sa dragEnterEvent(), dragMoveEvent(), dragLeaveEvent()
6934 */
dropEvent(QGraphicsSceneDragDropEvent * event)6935 void QGraphicsItem::dropEvent(QGraphicsSceneDragDropEvent *event)
6936 {
6937     Q_D(QGraphicsItem);
6938     // binary compatibility workaround between 4.4 and 4.5
6939     if (d->isProxyWidget())
6940         static_cast<QGraphicsProxyWidget*>(this)->dropEvent(event);
6941 }
6942 
6943 /*!
6944     This event handler, for event \a event, can be reimplemented to receive
6945     focus in events for this item. The default implementation calls
6946     ensureVisible().
6947 
6948     \sa focusOutEvent(), sceneEvent(), setFocus()
6949 */
focusInEvent(QFocusEvent * event)6950 void QGraphicsItem::focusInEvent(QFocusEvent *event)
6951 {
6952     Q_UNUSED(event);
6953     update();
6954 }
6955 
6956 /*!
6957     This event handler, for event \a event, can be reimplemented to receive
6958     focus out events for this item. The default implementation does nothing.
6959 
6960     \sa focusInEvent(), sceneEvent(), setFocus()
6961 */
focusOutEvent(QFocusEvent * event)6962 void QGraphicsItem::focusOutEvent(QFocusEvent *event)
6963 {
6964     Q_UNUSED(event);
6965     update();
6966 }
6967 
6968 /*!
6969     This event handler, for event \a event, can be reimplemented to receive
6970     hover enter events for this item. The default implementation calls
6971     update(); otherwise it does nothing.
6972 
6973     Calling QEvent::ignore() or QEvent::accept() on \a event has no effect.
6974 
6975     \sa hoverMoveEvent(), hoverLeaveEvent(), sceneEvent(), setAcceptHoverEvents()
6976 */
hoverEnterEvent(QGraphicsSceneHoverEvent * event)6977 void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
6978 {
6979     Q_UNUSED(event);
6980     update();
6981 }
6982 
6983 /*!
6984     This event handler, for event \a event, can be reimplemented to receive
6985     hover move events for this item. The default implementation does nothing.
6986 
6987     Calling QEvent::ignore() or QEvent::accept() on \a event has no effect.
6988 
6989     \sa hoverEnterEvent(), hoverLeaveEvent(), sceneEvent(), setAcceptHoverEvents()
6990 */
hoverMoveEvent(QGraphicsSceneHoverEvent * event)6991 void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
6992 {
6993     Q_UNUSED(event);
6994 }
6995 
6996 /*!
6997     This event handler, for event \a event, can be reimplemented to receive
6998     hover leave events for this item. The default implementation calls
6999     update(); otherwise it does nothing.
7000 
7001     Calling QEvent::ignore() or QEvent::accept() on \a event has no effect.
7002 
7003     \sa hoverEnterEvent(), hoverMoveEvent(), sceneEvent(), setAcceptHoverEvents()
7004 */
hoverLeaveEvent(QGraphicsSceneHoverEvent * event)7005 void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
7006 {
7007     Q_UNUSED(event);
7008     update();
7009 }
7010 
7011 /*!
7012     This event handler, for event \a event, can be reimplemented to
7013     receive key press events for this item. The default implementation
7014     ignores the event. If you reimplement this handler, the event will by
7015     default be accepted.
7016 
7017     Note that key events are only received for items that set the
7018     ItemIsFocusable flag, and that have keyboard input focus.
7019 
7020     \sa keyReleaseEvent(), setFocus(), QGraphicsScene::setFocusItem(),
7021     sceneEvent()
7022 */
keyPressEvent(QKeyEvent * event)7023 void QGraphicsItem::keyPressEvent(QKeyEvent *event)
7024 {
7025     event->ignore();
7026 }
7027 
7028 /*!
7029     This event handler, for event \a event, can be reimplemented to receive
7030     key release events for this item. The default implementation
7031     ignores the event. If you reimplement this handler, the event will by
7032     default be accepted.
7033 
7034     Note that key events are only received for items that set the
7035     ItemIsFocusable flag, and that have keyboard input focus.
7036 
7037     \sa keyPressEvent(), setFocus(), QGraphicsScene::setFocusItem(),
7038     sceneEvent()
7039 */
keyReleaseEvent(QKeyEvent * event)7040 void QGraphicsItem::keyReleaseEvent(QKeyEvent *event)
7041 {
7042     event->ignore();
7043 }
7044 
7045 /*!
7046     This event handler, for event \a event, can be reimplemented to
7047     receive mouse press events for this item. Mouse press events are
7048     only delivered to items that accept the mouse button that is
7049     pressed. By default, an item accepts all mouse buttons, but you
7050     can change this by calling setAcceptedMouseButtons().
7051 
7052     The mouse press event decides which item should become the mouse
7053     grabber (see QGraphicsScene::mouseGrabberItem()). If you do not
7054     reimplement this function, the press event will propagate to any
7055     topmost item beneath this item, and no other mouse events will be
7056     delivered to this item.
7057 
7058     If you do reimplement this function, \a event will by default be
7059     accepted (see QEvent::accept()), and this item is then the mouse
7060     grabber. This allows the item to receive future move, release and
7061     doubleclick events. If you call QEvent::ignore() on \a event, this
7062     item will lose the mouse grab, and \a event will propagate to any
7063     topmost item beneath. No further mouse events will be delivered to
7064     this item unless a new mouse press event is received.
7065 
7066     The default implementation handles basic item interaction, such as
7067     selection and moving. If you want to keep the base implementation
7068     when reimplementing this function, call
7069     QGraphicsItem::mousePressEvent() in your reimplementation.
7070 
7071     The event is \l{QEvent::ignore()}d for items that are neither
7072     \l{QGraphicsItem::ItemIsMovable}{movable} nor
7073     \l{QGraphicsItem::ItemIsSelectable}{selectable}.
7074 
7075     \sa mouseMoveEvent(), mouseReleaseEvent(),
7076     mouseDoubleClickEvent(), sceneEvent()
7077 */
mousePressEvent(QGraphicsSceneMouseEvent * event)7078 void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
7079 {
7080     if (event->button() == Qt::LeftButton && (flags() & ItemIsSelectable)) {
7081         bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0;
7082         if (!multiSelect) {
7083             if (!d_ptr->selected) {
7084                 if (QGraphicsScene *scene = d_ptr->scene) {
7085                     ++scene->d_func()->selectionChanging;
7086                     scene->clearSelection();
7087                     --scene->d_func()->selectionChanging;
7088                 }
7089                 setSelected(true);
7090             }
7091         }
7092     } else if (!(flags() & ItemIsMovable)) {
7093         event->ignore();
7094     }
7095     if (d_ptr->isWidget) {
7096         // Qt::Popup closes when you click outside.
7097         QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this);
7098         if ((w->windowFlags() & Qt::Popup) == Qt::Popup) {
7099             event->accept();
7100             if (!w->rect().contains(event->pos()))
7101                 w->close();
7102         }
7103     }
7104 }
7105 
7106 /*!
7107     obsolete
7108 */
_qt_movableAncestorIsSelected(const QGraphicsItem * item)7109 bool _qt_movableAncestorIsSelected(const QGraphicsItem *item)
7110 {
7111     const QGraphicsItem *parent = item->parentItem();
7112     return parent && (((parent->flags() & QGraphicsItem::ItemIsMovable) && parent->isSelected()) || _qt_movableAncestorIsSelected(parent));
7113 }
7114 
movableAncestorIsSelected(const QGraphicsItem * item)7115 bool QGraphicsItemPrivate::movableAncestorIsSelected(const QGraphicsItem *item)
7116 {
7117     const QGraphicsItem *parent = item->d_ptr->parent;
7118     return parent && (((parent->flags() & QGraphicsItem::ItemIsMovable) && parent->isSelected()) || _qt_movableAncestorIsSelected(parent));
7119 }
7120 
7121 /*!
7122     This event handler, for event \a event, can be reimplemented to
7123     receive mouse move events for this item. If you do receive this
7124     event, you can be certain that this item also received a mouse
7125     press event, and that this item is the current mouse grabber.
7126 
7127     Calling QEvent::ignore() or QEvent::accept() on \a event has no
7128     effect.
7129 
7130     The default implementation handles basic item interaction, such as
7131     selection and moving. If you want to keep the base implementation
7132     when reimplementing this function, call
7133     QGraphicsItem::mouseMoveEvent() in your reimplementation.
7134 
7135     Please note that mousePressEvent() decides which graphics item it
7136     is that receives mouse events. See the mousePressEvent()
7137     description for details.
7138 
7139     \sa mousePressEvent(), mouseReleaseEvent(),
7140     mouseDoubleClickEvent(), sceneEvent()
7141 */
mouseMoveEvent(QGraphicsSceneMouseEvent * event)7142 void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
7143 {
7144     if ((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable)) {
7145         // Determine the list of items that need to be moved.
7146         QList<QGraphicsItem *> selectedItems;
7147         QMap<QGraphicsItem *, QPointF> initialPositions;
7148         if (d_ptr->scene) {
7149             selectedItems = d_ptr->scene->selectedItems();
7150             initialPositions = d_ptr->scene->d_func()->movingItemsInitialPositions;
7151             if (initialPositions.isEmpty()) {
7152                 foreach (QGraphicsItem *item, selectedItems)
7153                     initialPositions[item] = item->pos();
7154                 initialPositions[this] = pos();
7155             }
7156             d_ptr->scene->d_func()->movingItemsInitialPositions = initialPositions;
7157         }
7158 
7159         // Find the active view.
7160         QGraphicsView *view = 0;
7161         if (event->widget())
7162             view = qobject_cast<QGraphicsView *>(event->widget()->parentWidget());
7163 
7164         // Move all selected items
7165         int i = 0;
7166         bool movedMe = false;
7167         while (i <= selectedItems.size()) {
7168             QGraphicsItem *item = 0;
7169             if (i < selectedItems.size())
7170                 item = selectedItems.at(i);
7171             else
7172                 item = this;
7173             if (item == this) {
7174                 // Slightly clumsy-looking way to ensure that "this" is part
7175                 // of the list of items to move, this is to avoid allocations
7176                 // (appending this item to the list of selected items causes a
7177                 // detach).
7178                 if (movedMe)
7179                     break;
7180                 movedMe = true;
7181             }
7182 
7183             if ((item->flags() & ItemIsMovable) && !QGraphicsItemPrivate::movableAncestorIsSelected(item)) {
7184                 QPointF currentParentPos;
7185                 QPointF buttonDownParentPos;
7186                 if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations) {
7187                     // Items whose ancestors ignore transformations need to
7188                     // map screen coordinates to local coordinates, then map
7189                     // those to the parent.
7190                     QTransform viewToItemTransform = (item->deviceTransform(view->viewportTransform())).inverted();
7191                     currentParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->screenPos()))));
7192                     buttonDownParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton)))));
7193                 } else if (item->flags() & ItemIgnoresTransformations) {
7194                     // Root items that ignore transformations need to
7195                     // calculate their diff by mapping viewport coordinates
7196                     // directly to parent coordinates.
7197                     // COMBINE
7198                     QTransform itemTransform;
7199                     if (item->d_ptr->transformData)
7200                         itemTransform = item->d_ptr->transformData->computedFullTransform();
7201                     itemTransform.translate(item->d_ptr->pos.x(), item->d_ptr->pos.y());
7202                     QTransform viewToParentTransform = itemTransform
7203                                                        * (item->sceneTransform() * view->viewportTransform()).inverted();
7204                     currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos())));
7205                     buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton))));
7206                 } else {
7207                     // All other items simply map from the scene.
7208                     currentParentPos = item->mapToParent(item->mapFromScene(event->scenePos()));
7209                     buttonDownParentPos = item->mapToParent(item->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)));
7210                 }
7211 
7212                 item->setPos(initialPositions.value(item) + currentParentPos - buttonDownParentPos);
7213 
7214                 if (item->flags() & ItemIsSelectable)
7215                     item->setSelected(true);
7216             }
7217             ++i;
7218         }
7219 
7220     } else {
7221         event->ignore();
7222     }
7223 }
7224 
7225 /*!
7226     This event handler, for event \a event, can be reimplemented to
7227     receive mouse release events for this item.
7228 
7229     Calling QEvent::ignore() or QEvent::accept() on \a event has no
7230     effect.
7231 
7232     The default implementation handles basic item interaction, such as
7233     selection and moving. If you want to keep the base implementation
7234     when reimplementing this function, call
7235     QGraphicsItem::mouseReleaseEvent() in your reimplementation.
7236 
7237     Please note that mousePressEvent() decides which graphics item it
7238     is that receives mouse events. See the mousePressEvent()
7239     description for details.
7240 
7241     \sa mousePressEvent(), mouseMoveEvent(), mouseDoubleClickEvent(),
7242     sceneEvent()
7243 */
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)7244 void QGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
7245 {
7246     if (event->button() == Qt::LeftButton && (flags() & ItemIsSelectable)) {
7247         bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0;
7248         if (event->scenePos() == event->buttonDownScenePos(Qt::LeftButton)) {
7249             // The item didn't move
7250             if (multiSelect) {
7251                 setSelected(!isSelected());
7252             } else {
7253                 bool selectionChanged = false;
7254                 if (QGraphicsScene *scene = d_ptr->scene) {
7255                     ++scene->d_func()->selectionChanging;
7256                     // Clear everything but this item. Bypass
7257                     // QGraphicsScene::clearSelection()'s default behavior by
7258                     // temporarily removing this item from the selection list.
7259                     if (d_ptr->selected) {
7260                         scene->d_func()->selectedItems.remove(this);
7261                         foreach (QGraphicsItem *item, scene->d_func()->selectedItems) {
7262                             if (item->isSelected()) {
7263                                 selectionChanged = true;
7264                                 break;
7265                             }
7266                         }
7267                     }
7268                     scene->clearSelection();
7269                     if (d_ptr->selected)
7270                         scene->d_func()->selectedItems.insert(this);
7271                     --scene->d_func()->selectionChanging;
7272                     if (selectionChanged)
7273                         emit d_ptr->scene->selectionChanged();
7274                 }
7275                 setSelected(true);
7276             }
7277         }
7278     }
7279     if (d_ptr->scene && !event->buttons())
7280         d_ptr->scene->d_func()->movingItemsInitialPositions.clear();
7281 }
7282 
7283 /*!
7284     This event handler, for event \a event, can be reimplemented to
7285     receive mouse doubleclick events for this item.
7286 
7287     When doubleclicking an item, the item will first receive a mouse
7288     press event, followed by a release event (i.e., a click), then a
7289     doubleclick event, and finally a release event.
7290 
7291     Calling QEvent::ignore() or QEvent::accept() on \a event has no
7292     effect.
7293 
7294     The default implementation calls mousePressEvent(). If you want to
7295     keep the base implementation when reimplementing this function,
7296     call QGraphicsItem::mouseDoubleClickEvent() in your
7297     reimplementation.
7298 
7299     Note that an item will not receive double click events if it is
7300     neither \l {QGraphicsItem::ItemIsSelectable}{selectable} nor
7301     \l{QGraphicsItem::ItemIsMovable}{movable} (single mouse clicks are
7302     ignored in this case, and that stops the generation of double
7303     clicks).
7304 
7305     \sa mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), sceneEvent()
7306 */
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)7307 void QGraphicsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
7308 {
7309     mousePressEvent(event);
7310 }
7311 
7312 /*!
7313     This event handler, for event \a event, can be reimplemented to receive
7314     wheel events for this item. If you reimplement this function, \a event
7315     will be accepted by default.
7316 
7317     If you ignore the event, (i.e., by calling QEvent::ignore(),) it will
7318     propagate to any item beneath this item. If no items accept the event, it
7319     will be ignored by the scene, and propagate to the view (e.g., the view's
7320     vertical scroll bar).
7321 
7322     The default implementation ignores the event.
7323 
7324     \sa sceneEvent()
7325 */
wheelEvent(QGraphicsSceneWheelEvent * event)7326 void QGraphicsItem::wheelEvent(QGraphicsSceneWheelEvent *event)
7327 {
7328     event->ignore();
7329 }
7330 
7331 /*!
7332     This event handler, for event \a event, can be reimplemented to receive
7333     input method events for this item. The default implementation ignores the
7334     event.
7335 
7336     \sa inputMethodQuery(), sceneEvent()
7337 */
inputMethodEvent(QInputMethodEvent * event)7338 void QGraphicsItem::inputMethodEvent(QInputMethodEvent *event)
7339 {
7340     event->ignore();
7341 }
7342 
7343 /*!
7344     This method is only relevant for input items. It is used by the
7345     input method to query a set of properties of the item to be able
7346     to support complex input method operations, such as support for
7347     surrounding text and reconversions. \a query specifies which
7348     property is queried.
7349 
7350     \sa inputMethodEvent(), QInputMethodEvent, QInputContext
7351 */
inputMethodQuery(Qt::InputMethodQuery query) const7352 QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const
7353 {
7354     if (isWidget()) {
7355         // ### Qt 5: Remove. The reimplementation in
7356         // QGraphicsProxyWidget solves this problem (but requires a
7357         // recompile to take effect).
7358         return d_ptr->inputMethodQueryHelper(query);
7359     }
7360 
7361     Q_UNUSED(query);
7362     return QVariant();
7363 }
7364 
7365 /*!
7366     Returns the current input method hints of this item.
7367 
7368     Input method hints are only relevant for input items.
7369     The hints are used by the input method to indicate how it should operate.
7370     For example, if the Qt::ImhNumbersOnly flag is set, the input method may change
7371     its visual components to reflect that only numbers can be entered.
7372 
7373     The effect may vary between input method implementations.
7374 
7375     \since 4.6
7376 
7377     \sa setInputMethodHints(), inputMethodQuery(), QInputContext
7378 */
inputMethodHints() const7379 Qt::InputMethodHints QGraphicsItem::inputMethodHints() const
7380 {
7381     Q_D(const QGraphicsItem);
7382     return d->imHints;
7383 }
7384 
7385 /*!
7386     Sets the current input method hints of this item to \a hints.
7387 
7388     \since 4.6
7389 
7390     \sa inputMethodHints(), inputMethodQuery(), QInputContext
7391 */
setInputMethodHints(Qt::InputMethodHints hints)7392 void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
7393 {
7394     Q_D(QGraphicsItem);
7395     d->imHints = hints;
7396     if (!hasFocus())
7397         return;
7398     d->scene->d_func()->updateInputMethodSensitivityInViews();
7399 #if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
7400     QWidget *fw = QApplication::focusWidget();
7401     if (!fw)
7402         return;
7403     for (int i = 0 ; i < scene()->views().count() ; ++i)
7404         if (scene()->views().at(i) == fw)
7405             if (QInputContext *inputContext = fw->inputContext())
7406                 inputContext->update();
7407 #endif
7408 }
7409 
7410 /*!
7411     Updates the item's micro focus.
7412 
7413     \since 4.7
7414 
7415     \sa QInputContext
7416 */
updateMicroFocus()7417 void QGraphicsItem::updateMicroFocus()
7418 {
7419 #if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
7420     if (QWidget *fw = QApplication::focusWidget()) {
7421         if (scene()) {
7422             for (int i = 0 ; i < scene()->views().count() ; ++i) {
7423                 if (scene()->views().at(i) == fw) {
7424                     if (QInputContext *inputContext = fw->inputContext()) {
7425                         inputContext->update();
7426 #ifndef QT_NO_ACCESSIBILITY
7427                         // ##### is this correct
7428                         if (toGraphicsObject())
7429                             QAccessible::updateAccessibility(toGraphicsObject(), 0, QAccessible::StateChanged);
7430 #endif
7431                         break;
7432                     }
7433                 }
7434             }
7435         }
7436     }
7437 #endif
7438 }
7439 
7440 /*!
7441     This virtual function is called by QGraphicsItem to notify custom items
7442     that some part of the item's state changes. By reimplementing this
7443     function, your can react to a change, and in some cases, (depending on \a
7444     change,) adjustments can be made.
7445 
7446     \a change is the parameter of the item that is changing. \a value is the
7447     new value; the type of the value depends on \a change.
7448 
7449     Example:
7450 
7451     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 15
7452 
7453     The default implementation does nothing, and returns \a value.
7454 
7455     Note: Certain QGraphicsItem functions cannot be called in a
7456     reimplementation of this function; see the GraphicsItemChange
7457     documentation for details.
7458 
7459     \sa GraphicsItemChange
7460 */
itemChange(GraphicsItemChange change,const QVariant & value)7461 QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
7462 {
7463     Q_UNUSED(change);
7464     return value;
7465 }
7466 
7467 /*!
7468     \internal
7469 
7470     Note: This is provided as a hook to avoid future problems related
7471     to adding virtual functions.
7472 */
supportsExtension(Extension extension) const7473 bool QGraphicsItem::supportsExtension(Extension extension) const
7474 {
7475     Q_UNUSED(extension);
7476     return false;
7477 }
7478 
7479 /*!
7480     \internal
7481 
7482     Note: This is provided as a hook to avoid future problems related
7483     to adding virtual functions.
7484 */
setExtension(Extension extension,const QVariant & variant)7485 void QGraphicsItem::setExtension(Extension extension, const QVariant &variant)
7486 {
7487     Q_UNUSED(extension);
7488     Q_UNUSED(variant);
7489 }
7490 
7491 /*!
7492     \internal
7493 
7494     Note: This is provided as a hook to avoid future problems related
7495     to adding virtual functions.
7496 */
extension(const QVariant & variant) const7497 QVariant QGraphicsItem::extension(const QVariant &variant) const
7498 {
7499     Q_UNUSED(variant);
7500     return QVariant();
7501 }
7502 
7503 /*!
7504     \internal
7505 
7506     Adds this item to the scene's index. Called in conjunction with
7507     removeFromIndex() to ensure the index bookkeeping is correct when
7508     the item's position, transformation or shape changes.
7509 */
addToIndex()7510 void QGraphicsItem::addToIndex()
7511 {
7512     if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
7513         // ### add to child index only if applicable
7514         return;
7515     }
7516     if (d_ptr->scene)
7517         d_ptr->scene->d_func()->index->addItem(this);
7518 }
7519 
7520 /*!
7521     \internal
7522 
7523     Removes this item from the scene's index. Called in conjunction
7524     with addToIndex() to ensure the index bookkeeping is correct when
7525     the item's position, transformation or shape changes.
7526 */
removeFromIndex()7527 void QGraphicsItem::removeFromIndex()
7528 {
7529     if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
7530         // ### remove from child index only if applicable
7531         return;
7532     }
7533     if (d_ptr->scene)
7534         d_ptr->scene->d_func()->index->removeItem(this);
7535 }
7536 
7537 /*!
7538     Prepares the item for a geometry change. Call this function before
7539     changing the bounding rect of an item to keep QGraphicsScene's index up to
7540     date.
7541 
7542     prepareGeometryChange() will call update() if this is necessary.
7543 
7544     Example:
7545 
7546     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 16
7547 
7548     \sa boundingRect()
7549 */
prepareGeometryChange()7550 void QGraphicsItem::prepareGeometryChange()
7551 {
7552     if (d_ptr->inDestructor)
7553         return;
7554     if (d_ptr->scene) {
7555         d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true;
7556         d_ptr->geometryChanged = 1;
7557         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
7558         d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
7559 
7560         QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
7561         scenePrivate->index->prepareBoundingRectChange(this);
7562         scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*force=*/false,
7563                                 /*ignoreOpacity=*/ false, /*removingItemFromScene=*/ false,
7564                                 /*updateBoundingRect=*/true);
7565 
7566         // For compatibility reasons, we have to update the item's old geometry
7567         // if someone is connected to the changed signal or the scene has no views.
7568         // Note that this has to be done *after* markDirty to ensure that
7569         // _q_processDirtyItems is called before _q_emitUpdated.
7570         if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex)
7571             || scenePrivate->views.isEmpty()) {
7572             if (d_ptr->hasTranslateOnlySceneTransform()) {
7573                 d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(),
7574                                                                d_ptr->sceneTransform.dy()));
7575             } else {
7576                 d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect()));
7577             }
7578         }
7579     }
7580 
7581     d_ptr->markParentDirty(/*updateBoundingRect=*/true);
7582 }
7583 
7584 /*!
7585     \internal
7586 
7587     Highlights \a item as selected.
7588 
7589     NOTE: This function is a duplicate of qt_graphicsItem_highlightSelected() in
7590           qgraphicssvgitem.cpp!
7591 */
qt_graphicsItem_highlightSelected(QGraphicsItem * item,QPainter * painter,const QStyleOptionGraphicsItem * option)7592 static void qt_graphicsItem_highlightSelected(
7593     QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
7594 {
7595     const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
7596     if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
7597         return;
7598 
7599     const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
7600     if (qMin(mbrect.width(), mbrect.height()) < qreal(1.0))
7601         return;
7602 
7603     qreal itemPenWidth;
7604     switch (item->type()) {
7605         case QGraphicsEllipseItem::Type:
7606             itemPenWidth = static_cast<QGraphicsEllipseItem *>(item)->pen().widthF();
7607             break;
7608         case QGraphicsPathItem::Type:
7609             itemPenWidth = static_cast<QGraphicsPathItem *>(item)->pen().widthF();
7610             break;
7611         case QGraphicsPolygonItem::Type:
7612             itemPenWidth = static_cast<QGraphicsPolygonItem *>(item)->pen().widthF();
7613             break;
7614         case QGraphicsRectItem::Type:
7615             itemPenWidth = static_cast<QGraphicsRectItem *>(item)->pen().widthF();
7616             break;
7617         case QGraphicsSimpleTextItem::Type:
7618             itemPenWidth = static_cast<QGraphicsSimpleTextItem *>(item)->pen().widthF();
7619             break;
7620         case QGraphicsLineItem::Type:
7621             itemPenWidth = static_cast<QGraphicsLineItem *>(item)->pen().widthF();
7622             break;
7623         default:
7624             itemPenWidth = 1.0;
7625     }
7626     const qreal pad = itemPenWidth / 2;
7627 
7628     const qreal penWidth = 0; // cosmetic pen
7629 
7630     const QColor fgcolor = option->palette.windowText().color();
7631     const QColor bgcolor( // ensure good contrast against fgcolor
7632         fgcolor.red()   > 127 ? 0 : 255,
7633         fgcolor.green() > 127 ? 0 : 255,
7634         fgcolor.blue()  > 127 ? 0 : 255);
7635 
7636     painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine));
7637     painter->setBrush(Qt::NoBrush);
7638     painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
7639 
7640     painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
7641     painter->setBrush(Qt::NoBrush);
7642     painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
7643 }
7644 
7645 /*!
7646     \class QGraphicsObject
7647     \brief The QGraphicsObject class provides a base class for all graphics items that
7648     require signals, slots and properties.
7649     \since 4.6
7650     \ingroup graphicsview-api
7651 
7652     The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms.
7653     It maps many of QGraphicsItem's basic setters and getters to properties and adds notification
7654     signals for many of them.
7655 
7656     \section1 Parents and Children
7657 
7658     Each graphics object can be constructed with a parent item. This ensures that the
7659     item will be destroyed when its parent item is destroyed. Although QGraphicsObject
7660     inherits from both QObject and QGraphicsItem, you should use the functions provided
7661     by QGraphicsItem, \e not QObject, to manage the relationships between parent and
7662     child items.
7663 
7664     The relationships between items can be explored using the parentItem() and childItems()
7665     functions. In the hierarchy of items in a scene, the parentObject() and parentWidget()
7666     functions are the equivalent of the QWidget::parent() and QWidget::parentWidget()
7667     functions for QWidget subclasses.
7668 
7669     \sa QGraphicsWidget
7670 */
7671 
7672 /*!
7673     Constructs a QGraphicsObject with \a parent.
7674 */
QGraphicsObject(QGraphicsItem * parent)7675 QGraphicsObject::QGraphicsObject(QGraphicsItem *parent)
7676         : QGraphicsItem(parent)
7677 {
7678     QGraphicsItem::d_ptr->isObject = true;
7679 }
7680 
7681 /*!
7682   \internal
7683 */
QGraphicsObject(QGraphicsItemPrivate & dd,QGraphicsItem * parent,QGraphicsScene * scene)7684 QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene)
7685     : QGraphicsItem(dd, parent, scene)
7686 {
7687     QGraphicsItem::d_ptr->isObject = true;
7688 }
7689 
7690 #ifndef QT_NO_GESTURES
7691 /*!
7692     Subscribes the graphics object to the given \a gesture with specific \a flags.
7693 
7694     \sa ungrabGesture(), QGestureEvent
7695 */
grabGesture(Qt::GestureType gesture,Qt::GestureFlags flags)7696 void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
7697 {
7698     bool contains = QGraphicsItem::d_ptr->gestureContext.contains(gesture);
7699     QGraphicsItem::d_ptr->gestureContext.insert(gesture, flags);
7700     if (!contains && QGraphicsItem::d_ptr->scene)
7701         QGraphicsItem::d_ptr->scene->d_func()->grabGesture(this, gesture);
7702 }
7703 
7704 /*!
7705     Unsubscribes the graphics object from the given \a gesture.
7706 
7707     \sa grabGesture(), QGestureEvent
7708 */
ungrabGesture(Qt::GestureType gesture)7709 void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
7710 {
7711     if (QGraphicsItem::d_ptr->gestureContext.remove(gesture) && QGraphicsItem::d_ptr->scene)
7712         QGraphicsItem::d_ptr->scene->d_func()->ungrabGesture(this, gesture);
7713 }
7714 #endif // QT_NO_GESTURES
7715 
7716 /*!
7717     Updates the item's micro focus. This is slot for convenience.
7718 
7719     \since 4.7
7720 
7721     \sa QInputContext
7722 */
updateMicroFocus()7723 void QGraphicsObject::updateMicroFocus()
7724 {
7725     QGraphicsItem::updateMicroFocus();
7726 }
7727 
children_append(QDeclarativeListProperty<QGraphicsObject> * list,QGraphicsObject * item)7728 void QGraphicsItemPrivate::children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item)
7729 {
7730     if (item) {
7731         QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(list->object);
7732         if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) {
7733             item->setParentItem(graphicsObject);
7734         } else {
7735             QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0);
7736         }
7737     }
7738 }
7739 
children_count(QDeclarativeListProperty<QGraphicsObject> * list)7740 int QGraphicsItemPrivate::children_count(QDeclarativeListProperty<QGraphicsObject> *list)
7741 {
7742     QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
7743     return d->children.count();
7744 }
7745 
children_at(QDeclarativeListProperty<QGraphicsObject> * list,int index)7746 QGraphicsObject *QGraphicsItemPrivate::children_at(QDeclarativeListProperty<QGraphicsObject> *list, int index)
7747 {
7748     QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
7749     if (index >= 0 && index < d->children.count())
7750         return d->children.at(index)->toGraphicsObject();
7751     else
7752         return 0;
7753 }
7754 
children_clear(QDeclarativeListProperty<QGraphicsObject> * list)7755 void QGraphicsItemPrivate::children_clear(QDeclarativeListProperty<QGraphicsObject> *list)
7756 {
7757     QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
7758     int childCount = d->children.count();
7759     if (d->sendParentChangeNotification) {
7760         for (int index = 0; index < childCount; index++)
7761             d->children.at(0)->setParentItem(0);
7762     } else {
7763         for (int index = 0; index < childCount; index++)
7764             QGraphicsItemPrivate::get(d->children.at(0))->setParentItemHelper(0, 0, 0);
7765     }
7766 }
7767 
7768 /*!
7769     Returns a list of this item's children.
7770 
7771     The items are sorted by stacking order. This takes into account both the
7772     items' insertion order and their Z-values.
7773 
7774 */
childrenList()7775 QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList()
7776 {
7777     Q_Q(QGraphicsItem);
7778     if (isObject) {
7779         QGraphicsObject *that = static_cast<QGraphicsObject *>(q);
7780         return QDeclarativeListProperty<QGraphicsObject>(that, &children, children_append,
7781                                                          children_count, children_at, children_clear);
7782     } else {
7783         //QGraphicsItem is not supported for this property
7784         return QDeclarativeListProperty<QGraphicsObject>();
7785     }
7786 }
7787 
7788 /*!
7789   \internal
7790   Returns the width of the item
7791   Reimplemented by QGraphicsWidget
7792 */
width() const7793 qreal QGraphicsItemPrivate::width() const
7794 {
7795     return 0;
7796 }
7797 
7798 /*!
7799   \internal
7800   Set the width of the item
7801   Reimplemented by QGraphicsWidget
7802 */
setWidth(qreal w)7803 void QGraphicsItemPrivate::setWidth(qreal w)
7804 {
7805     Q_UNUSED(w);
7806 }
7807 
7808 /*!
7809   \internal
7810   Reset the width of the item
7811   Reimplemented by QGraphicsWidget
7812 */
resetWidth()7813 void QGraphicsItemPrivate::resetWidth()
7814 {
7815 }
7816 
7817 /*!
7818   \internal
7819   Returns the height of the item
7820   Reimplemented by QGraphicsWidget
7821 */
height() const7822 qreal QGraphicsItemPrivate::height() const
7823 {
7824     return 0;
7825 }
7826 
7827 /*!
7828   \internal
7829   Set the height of the item
7830   Reimplemented by QGraphicsWidget
7831 */
setHeight(qreal h)7832 void QGraphicsItemPrivate::setHeight(qreal h)
7833 {
7834     Q_UNUSED(h);
7835 }
7836 
7837 /*!
7838   \internal
7839   Reset the height of the item
7840   Reimplemented by QGraphicsWidget
7841 */
resetHeight()7842 void QGraphicsItemPrivate::resetHeight()
7843 {
7844 }
7845 
7846 /*!
7847     \property QGraphicsObject::children
7848     \since 4.7
7849     \internal
7850 */
7851 
7852 /*!
7853     \property QGraphicsObject::width
7854     \since 4.7
7855     \internal
7856 */
7857 
7858 /*!
7859     \property QGraphicsObject::height
7860     \since 4.7
7861     \internal
7862 */
7863 
7864 /*!
7865   \property QGraphicsObject::parent
7866   \brief the parent of the item
7867 
7868   \note The item's parent is set independently of the parent object returned
7869   by QObject::parent().
7870 
7871   \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject()
7872 */
7873 
7874 /*!
7875   \property QGraphicsObject::opacity
7876   \brief the opacity of the item
7877 
7878   \sa QGraphicsItem::setOpacity(), QGraphicsItem::opacity()
7879 */
7880 
7881 /*!
7882   \fn QGraphicsObject::opacityChanged()
7883 
7884   This signal gets emitted whenever the opacity of the item changes
7885 
7886   \sa QGraphicsItem::opacity()
7887 */
7888 
7889 /*!
7890   \fn QGraphicsObject::parentChanged()
7891 
7892   This signal gets emitted whenever the parent of the item changes
7893 */
7894 
7895 /*!
7896   \property QGraphicsObject::pos
7897   \brief the position of the item
7898 
7899   Describes the items position.
7900 
7901   \sa QGraphicsItem::setPos(), QGraphicsItem::pos()
7902 */
7903 
7904 /*!
7905   \property QGraphicsObject::x
7906   \brief the x position of the item
7907 
7908   Describes the items x position.
7909 
7910   \sa QGraphicsItem::setX(), setPos(), xChanged()
7911 */
7912 
7913 /*!
7914   \fn QGraphicsObject::xChanged()
7915 
7916   This signal gets emitted whenever the x position of the item changes
7917 
7918   \sa pos()
7919 */
7920 
7921 /*!
7922   \property QGraphicsObject::y
7923   \brief the y position of the item
7924 
7925   Describes the items y position.
7926 
7927   \sa QGraphicsItem::setY(), setPos(), yChanged()
7928 */
7929 
7930 /*!
7931   \fn QGraphicsObject::yChanged()
7932 
7933   This signal gets emitted whenever the y position of the item changes.
7934 
7935   \sa pos()
7936 */
7937 
7938 /*!
7939   \property QGraphicsObject::z
7940   \brief the z value of the item
7941 
7942   Describes the items z value.
7943 
7944   \sa QGraphicsItem::setZValue(), zValue(), zChanged()
7945 */
7946 
7947 /*!
7948   \fn QGraphicsObject::zChanged()
7949 
7950   This signal gets emitted whenever the z value of the item changes.
7951 
7952   \sa pos()
7953 */
7954 
7955 /*!
7956   \property QGraphicsObject::rotation
7957   This property holds the rotation of the item in degrees.
7958 
7959   This specifies how many degrees to rotate the item around its transformOrigin.
7960   The default rotation is 0 degrees (i.e. not rotated at all).
7961 */
7962 
7963 /*!
7964   \fn QGraphicsObject::rotationChanged()
7965 
7966   This signal gets emitted whenever the roation of the item changes.
7967 */
7968 
7969 /*!
7970   \property QGraphicsObject::scale
7971   This property holds the scale of the item.
7972 
7973   A scale of less than 1 means the item will be displayed smaller than
7974   normal, and a scale of greater than 1 means the item will be
7975   displayed larger than normal.  A negative scale means the item will
7976   be mirrored.
7977 
7978   By default, items are displayed at a scale of 1 (i.e. at their
7979   normal size).
7980 
7981   Scaling is from the item's transformOrigin.
7982 */
7983 
7984 /*!
7985   \fn void QGraphicsObject::scaleChanged()
7986 
7987   This signal is emitted when the scale of the item changes.
7988 */
7989 
7990 
7991 /*!
7992   \property QGraphicsObject::enabled
7993   \brief whether the item is enabled or not
7994 
7995   This property is declared in QGraphicsItem.
7996 
7997   By default, this property is true.
7998 
7999   \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
8000   \sa QGraphicsObject::enabledChanged()
8001 */
8002 
8003 /*!
8004   \fn void QGraphicsObject::enabledChanged()
8005 
8006   This signal gets emitted whenever the item get's enabled or disabled.
8007 
8008   \sa isEnabled()
8009 */
8010 
8011 /*!
8012   \property QGraphicsObject::visible
8013   \brief whether the item is visible or not
8014 
8015   This property is declared in QGraphicsItem.
8016 
8017   By default, this property is true.
8018 
8019   \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), visibleChanged()
8020 */
8021 
8022 /*!
8023   \fn QGraphicsObject::visibleChanged()
8024 
8025   This signal gets emitted whenever the visibility of the item changes
8026 
8027   \sa visible
8028 */
8029 
8030 /*!
8031   \fn const QObjectList &QGraphicsObject::children() const
8032   \internal
8033 
8034   This function returns the same value as QObject::children(). It's
8035   provided to differentiate between the obsolete member
8036   QGraphicsItem::children() and QObject::children(). QGraphicsItem now
8037   provides childItems() instead.
8038 */
8039 
8040 /*!
8041   \property QGraphicsObject::transformOriginPoint
8042   \brief the transformation origin
8043 
8044   This property sets a specific point in the items coordiante system as the
8045   origin for scale and rotation.
8046 
8047   \sa scale, rotation, QGraphicsItem::transformOriginPoint()
8048 */
8049 
8050 /*!
8051     \fn void QGraphicsObject::widthChanged()
8052     \internal
8053 */
8054 
8055 /*!
8056     \fn void QGraphicsObject::heightChanged()
8057     \internal
8058 */
8059 
8060 /*!
8061 
8062   \fn QGraphicsObject::childrenChanged()
8063 
8064   This signal gets emitted whenever the children list changes
8065   \internal
8066 */
8067 
8068 /*!
8069   \property QGraphicsObject::effect
8070   \since 4.7
8071   \brief the effect attached to this item
8072 
8073   \sa QGraphicsItem::setGraphicsEffect(), QGraphicsItem::graphicsEffect()
8074 */
8075 
8076 /*!
8077     \class QAbstractGraphicsShapeItem
8078     \brief The QAbstractGraphicsShapeItem class provides a common base for
8079     all path items.
8080     \since 4.2
8081     \ingroup graphicsview-api
8082 
8083     This class does not fully implement an item by itself; in particular, it
8084     does not implement boundingRect() and paint(), which are inherited by
8085     QGraphicsItem.
8086 
8087     You can subclass this item to provide a simple base implementation of
8088     accessors for the item's pen and brush.
8089 
8090     \sa QGraphicsRectItem, QGraphicsEllipseItem, QGraphicsPathItem,
8091     QGraphicsPolygonItem, QGraphicsTextItem, QGraphicsLineItem,
8092     QGraphicsPixmapItem, {Graphics View Framework}
8093 */
8094 
8095 class QAbstractGraphicsShapeItemPrivate : public QGraphicsItemPrivate
8096 {
8097     Q_DECLARE_PUBLIC(QAbstractGraphicsShapeItem)
8098 public:
8099 
8100     QBrush brush;
8101     QPen pen;
8102 
8103     // Cached bounding rectangle
8104     mutable QRectF boundingRect;
8105 };
8106 
8107 /*!
8108     Constructs a QAbstractGraphicsShapeItem. \a parent is passed to
8109     QGraphicsItem's constructor.
8110 */
QAbstractGraphicsShapeItem(QGraphicsItem * parent,QGraphicsScene * scene)8111 QAbstractGraphicsShapeItem::QAbstractGraphicsShapeItem(QGraphicsItem *parent
8112 #ifndef Q_QDOC
8113                                                        // obsolete argument
8114                                                        , QGraphicsScene *scene
8115 #endif
8116     )
8117     : QGraphicsItem(*new QAbstractGraphicsShapeItemPrivate, parent, scene)
8118 {
8119 }
8120 
8121 /*!
8122     \internal
8123 */
QAbstractGraphicsShapeItem(QAbstractGraphicsShapeItemPrivate & dd,QGraphicsItem * parent,QGraphicsScene * scene)8124 QAbstractGraphicsShapeItem::QAbstractGraphicsShapeItem(QAbstractGraphicsShapeItemPrivate &dd,
8125                                                      QGraphicsItem *parent,
8126                                                      QGraphicsScene *scene)
8127     : QGraphicsItem(dd, parent, scene)
8128 {
8129 }
8130 
8131 /*!
8132     Destroys a QAbstractGraphicsShapeItem.
8133 */
~QAbstractGraphicsShapeItem()8134 QAbstractGraphicsShapeItem::~QAbstractGraphicsShapeItem()
8135 {
8136 }
8137 
8138 /*!
8139     Returns the item's pen. If no pen has been set, this function returns
8140     QPen(), a default black solid line pen with 0 width.
8141 */
pen() const8142 QPen QAbstractGraphicsShapeItem::pen() const
8143 {
8144     Q_D(const QAbstractGraphicsShapeItem);
8145     return d->pen;
8146 }
8147 
8148 /*!
8149     Sets the pen for this item to \a pen.
8150 
8151     The pen is used to draw the item's outline.
8152 
8153     \sa pen()
8154 */
setPen(const QPen & pen)8155 void QAbstractGraphicsShapeItem::setPen(const QPen &pen)
8156 {
8157     Q_D(QAbstractGraphicsShapeItem);
8158     if (d->pen == pen)
8159         return;
8160     prepareGeometryChange();
8161     d->pen = pen;
8162     d->boundingRect = QRectF();
8163     update();
8164 }
8165 
8166 /*!
8167     Returns the item's brush, or an empty brush if no brush has been set.
8168 
8169     \sa setBrush()
8170 */
brush() const8171 QBrush QAbstractGraphicsShapeItem::brush() const
8172 {
8173     Q_D(const QAbstractGraphicsShapeItem);
8174     return d->brush;
8175 }
8176 
8177 /*!
8178     Sets the item's brush to \a brush.
8179 
8180     The item's brush is used to fill the item.
8181 
8182     If you use a brush with a QGradient, the gradient
8183     is relative to the item's coordinate system.
8184 
8185     \sa brush()
8186 */
setBrush(const QBrush & brush)8187 void QAbstractGraphicsShapeItem::setBrush(const QBrush &brush)
8188 {
8189     Q_D(QAbstractGraphicsShapeItem);
8190     if (d->brush == brush)
8191         return;
8192     d->brush = brush;
8193     update();
8194 }
8195 
8196 /*!
8197     \reimp
8198 */
isObscuredBy(const QGraphicsItem * item) const8199 bool QAbstractGraphicsShapeItem::isObscuredBy(const QGraphicsItem *item) const
8200 {
8201     return QGraphicsItem::isObscuredBy(item);
8202 }
8203 
8204 /*!
8205     \reimp
8206 */
opaqueArea() const8207 QPainterPath QAbstractGraphicsShapeItem::opaqueArea() const
8208 {
8209     Q_D(const QAbstractGraphicsShapeItem);
8210     if (d->brush.isOpaque())
8211         return isClipped() ? clipPath() : shape();
8212     return QGraphicsItem::opaqueArea();
8213 }
8214 
8215 /*!
8216     \class QGraphicsPathItem
8217     \brief The QGraphicsPathItem class provides a path item that you
8218     can add to a QGraphicsScene.
8219     \since 4.2
8220     \ingroup graphicsview-api
8221 
8222     To set the item's path, pass a QPainterPath to QGraphicsPathItem's
8223     constructor, or call the setPath() function. The path() function
8224     returns the current path.
8225 
8226     \image graphicsview-pathitem.png
8227 
8228     QGraphicsPathItem uses the path to provide a reasonable
8229     implementation of boundingRect(), shape(), and contains(). The
8230     paint() function draws the path using the item's associated pen
8231     and brush, which you can set by calling the setPen() and
8232     setBrush() functions.
8233 
8234     \sa QGraphicsRectItem, QGraphicsEllipseItem, QGraphicsPolygonItem,
8235     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
8236     View Framework}
8237 */
8238 
8239 class QGraphicsPathItemPrivate : public QAbstractGraphicsShapeItemPrivate
8240 {
8241     Q_DECLARE_PUBLIC(QGraphicsPathItem)
8242 public:
8243     QPainterPath path;
8244 };
8245 
8246 /*!
8247     Constructs a QGraphicsPath item using \a path as the default path. \a
8248     parent is passed to QAbstractGraphicsShapeItem's constructor.
8249 
8250     \sa QGraphicsScene::addItem()
8251 */
QGraphicsPathItem(const QPainterPath & path,QGraphicsItem * parent,QGraphicsScene * scene)8252 QGraphicsPathItem::QGraphicsPathItem(const QPainterPath &path,
8253                                      QGraphicsItem *parent
8254 #ifndef Q_QDOC
8255                                      // obsolete argument
8256                                      , QGraphicsScene *scene
8257 #endif
8258     )
8259     : QAbstractGraphicsShapeItem(*new QGraphicsPathItemPrivate, parent, scene)
8260 {
8261     if (!path.isEmpty())
8262         setPath(path);
8263 }
8264 
8265 /*!
8266     Constructs a QGraphicsPath. \a parent is passed to
8267     QAbstractGraphicsShapeItem's constructor.
8268 
8269     \sa QGraphicsScene::addItem()
8270 */
QGraphicsPathItem(QGraphicsItem * parent,QGraphicsScene * scene)8271 QGraphicsPathItem::QGraphicsPathItem(QGraphicsItem *parent
8272 #ifndef Q_QDOC
8273                                      // obsolete argument
8274                                      , QGraphicsScene *scene
8275 #endif
8276     )
8277     : QAbstractGraphicsShapeItem(*new QGraphicsPathItemPrivate, parent, scene)
8278 {
8279 }
8280 
8281 /*!
8282     Destroys the QGraphicsPathItem.
8283 */
~QGraphicsPathItem()8284 QGraphicsPathItem::~QGraphicsPathItem()
8285 {
8286 }
8287 
8288 /*!
8289     Returns the item's path as a QPainterPath. If no item has been set, an
8290     empty QPainterPath is returned.
8291 
8292     \sa setPath()
8293 */
path() const8294 QPainterPath QGraphicsPathItem::path() const
8295 {
8296     Q_D(const QGraphicsPathItem);
8297     return d->path;
8298 }
8299 
8300 /*!
8301     Sets the item's path to be the given \a path.
8302 
8303     \sa path()
8304 */
setPath(const QPainterPath & path)8305 void QGraphicsPathItem::setPath(const QPainterPath &path)
8306 {
8307     Q_D(QGraphicsPathItem);
8308     if (d->path == path)
8309         return;
8310     prepareGeometryChange();
8311     d->path = path;
8312     d->boundingRect = QRectF();
8313     update();
8314 }
8315 
8316 /*!
8317     \reimp
8318 */
boundingRect() const8319 QRectF QGraphicsPathItem::boundingRect() const
8320 {
8321     Q_D(const QGraphicsPathItem);
8322     if (d->boundingRect.isNull()) {
8323         qreal pw = pen().widthF();
8324         if (pw == 0.0)
8325             d->boundingRect = d->path.controlPointRect();
8326         else {
8327             d->boundingRect = shape().controlPointRect();
8328         }
8329     }
8330     return d->boundingRect;
8331 }
8332 
8333 /*!
8334     \reimp
8335 */
shape() const8336 QPainterPath QGraphicsPathItem::shape() const
8337 {
8338     Q_D(const QGraphicsPathItem);
8339     return qt_graphicsItem_shapeFromPath(d->path, d->pen);
8340 }
8341 
8342 /*!
8343     \reimp
8344 */
contains(const QPointF & point) const8345 bool QGraphicsPathItem::contains(const QPointF &point) const
8346 {
8347     return QAbstractGraphicsShapeItem::contains(point);
8348 }
8349 
8350 /*!
8351     \reimp
8352 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)8353 void QGraphicsPathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
8354                               QWidget *widget)
8355 {
8356     Q_D(QGraphicsPathItem);
8357     Q_UNUSED(widget);
8358     painter->setPen(d->pen);
8359     painter->setBrush(d->brush);
8360     painter->drawPath(d->path);
8361 
8362     if (option->state & QStyle::State_Selected)
8363         qt_graphicsItem_highlightSelected(this, painter, option);
8364 }
8365 
8366 /*!
8367     \reimp
8368 */
isObscuredBy(const QGraphicsItem * item) const8369 bool QGraphicsPathItem::isObscuredBy(const QGraphicsItem *item) const
8370 {
8371     return QAbstractGraphicsShapeItem::isObscuredBy(item);
8372 }
8373 
8374 /*!
8375     \reimp
8376 */
opaqueArea() const8377 QPainterPath QGraphicsPathItem::opaqueArea() const
8378 {
8379     return QAbstractGraphicsShapeItem::opaqueArea();
8380 }
8381 
8382 /*!
8383     \reimp
8384 */
type() const8385 int QGraphicsPathItem::type() const
8386 {
8387     return Type;
8388 }
8389 
8390 /*!
8391     \internal
8392 */
supportsExtension(Extension extension) const8393 bool QGraphicsPathItem::supportsExtension(Extension extension) const
8394 {
8395     Q_UNUSED(extension);
8396     return false;
8397 }
8398 
8399 /*!
8400     \internal
8401 */
setExtension(Extension extension,const QVariant & variant)8402 void QGraphicsPathItem::setExtension(Extension extension, const QVariant &variant)
8403 {
8404     Q_UNUSED(extension);
8405     Q_UNUSED(variant);
8406 }
8407 
8408 /*!
8409     \internal
8410 */
extension(const QVariant & variant) const8411 QVariant QGraphicsPathItem::extension(const QVariant &variant) const
8412 {
8413     Q_UNUSED(variant);
8414     return QVariant();
8415 }
8416 
8417 /*!
8418     \class QGraphicsRectItem
8419     \brief The QGraphicsRectItem class provides a rectangle item that you
8420     can add to a QGraphicsScene.
8421     \since 4.2
8422     \ingroup graphicsview-api
8423 
8424     To set the item's rectangle, pass a QRectF to QGraphicsRectItem's
8425     constructor, or call the setRect() function. The rect() function
8426     returns the current rectangle.
8427 
8428     \image graphicsview-rectitem.png
8429 
8430     QGraphicsRectItem uses the rectangle and the pen width to provide
8431     a reasonable implementation of boundingRect(), shape(), and
8432     contains(). The paint() function draws the rectangle using the
8433     item's associated pen and brush, which you can set by calling the
8434     setPen() and setBrush() functions.
8435 
8436     \note The rendering of invalid rectangles, such as those with negative
8437     widths or heights, is undefined. If you cannot be sure that you are
8438     using valid rectangles (for example, if you are creating
8439     rectangles using data from an unreliable source) then you should
8440     use QRectF::normalized() to create normalized rectangles, and use
8441     those instead.
8442 
8443     \sa QGraphicsPathItem, QGraphicsEllipseItem, QGraphicsPolygonItem,
8444     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
8445     View Framework}
8446 */
8447 
8448 class QGraphicsRectItemPrivate : public QAbstractGraphicsShapeItemPrivate
8449 {
8450     Q_DECLARE_PUBLIC(QGraphicsRectItem)
8451 public:
8452     QRectF rect;
8453 };
8454 
8455 /*!
8456     Constructs a QGraphicsRectItem, using \a rect as the default rectangle.
8457     \a parent is passed to QAbstractGraphicsShapeItem's constructor.
8458 
8459     \sa QGraphicsScene::addItem()
8460 */
QGraphicsRectItem(const QRectF & rect,QGraphicsItem * parent,QGraphicsScene * scene)8461 QGraphicsRectItem::QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent
8462 #ifndef Q_QDOC
8463                                      // obsolete argument
8464                                      , QGraphicsScene *scene
8465 #endif
8466     )
8467     : QAbstractGraphicsShapeItem(*new QGraphicsRectItemPrivate, parent, scene)
8468 {
8469     setRect(rect);
8470 }
8471 
8472 /*!
8473     \fn QGraphicsRectItem::QGraphicsRectItem(qreal x, qreal y, qreal width, qreal height,
8474                                      QGraphicsItem *parent)
8475 
8476     Constructs a QGraphicsRectItem with a default rectangle defined
8477     by (\a x, \a y) and the given \a width and \a height.
8478 
8479     \a parent is passed to QAbstractGraphicsShapeItem's constructor.
8480 
8481     \sa QGraphicsScene::addItem()
8482 */
QGraphicsRectItem(qreal x,qreal y,qreal w,qreal h,QGraphicsItem * parent,QGraphicsScene * scene)8483 QGraphicsRectItem::QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h,
8484                                      QGraphicsItem *parent
8485 #ifndef Q_QDOC
8486                                      // obsolete argument
8487                                      , QGraphicsScene *scene
8488 #endif
8489     )
8490     : QAbstractGraphicsShapeItem(*new QGraphicsRectItemPrivate, parent, scene)
8491 {
8492     setRect(QRectF(x, y, w, h));
8493 }
8494 
8495 /*!
8496     Constructs a QGraphicsRectItem. \a parent is passed to
8497     QAbstractGraphicsShapeItem's constructor.
8498 
8499     \sa QGraphicsScene::addItem()
8500 */
QGraphicsRectItem(QGraphicsItem * parent,QGraphicsScene * scene)8501 QGraphicsRectItem::QGraphicsRectItem(QGraphicsItem *parent
8502 #ifndef Q_QDOC
8503                                      // obsolete argument
8504                                      , QGraphicsScene *scene
8505 #endif
8506     )
8507     : QAbstractGraphicsShapeItem(*new QGraphicsRectItemPrivate, parent, scene)
8508 {
8509 }
8510 
8511 /*!
8512     Destroys the QGraphicsRectItem.
8513 */
~QGraphicsRectItem()8514 QGraphicsRectItem::~QGraphicsRectItem()
8515 {
8516 }
8517 
8518 /*!
8519     Returns the item's rectangle.
8520 
8521     \sa setRect()
8522 */
rect() const8523 QRectF QGraphicsRectItem::rect() const
8524 {
8525     Q_D(const QGraphicsRectItem);
8526     return d->rect;
8527 }
8528 
8529 /*!
8530     \fn void QGraphicsRectItem::setRect(const QRectF &rectangle)
8531 
8532     Sets the item's rectangle to be the given \a rectangle.
8533 
8534     \sa rect()
8535 */
setRect(const QRectF & rect)8536 void QGraphicsRectItem::setRect(const QRectF &rect)
8537 {
8538     Q_D(QGraphicsRectItem);
8539     if (d->rect == rect)
8540         return;
8541     prepareGeometryChange();
8542     d->rect = rect;
8543     d->boundingRect = QRectF();
8544     update();
8545 }
8546 
8547 /*!
8548     \fn void QGraphicsRectItem::setRect(qreal x, qreal y, qreal width, qreal height)
8549     \fn void QGraphicsEllipseItem::setRect(qreal x, qreal y, qreal width, qreal height)
8550 
8551     Sets the item's rectangle to the rectangle defined by (\a x, \a y)
8552     and the given \a width and \a height.
8553 
8554     This convenience function is equivalent to calling \c
8555     {setRect(QRectF(x, y, width, height))}
8556 
8557     \sa rect()
8558 */
8559 
8560 /*!
8561     \reimp
8562 */
boundingRect() const8563 QRectF QGraphicsRectItem::boundingRect() const
8564 {
8565     Q_D(const QGraphicsRectItem);
8566     if (d->boundingRect.isNull()) {
8567         qreal halfpw = pen().widthF() / 2;
8568         d->boundingRect = d->rect;
8569         if (halfpw > 0.0)
8570             d->boundingRect.adjust(-halfpw, -halfpw, halfpw, halfpw);
8571     }
8572     return d->boundingRect;
8573 }
8574 
8575 /*!
8576     \reimp
8577 */
shape() const8578 QPainterPath QGraphicsRectItem::shape() const
8579 {
8580     Q_D(const QGraphicsRectItem);
8581     QPainterPath path;
8582     path.addRect(d->rect);
8583     return qt_graphicsItem_shapeFromPath(path, d->pen);
8584 }
8585 
8586 /*!
8587     \reimp
8588 */
contains(const QPointF & point) const8589 bool QGraphicsRectItem::contains(const QPointF &point) const
8590 {
8591     return QAbstractGraphicsShapeItem::contains(point);
8592 }
8593 
8594 /*!
8595     \reimp
8596 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)8597 void QGraphicsRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
8598                               QWidget *widget)
8599 {
8600     Q_D(QGraphicsRectItem);
8601     Q_UNUSED(widget);
8602     painter->setPen(d->pen);
8603     painter->setBrush(d->brush);
8604     painter->drawRect(d->rect);
8605 
8606     if (option->state & QStyle::State_Selected)
8607         qt_graphicsItem_highlightSelected(this, painter, option);
8608 }
8609 
8610 /*!
8611     \reimp
8612 */
isObscuredBy(const QGraphicsItem * item) const8613 bool QGraphicsRectItem::isObscuredBy(const QGraphicsItem *item) const
8614 {
8615     return QAbstractGraphicsShapeItem::isObscuredBy(item);
8616 }
8617 
8618 /*!
8619     \reimp
8620 */
opaqueArea() const8621 QPainterPath QGraphicsRectItem::opaqueArea() const
8622 {
8623     return QAbstractGraphicsShapeItem::opaqueArea();
8624 }
8625 
8626 /*!
8627     \reimp
8628 */
type() const8629 int QGraphicsRectItem::type() const
8630 {
8631     return Type;
8632 }
8633 
8634 /*!
8635     \internal
8636 */
supportsExtension(Extension extension) const8637 bool QGraphicsRectItem::supportsExtension(Extension extension) const
8638 {
8639     Q_UNUSED(extension);
8640     return false;
8641 }
8642 
8643 /*!
8644     \internal
8645 */
setExtension(Extension extension,const QVariant & variant)8646 void QGraphicsRectItem::setExtension(Extension extension, const QVariant &variant)
8647 {
8648     Q_UNUSED(extension);
8649     Q_UNUSED(variant);
8650 }
8651 
8652 /*!
8653     \internal
8654 */
extension(const QVariant & variant) const8655 QVariant QGraphicsRectItem::extension(const QVariant &variant) const
8656 {
8657     Q_UNUSED(variant);
8658     return QVariant();
8659 }
8660 
8661 /*!
8662     \class QGraphicsEllipseItem
8663     \brief The QGraphicsEllipseItem class provides an ellipse item that you
8664     can add to a QGraphicsScene.
8665     \since 4.2
8666     \ingroup graphicsview-api
8667 
8668     QGraphicsEllipseItem respresents an ellipse with a fill and an outline,
8669     and you can also use it for ellipse segments (see startAngle(),
8670     spanAngle()).
8671 
8672     \table
8673         \row
8674             \o \inlineimage graphicsview-ellipseitem.png
8675             \o \inlineimage graphicsview-ellipseitem-pie.png
8676     \endtable
8677 
8678     To set the item's ellipse, pass a QRectF to QGraphicsEllipseItem's
8679     constructor, or call setRect(). The rect() function returns the
8680     current ellipse geometry.
8681 
8682     QGraphicsEllipseItem uses the rect and the pen width to provide a
8683     reasonable implementation of boundingRect(), shape(), and contains(). The
8684     paint() function draws the ellipse using the item's associated pen and
8685     brush, which you can set by calling setPen() and setBrush().
8686 
8687     \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsPolygonItem,
8688     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
8689     View Framework}
8690 */
8691 
8692 class QGraphicsEllipseItemPrivate : public QAbstractGraphicsShapeItemPrivate
8693 {
8694     Q_DECLARE_PUBLIC(QGraphicsEllipseItem)
8695 public:
QGraphicsEllipseItemPrivate()8696     inline QGraphicsEllipseItemPrivate()
8697         : startAngle(0), spanAngle(360 * 16)
8698     { }
8699 
8700     QRectF rect;
8701     int startAngle;
8702     int spanAngle;
8703 };
8704 
8705 /*!
8706     Constructs a QGraphicsEllipseItem using \a rect as the default rectangle.
8707     \a parent is passed to QAbstractGraphicsShapeItem's constructor.
8708 
8709     \sa QGraphicsScene::addItem()
8710 */
QGraphicsEllipseItem(const QRectF & rect,QGraphicsItem * parent,QGraphicsScene * scene)8711 QGraphicsEllipseItem::QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent
8712 #ifndef Q_QDOC
8713                                            // obsolete argument
8714                                            , QGraphicsScene *scene
8715 #endif
8716     )
8717     : QAbstractGraphicsShapeItem(*new QGraphicsEllipseItemPrivate, parent, scene)
8718 {
8719     setRect(rect);
8720 }
8721 
8722 /*!
8723     \fn QGraphicsEllipseItem::QGraphicsEllipseItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent)
8724     \since 4.3
8725 
8726     Constructs a QGraphicsEllipseItem using the rectangle defined by (\a x, \a
8727     y) and the given \a width and \a height, as the default rectangle. \a
8728     parent is passed to QAbstractGraphicsShapeItem's constructor.
8729 
8730     \sa QGraphicsScene::addItem()
8731 */
QGraphicsEllipseItem(qreal x,qreal y,qreal w,qreal h,QGraphicsItem * parent,QGraphicsScene * scene)8732 QGraphicsEllipseItem::QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h,
8733                                            QGraphicsItem *parent
8734 #ifndef Q_QDOC
8735                                            // obsolete argument
8736                                            , QGraphicsScene *scene
8737 #endif
8738     )
8739     : QAbstractGraphicsShapeItem(*new QGraphicsEllipseItemPrivate, parent, scene)
8740 {
8741     setRect(x,y,w,h);
8742 }
8743 
8744 
8745 
8746 /*!
8747     Constructs a QGraphicsEllipseItem. \a parent is passed to
8748     QAbstractGraphicsShapeItem's constructor.
8749 
8750     \sa QGraphicsScene::addItem()
8751 */
QGraphicsEllipseItem(QGraphicsItem * parent,QGraphicsScene * scene)8752 QGraphicsEllipseItem::QGraphicsEllipseItem(QGraphicsItem *parent
8753 #ifndef Q_QDOC
8754                                            // obsolete argument
8755                                            , QGraphicsScene *scene
8756 #endif
8757     )
8758     : QAbstractGraphicsShapeItem(*new QGraphicsEllipseItemPrivate, parent, scene)
8759 {
8760 }
8761 
8762 /*!
8763     Destroys the QGraphicsEllipseItem.
8764 */
~QGraphicsEllipseItem()8765 QGraphicsEllipseItem::~QGraphicsEllipseItem()
8766 {
8767 }
8768 
8769 /*!
8770     Returns the item's ellipse geometry as a QRectF.
8771 
8772     \sa setRect(), QPainter::drawEllipse()
8773 */
rect() const8774 QRectF QGraphicsEllipseItem::rect() const
8775 {
8776     Q_D(const QGraphicsEllipseItem);
8777     return d->rect;
8778 }
8779 
8780 /*!
8781     Sets the item's ellipse geometry to \a rect. The rectangle's left edge
8782     defines the left edge of the ellipse, and the rectangle's top edge
8783     describes the top of the ellipse. The height and width of the rectangle
8784     describe the height and width of the ellipse.
8785 
8786     \sa rect(), QPainter::drawEllipse()
8787 */
setRect(const QRectF & rect)8788 void QGraphicsEllipseItem::setRect(const QRectF &rect)
8789 {
8790     Q_D(QGraphicsEllipseItem);
8791     if (d->rect == rect)
8792         return;
8793     prepareGeometryChange();
8794     d->rect = rect;
8795     d->boundingRect = QRectF();
8796     update();
8797 }
8798 
8799 /*!
8800     Returns the start angle for an ellipse segment in 16ths of a degree. This
8801     angle is used together with spanAngle() for representing an ellipse
8802     segment (a pie). By default, the start angle is 0.
8803 
8804     \sa setStartAngle(), spanAngle()
8805 */
startAngle() const8806 int QGraphicsEllipseItem::startAngle() const
8807 {
8808     Q_D(const QGraphicsEllipseItem);
8809     return d->startAngle;
8810 }
8811 
8812 /*!
8813     Sets the start angle for an ellipse segment to \a angle, which is in 16ths
8814     of a degree. This angle is used together with spanAngle() for representing
8815     an ellipse segment (a pie). By default, the start angle is 0.
8816 
8817     \sa startAngle(), setSpanAngle(), QPainter::drawPie()
8818 */
setStartAngle(int angle)8819 void QGraphicsEllipseItem::setStartAngle(int angle)
8820 {
8821     Q_D(QGraphicsEllipseItem);
8822     if (angle != d->startAngle) {
8823         prepareGeometryChange();
8824         d->boundingRect = QRectF();
8825         d->startAngle = angle;
8826         update();
8827     }
8828 }
8829 
8830 /*!
8831     Returns the span angle of an ellipse segment in 16ths of a degree. This
8832     angle is used together with startAngle() for representing an ellipse
8833     segment (a pie). By default, this function returns 5760 (360 * 16, a full
8834     ellipse).
8835 
8836     \sa setSpanAngle(), startAngle()
8837 */
spanAngle() const8838 int QGraphicsEllipseItem::spanAngle() const
8839 {
8840     Q_D(const QGraphicsEllipseItem);
8841     return d->spanAngle;
8842 }
8843 
8844 /*!
8845     Sets the span angle for an ellipse segment to \a angle, which is in 16ths
8846     of a degree. This angle is used together with startAngle() to represent an
8847     ellipse segment (a pie). By default, the span angle is 5760 (360 * 16, a
8848     full ellipse).
8849 
8850     \sa spanAngle(), setStartAngle(), QPainter::drawPie()
8851 */
setSpanAngle(int angle)8852 void QGraphicsEllipseItem::setSpanAngle(int angle)
8853 {
8854     Q_D(QGraphicsEllipseItem);
8855     if (angle != d->spanAngle) {
8856         prepareGeometryChange();
8857         d->boundingRect = QRectF();
8858         d->spanAngle = angle;
8859         update();
8860     }
8861 }
8862 
8863 /*!
8864     \reimp
8865 */
boundingRect() const8866 QRectF QGraphicsEllipseItem::boundingRect() const
8867 {
8868     Q_D(const QGraphicsEllipseItem);
8869     if (d->boundingRect.isNull()) {
8870         qreal pw = pen().widthF();
8871         if (pw == 0.0 && d->spanAngle == 360 * 16)
8872             d->boundingRect = d->rect;
8873         else
8874             d->boundingRect = shape().controlPointRect();
8875     }
8876     return d->boundingRect;
8877 }
8878 
8879 /*!
8880     \reimp
8881 */
shape() const8882 QPainterPath QGraphicsEllipseItem::shape() const
8883 {
8884     Q_D(const QGraphicsEllipseItem);
8885     QPainterPath path;
8886     if (d->rect.isNull())
8887         return path;
8888     if (d->spanAngle != 360 * 16) {
8889         path.moveTo(d->rect.center());
8890         path.arcTo(d->rect, d->startAngle / qreal(16.0), d->spanAngle / qreal(16.0));
8891     } else {
8892         path.addEllipse(d->rect);
8893     }
8894 
8895     return qt_graphicsItem_shapeFromPath(path, d->pen);
8896 }
8897 
8898 /*!
8899     \reimp
8900 */
contains(const QPointF & point) const8901 bool QGraphicsEllipseItem::contains(const QPointF &point) const
8902 {
8903     return QAbstractGraphicsShapeItem::contains(point);
8904 }
8905 
8906 /*!
8907     \reimp
8908 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)8909 void QGraphicsEllipseItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
8910                                  QWidget *widget)
8911 {
8912     Q_D(QGraphicsEllipseItem);
8913     Q_UNUSED(widget);
8914     painter->setPen(d->pen);
8915     painter->setBrush(d->brush);
8916     if ((d->spanAngle != 0) && (qAbs(d->spanAngle) % (360 * 16) == 0))
8917         painter->drawEllipse(d->rect);
8918     else
8919         painter->drawPie(d->rect, d->startAngle, d->spanAngle);
8920 
8921     if (option->state & QStyle::State_Selected)
8922         qt_graphicsItem_highlightSelected(this, painter, option);
8923 }
8924 
8925 /*!
8926     \reimp
8927 */
isObscuredBy(const QGraphicsItem * item) const8928 bool QGraphicsEllipseItem::isObscuredBy(const QGraphicsItem *item) const
8929 {
8930     return QAbstractGraphicsShapeItem::isObscuredBy(item);
8931 }
8932 
8933 /*!
8934     \reimp
8935 */
opaqueArea() const8936 QPainterPath QGraphicsEllipseItem::opaqueArea() const
8937 {
8938     return QAbstractGraphicsShapeItem::opaqueArea();
8939 }
8940 
8941 /*!
8942     \reimp
8943 */
type() const8944 int QGraphicsEllipseItem::type() const
8945 {
8946     return Type;
8947 }
8948 
8949 
8950 /*!
8951     \internal
8952 */
supportsExtension(Extension extension) const8953 bool QGraphicsEllipseItem::supportsExtension(Extension extension) const
8954 {
8955     Q_UNUSED(extension);
8956     return false;
8957 }
8958 
8959 /*!
8960     \internal
8961 */
setExtension(Extension extension,const QVariant & variant)8962 void QGraphicsEllipseItem::setExtension(Extension extension, const QVariant &variant)
8963 {
8964     Q_UNUSED(extension);
8965     Q_UNUSED(variant);
8966 }
8967 
8968 /*!
8969     \internal
8970 */
extension(const QVariant & variant) const8971 QVariant QGraphicsEllipseItem::extension(const QVariant &variant) const
8972 {
8973     Q_UNUSED(variant);
8974     return QVariant();
8975 }
8976 
8977 /*!
8978     \class QGraphicsPolygonItem
8979     \brief The QGraphicsPolygonItem class provides a polygon item that you
8980     can add to a QGraphicsScene.
8981     \since 4.2
8982     \ingroup graphicsview-api
8983 
8984     To set the item's polygon, pass a QPolygonF to
8985     QGraphicsPolygonItem's constructor, or call the setPolygon()
8986     function. The polygon() function returns the current polygon.
8987 
8988     \image graphicsview-polygonitem.png
8989 
8990     QGraphicsPolygonItem uses the polygon and the pen width to provide
8991     a reasonable implementation of boundingRect(), shape(), and
8992     contains(). The paint() function draws the polygon using the
8993     item's associated pen and brush, which you can set by calling the
8994     setPen() and setBrush() functions.
8995 
8996     \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem,
8997     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
8998     View Framework}
8999 */
9000 
9001 class QGraphicsPolygonItemPrivate : public QAbstractGraphicsShapeItemPrivate
9002 {
9003     Q_DECLARE_PUBLIC(QGraphicsPolygonItem)
9004 public:
QGraphicsPolygonItemPrivate()9005     inline QGraphicsPolygonItemPrivate()
9006         : fillRule(Qt::OddEvenFill)
9007     { }
9008 
9009     QPolygonF polygon;
9010     Qt::FillRule fillRule;
9011 };
9012 
9013 /*!
9014     Constructs a QGraphicsPolygonItem with \a polygon as the default
9015     polygon. \a parent is passed to QAbstractGraphicsShapeItem's constructor.
9016 
9017     \sa QGraphicsScene::addItem()
9018 */
QGraphicsPolygonItem(const QPolygonF & polygon,QGraphicsItem * parent,QGraphicsScene * scene)9019 QGraphicsPolygonItem::QGraphicsPolygonItem(const QPolygonF &polygon,
9020                                            QGraphicsItem *parent
9021 #ifndef Q_QDOC
9022                                            // obsolete argument
9023                                            , QGraphicsScene *scene
9024 #endif
9025     )
9026     : QAbstractGraphicsShapeItem(*new QGraphicsPolygonItemPrivate, parent, scene)
9027 {
9028     setPolygon(polygon);
9029 }
9030 
9031 /*!
9032     Constructs a QGraphicsPolygonItem. \a parent is passed to
9033     QAbstractGraphicsShapeItem's constructor.
9034 
9035     \sa QGraphicsScene::addItem()
9036 */
QGraphicsPolygonItem(QGraphicsItem * parent,QGraphicsScene * scene)9037 QGraphicsPolygonItem::QGraphicsPolygonItem(QGraphicsItem *parent
9038 #ifndef Q_QDOC
9039                                            // obsolete argument
9040                                            , QGraphicsScene *scene
9041 #endif
9042     )
9043     : QAbstractGraphicsShapeItem(*new QGraphicsPolygonItemPrivate, parent, scene)
9044 {
9045 }
9046 
9047 /*!
9048     Destroys the QGraphicsPolygonItem.
9049 */
~QGraphicsPolygonItem()9050 QGraphicsPolygonItem::~QGraphicsPolygonItem()
9051 {
9052 }
9053 
9054 /*!
9055     Returns the item's polygon, or an empty polygon if no polygon
9056     has been set.
9057 
9058     \sa setPolygon()
9059 */
polygon() const9060 QPolygonF QGraphicsPolygonItem::polygon() const
9061 {
9062     Q_D(const QGraphicsPolygonItem);
9063     return d->polygon;
9064 }
9065 
9066 /*!
9067     Sets the item's polygon to be the given \a polygon.
9068 
9069     \sa polygon()
9070 */
setPolygon(const QPolygonF & polygon)9071 void QGraphicsPolygonItem::setPolygon(const QPolygonF &polygon)
9072 {
9073     Q_D(QGraphicsPolygonItem);
9074     if (d->polygon == polygon)
9075         return;
9076     prepareGeometryChange();
9077     d->polygon = polygon;
9078     d->boundingRect = QRectF();
9079     update();
9080 }
9081 
9082 /*!
9083      Returns the fill rule of the polygon. The default fill rule is
9084      Qt::OddEvenFill.
9085 
9086      \sa setFillRule(), QPainterPath::fillRule(), QPainter::drawPolygon()
9087 */
fillRule() const9088 Qt::FillRule QGraphicsPolygonItem::fillRule() const
9089 {
9090      Q_D(const QGraphicsPolygonItem);
9091      return d->fillRule;
9092 }
9093 
9094 /*!
9095      Sets the fill rule of the polygon to \a rule. The default fill rule is
9096      Qt::OddEvenFill.
9097 
9098      \sa fillRule(), QPainterPath::fillRule(), QPainter::drawPolygon()
9099 */
setFillRule(Qt::FillRule rule)9100 void QGraphicsPolygonItem::setFillRule(Qt::FillRule rule)
9101 {
9102      Q_D(QGraphicsPolygonItem);
9103      if (rule != d->fillRule) {
9104          d->fillRule = rule;
9105          update();
9106      }
9107 }
9108 
9109 /*!
9110     \reimp
9111 */
boundingRect() const9112 QRectF QGraphicsPolygonItem::boundingRect() const
9113 {
9114     Q_D(const QGraphicsPolygonItem);
9115     if (d->boundingRect.isNull()) {
9116         qreal pw = pen().widthF();
9117         if (pw == 0.0)
9118             d->boundingRect = d->polygon.boundingRect();
9119         else
9120             d->boundingRect = shape().controlPointRect();
9121     }
9122     return d->boundingRect;
9123 }
9124 
9125 /*!
9126     \reimp
9127 */
shape() const9128 QPainterPath QGraphicsPolygonItem::shape() const
9129 {
9130     Q_D(const QGraphicsPolygonItem);
9131     QPainterPath path;
9132     path.addPolygon(d->polygon);
9133     return qt_graphicsItem_shapeFromPath(path, d->pen);
9134 }
9135 
9136 /*!
9137     \reimp
9138 */
contains(const QPointF & point) const9139 bool QGraphicsPolygonItem::contains(const QPointF &point) const
9140 {
9141     return QAbstractGraphicsShapeItem::contains(point);
9142 }
9143 
9144 /*!
9145     \reimp
9146 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)9147 void QGraphicsPolygonItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
9148 {
9149     Q_D(QGraphicsPolygonItem);
9150     Q_UNUSED(widget);
9151     painter->setPen(d->pen);
9152     painter->setBrush(d->brush);
9153     painter->drawPolygon(d->polygon, d->fillRule);
9154 
9155     if (option->state & QStyle::State_Selected)
9156         qt_graphicsItem_highlightSelected(this, painter, option);
9157 }
9158 
9159 /*!
9160     \reimp
9161 */
isObscuredBy(const QGraphicsItem * item) const9162 bool QGraphicsPolygonItem::isObscuredBy(const QGraphicsItem *item) const
9163 {
9164     return QAbstractGraphicsShapeItem::isObscuredBy(item);
9165 }
9166 
9167 /*!
9168     \reimp
9169 */
opaqueArea() const9170 QPainterPath QGraphicsPolygonItem::opaqueArea() const
9171 {
9172     return QAbstractGraphicsShapeItem::opaqueArea();
9173 }
9174 
9175 /*!
9176     \reimp
9177 */
type() const9178 int QGraphicsPolygonItem::type() const
9179 {
9180     return Type;
9181 }
9182 
9183 /*!
9184     \internal
9185 */
supportsExtension(Extension extension) const9186 bool QGraphicsPolygonItem::supportsExtension(Extension extension) const
9187 {
9188     Q_UNUSED(extension);
9189     return false;
9190 }
9191 
9192 /*!
9193     \internal
9194 */
setExtension(Extension extension,const QVariant & variant)9195 void QGraphicsPolygonItem::setExtension(Extension extension, const QVariant &variant)
9196 {
9197     Q_UNUSED(extension);
9198     Q_UNUSED(variant);
9199 }
9200 
9201 /*!
9202     \internal
9203 */
extension(const QVariant & variant) const9204 QVariant QGraphicsPolygonItem::extension(const QVariant &variant) const
9205 {
9206     Q_UNUSED(variant);
9207     return QVariant();
9208 }
9209 
9210 /*!
9211     \class QGraphicsLineItem
9212     \brief The QGraphicsLineItem class provides a line item that you can add to a
9213     QGraphicsScene.
9214     \since 4.2
9215     \ingroup graphicsview-api
9216 
9217     To set the item's line, pass a QLineF to QGraphicsLineItem's
9218     constructor, or call the setLine() function. The line() function
9219     returns the current line. By default the line is black with a
9220     width of 0, but you can change this by calling setPen().
9221 
9222     \img graphicsview-lineitem.png
9223 
9224     QGraphicsLineItem uses the line and the pen width to provide a reasonable
9225     implementation of boundingRect(), shape(), and contains(). The paint()
9226     function draws the line using the item's associated pen.
9227 
9228     \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem,
9229     QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsPixmapItem,
9230     {Graphics View Framework}
9231 */
9232 
9233 class QGraphicsLineItemPrivate : public QGraphicsItemPrivate
9234 {
9235     Q_DECLARE_PUBLIC(QGraphicsLineItem)
9236 public:
9237     QLineF line;
9238     QPen pen;
9239 };
9240 
9241 /*!
9242     Constructs a QGraphicsLineItem, using \a line as the default line. \a
9243     parent is passed to QGraphicsItem's constructor.
9244 
9245     \sa QGraphicsScene::addItem()
9246 */
QGraphicsLineItem(const QLineF & line,QGraphicsItem * parent,QGraphicsScene * scene)9247 QGraphicsLineItem::QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent
9248 #ifndef Q_QDOC
9249                                      // obsolete argument
9250                                      , QGraphicsScene *scene
9251 #endif
9252     )
9253     : QGraphicsItem(*new QGraphicsLineItemPrivate, parent, scene)
9254 {
9255     setLine(line);
9256 }
9257 
9258 /*!
9259     Constructs a QGraphicsLineItem, using the line between (\a x1, \a y1) and
9260     (\a x2, \a y2) as the default line.  \a parent is passed to
9261     QGraphicsItem's constructor.
9262 
9263     \sa QGraphicsScene::addItem()
9264 */
QGraphicsLineItem(qreal x1,qreal y1,qreal x2,qreal y2,QGraphicsItem * parent,QGraphicsScene * scene)9265 QGraphicsLineItem::QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent
9266 #ifndef Q_QDOC
9267                                      // obsolete argument
9268                                      , QGraphicsScene *scene
9269 #endif
9270     )
9271     : QGraphicsItem(*new QGraphicsLineItemPrivate, parent, scene)
9272 {
9273     setLine(x1, y1, x2, y2);
9274 }
9275 
9276 
9277 
9278 /*!
9279     Constructs a QGraphicsLineItem. \a parent is passed to QGraphicsItem's
9280     constructor.
9281 
9282     \sa QGraphicsScene::addItem()
9283 */
QGraphicsLineItem(QGraphicsItem * parent,QGraphicsScene * scene)9284 QGraphicsLineItem::QGraphicsLineItem(QGraphicsItem *parent
9285 #ifndef Q_QDOC
9286                                      // obsolete argument
9287                                      , QGraphicsScene *scene
9288 #endif
9289     )
9290     : QGraphicsItem(*new QGraphicsLineItemPrivate, parent, scene)
9291 {
9292 }
9293 
9294 /*!
9295     Destroys the QGraphicsLineItem.
9296 */
~QGraphicsLineItem()9297 QGraphicsLineItem::~QGraphicsLineItem()
9298 {
9299 }
9300 
9301 /*!
9302     Returns the item's pen, or a black solid 0-width pen if no pen has
9303     been set.
9304 
9305     \sa setPen()
9306 */
pen() const9307 QPen QGraphicsLineItem::pen() const
9308 {
9309     Q_D(const QGraphicsLineItem);
9310     return d->pen;
9311 }
9312 
9313 /*!
9314     Sets the item's pen to \a pen. If no pen is set, the line will be painted
9315     using a black solid 0-width pen.
9316 
9317     \sa pen()
9318 */
setPen(const QPen & pen)9319 void QGraphicsLineItem::setPen(const QPen &pen)
9320 {
9321     Q_D(QGraphicsLineItem);
9322     if (d->pen == pen)
9323         return;
9324     prepareGeometryChange();
9325     d->pen = pen;
9326     update();
9327 }
9328 
9329 /*!
9330     Returns the item's line, or a null line if no line has been set.
9331 
9332     \sa setLine()
9333 */
line() const9334 QLineF QGraphicsLineItem::line() const
9335 {
9336     Q_D(const QGraphicsLineItem);
9337     return d->line;
9338 }
9339 
9340 /*!
9341     Sets the item's line to be the given \a line.
9342 
9343     \sa line()
9344 */
setLine(const QLineF & line)9345 void QGraphicsLineItem::setLine(const QLineF &line)
9346 {
9347     Q_D(QGraphicsLineItem);
9348     if (d->line == line)
9349         return;
9350     prepareGeometryChange();
9351     d->line = line;
9352     update();
9353 }
9354 
9355 /*!
9356     \fn void QGraphicsLineItem::setLine(qreal x1, qreal y1, qreal x2, qreal y2)
9357     \overload
9358 
9359     Sets the item's line to be the line between (\a x1, \a y1) and (\a
9360     x2, \a y2).
9361 
9362     This is the same as calling \c {setLine(QLineF(x1, y1, x2, y2))}.
9363 */
9364 
9365 /*!
9366     \reimp
9367 */
boundingRect() const9368 QRectF QGraphicsLineItem::boundingRect() const
9369 {
9370     Q_D(const QGraphicsLineItem);
9371     if (d->pen.widthF() == 0.0) {
9372         const qreal x1 = d->line.p1().x();
9373         const qreal x2 = d->line.p2().x();
9374         const qreal y1 = d->line.p1().y();
9375         const qreal y2 = d->line.p2().y();
9376         qreal lx = qMin(x1, x2);
9377         qreal rx = qMax(x1, x2);
9378         qreal ty = qMin(y1, y2);
9379         qreal by = qMax(y1, y2);
9380         return QRectF(lx, ty, rx - lx, by - ty);
9381     }
9382     return shape().controlPointRect();
9383 }
9384 
9385 /*!
9386     \reimp
9387 */
shape() const9388 QPainterPath QGraphicsLineItem::shape() const
9389 {
9390     Q_D(const QGraphicsLineItem);
9391     QPainterPath path;
9392     if (d->line == QLineF())
9393         return path;
9394 
9395     path.moveTo(d->line.p1());
9396     path.lineTo(d->line.p2());
9397     return qt_graphicsItem_shapeFromPath(path, d->pen);
9398 }
9399 
9400 /*!
9401     \reimp
9402 */
contains(const QPointF & point) const9403 bool QGraphicsLineItem::contains(const QPointF &point) const
9404 {
9405     return QGraphicsItem::contains(point);
9406 }
9407 
9408 /*!
9409     \reimp
9410 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)9411 void QGraphicsLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
9412 {
9413     Q_D(QGraphicsLineItem);
9414     Q_UNUSED(widget);
9415     painter->setPen(d->pen);
9416     painter->drawLine(d->line);
9417 
9418     if (option->state & QStyle::State_Selected)
9419         qt_graphicsItem_highlightSelected(this, painter, option);
9420 }
9421 
9422 /*!
9423     \reimp
9424 */
isObscuredBy(const QGraphicsItem * item) const9425 bool QGraphicsLineItem::isObscuredBy(const QGraphicsItem *item) const
9426 {
9427     return QGraphicsItem::isObscuredBy(item);
9428 }
9429 
9430 /*!
9431     \reimp
9432 */
opaqueArea() const9433 QPainterPath QGraphicsLineItem::opaqueArea() const
9434 {
9435     return QGraphicsItem::opaqueArea();
9436 }
9437 
9438 /*!
9439     \reimp
9440 */
type() const9441 int QGraphicsLineItem::type() const
9442 {
9443     return Type;
9444 }
9445 
9446 /*!
9447     \internal
9448 */
supportsExtension(Extension extension) const9449 bool QGraphicsLineItem::supportsExtension(Extension extension) const
9450 {
9451     Q_UNUSED(extension);
9452     return false;
9453 }
9454 
9455 /*!
9456     \internal
9457 */
setExtension(Extension extension,const QVariant & variant)9458 void QGraphicsLineItem::setExtension(Extension extension, const QVariant &variant)
9459 {
9460     Q_UNUSED(extension);
9461     Q_UNUSED(variant);
9462 }
9463 
9464 /*!
9465     \internal
9466 */
extension(const QVariant & variant) const9467 QVariant QGraphicsLineItem::extension(const QVariant &variant) const
9468 {
9469     Q_UNUSED(variant);
9470     return QVariant();
9471 }
9472 
9473 /*!
9474     \class QGraphicsPixmapItem
9475     \brief The QGraphicsPixmapItem class provides a pixmap item that you can add to
9476     a QGraphicsScene.
9477     \since 4.2
9478     \ingroup graphicsview-api
9479 
9480     To set the item's pixmap, pass a QPixmap to QGraphicsPixmapItem's
9481     constructor, or call the setPixmap() function. The pixmap()
9482     function returns the current pixmap.
9483 
9484     QGraphicsPixmapItem uses pixmap's optional alpha mask to provide a
9485     reasonable implementation of boundingRect(), shape(), and contains().
9486 
9487     \image graphicsview-pixmapitem.png
9488 
9489     The pixmap is drawn at the item's (0, 0) coordinate, as returned by
9490     offset(). You can change the drawing offset by calling setOffset().
9491 
9492     You can set the pixmap's transformation mode by calling
9493     setTransformationMode(). By default, Qt::FastTransformation is used, which
9494     provides fast, non-smooth scaling. Qt::SmoothTransformation enables
9495     QPainter::SmoothPixmapTransform on the painter, and the quality depends on
9496     the platform and viewport. The result is usually not as good as calling
9497     QPixmap::scale() directly. Call transformationMode() to get the current
9498     transformation mode for the item.
9499 
9500     \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem,
9501     QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsLineItem,
9502     {Graphics View Framework}
9503 */
9504 
9505 /*!
9506     \enum QGraphicsPixmapItem::ShapeMode
9507 
9508     This enum describes how QGraphicsPixmapItem calculates its shape and
9509     opaque area.
9510 
9511     The default value is MaskShape.
9512 
9513     \value MaskShape The shape is determined by calling QPixmap::mask().
9514     This shape includes only the opaque pixels of the pixmap.
9515     Because the shape is more complex, however, it can be slower than the other modes,
9516     and uses more memory.
9517 
9518     \value BoundingRectShape The shape is determined by tracing the outline of
9519     the pixmap. This is the fastest shape mode, but it does not take into account
9520     any transparent areas on the pixmap.
9521 
9522     \value HeuristicMaskShape The shape is determine by calling
9523     QPixmap::createHeuristicMask().  The performance and memory consumption
9524     is similar to MaskShape.
9525 */
9526 extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region);
9527 
9528 class QGraphicsPixmapItemPrivate : public QGraphicsItemPrivate
9529 {
9530     Q_DECLARE_PUBLIC(QGraphicsPixmapItem)
9531 public:
QGraphicsPixmapItemPrivate()9532     QGraphicsPixmapItemPrivate()
9533         : transformationMode(Qt::FastTransformation),
9534         shapeMode(QGraphicsPixmapItem::MaskShape),
9535         hasShape(false)
9536     {}
9537 
9538     QPixmap pixmap;
9539     Qt::TransformationMode transformationMode;
9540     QPointF offset;
9541     QGraphicsPixmapItem::ShapeMode shapeMode;
9542     QPainterPath shape;
9543     bool hasShape;
9544 
updateShape()9545     void updateShape()
9546     {
9547         shape = QPainterPath();
9548         switch (shapeMode) {
9549         case QGraphicsPixmapItem::MaskShape: {
9550             QBitmap mask = pixmap.mask();
9551             if (!mask.isNull()) {
9552                 shape = qt_regionToPath(QRegion(mask).translated(offset.toPoint()));
9553                 break;
9554             }
9555             // FALL THROUGH
9556         }
9557         case QGraphicsPixmapItem::BoundingRectShape:
9558             shape.addRect(QRectF(offset.x(), offset.y(), pixmap.width(), pixmap.height()));
9559             break;
9560         case QGraphicsPixmapItem::HeuristicMaskShape:
9561 #ifndef QT_NO_IMAGE_HEURISTIC_MASK
9562             shape = qt_regionToPath(QRegion(pixmap.createHeuristicMask()).translated(offset.toPoint()));
9563 #else
9564             shape.addRect(QRectF(offset.x(), offset.y(), pixmap.width(), pixmap.height()));
9565 #endif
9566             break;
9567         }
9568     }
9569 };
9570 
9571 /*!
9572     Constructs a QGraphicsPixmapItem, using \a pixmap as the default pixmap.
9573     \a parent is passed to QGraphicsItem's constructor.
9574 
9575     \sa QGraphicsScene::addItem()
9576 */
QGraphicsPixmapItem(const QPixmap & pixmap,QGraphicsItem * parent,QGraphicsScene * scene)9577 QGraphicsPixmapItem::QGraphicsPixmapItem(const QPixmap &pixmap,
9578                                          QGraphicsItem *parent
9579 #ifndef Q_QDOC
9580                                          // obsolete argument
9581                                          , QGraphicsScene *scene
9582 #endif
9583     )
9584     : QGraphicsItem(*new QGraphicsPixmapItemPrivate, parent, scene)
9585 {
9586     setPixmap(pixmap);
9587 }
9588 
9589 /*!
9590     Constructs a QGraphicsPixmapItem. \a parent is passed to QGraphicsItem's
9591     constructor.
9592 
9593     \sa QGraphicsScene::addItem()
9594 */
QGraphicsPixmapItem(QGraphicsItem * parent,QGraphicsScene * scene)9595 QGraphicsPixmapItem::QGraphicsPixmapItem(QGraphicsItem *parent
9596 #ifndef Q_QDOC
9597                                          // obsolete argument
9598                                          , QGraphicsScene *scene
9599 #endif
9600     )
9601     : QGraphicsItem(*new QGraphicsPixmapItemPrivate, parent, scene)
9602 {
9603 }
9604 
9605 /*!
9606     Destroys the QGraphicsPixmapItem.
9607 */
~QGraphicsPixmapItem()9608 QGraphicsPixmapItem::~QGraphicsPixmapItem()
9609 {
9610 }
9611 
9612 /*!
9613     Sets the item's pixmap to \a pixmap.
9614 
9615     \sa pixmap()
9616 */
setPixmap(const QPixmap & pixmap)9617 void QGraphicsPixmapItem::setPixmap(const QPixmap &pixmap)
9618 {
9619     Q_D(QGraphicsPixmapItem);
9620     prepareGeometryChange();
9621     d->pixmap = pixmap;
9622     d->hasShape = false;
9623     update();
9624 }
9625 
9626 /*!
9627     Returns the item's pixmap, or an invalid QPixmap if no pixmap has been
9628     set.
9629 
9630     \sa setPixmap()
9631 */
pixmap() const9632 QPixmap QGraphicsPixmapItem::pixmap() const
9633 {
9634     Q_D(const QGraphicsPixmapItem);
9635     return d->pixmap;
9636 }
9637 
9638 /*!
9639     Returns the transformation mode of the pixmap. The default mode is
9640     Qt::FastTransformation, which provides quick transformation with no
9641     smoothing.
9642 
9643     \sa setTransformationMode()
9644 */
transformationMode() const9645 Qt::TransformationMode QGraphicsPixmapItem::transformationMode() const
9646 {
9647     Q_D(const QGraphicsPixmapItem);
9648     return d->transformationMode;
9649 }
9650 
9651 /*!
9652     Sets the pixmap item's transformation mode to \a mode, and toggles an
9653     update of the item. The default mode is Qt::FastTransformation, which
9654     provides quick transformation with no smoothing.
9655 
9656     Qt::SmoothTransformation enables QPainter::SmoothPixmapTransform on the
9657     painter, and the quality depends on the platform and viewport. The result
9658     is usually not as good as calling QPixmap::scale() directly.
9659 
9660     \sa transformationMode()
9661 */
setTransformationMode(Qt::TransformationMode mode)9662 void QGraphicsPixmapItem::setTransformationMode(Qt::TransformationMode mode)
9663 {
9664     Q_D(QGraphicsPixmapItem);
9665     if (mode != d->transformationMode) {
9666         d->transformationMode = mode;
9667         update();
9668     }
9669 }
9670 
9671 /*!
9672     Returns the pixmap item's \e offset, which defines the point of the
9673     top-left corner of the pixmap, in local coordinates.
9674 
9675     \sa setOffset()
9676 */
offset() const9677 QPointF QGraphicsPixmapItem::offset() const
9678 {
9679     Q_D(const QGraphicsPixmapItem);
9680     return d->offset;
9681 }
9682 
9683 /*!
9684     Sets the pixmap item's offset to \a offset. QGraphicsPixmapItem will draw
9685     its pixmap using \a offset for its top-left corner.
9686 
9687     \sa offset()
9688 */
setOffset(const QPointF & offset)9689 void QGraphicsPixmapItem::setOffset(const QPointF &offset)
9690 {
9691     Q_D(QGraphicsPixmapItem);
9692     if (d->offset == offset)
9693         return;
9694     prepareGeometryChange();
9695     d->offset = offset;
9696     d->hasShape = false;
9697     update();
9698 }
9699 
9700 /*!
9701     \fn void QGraphicsPixmapItem::setOffset(qreal x, qreal y)
9702     \since 4.3
9703 
9704     This convenience function is equivalent to calling setOffset(QPointF(\a x, \a y)).
9705 */
9706 
9707 /*!
9708     \reimp
9709 */
boundingRect() const9710 QRectF QGraphicsPixmapItem::boundingRect() const
9711 {
9712     Q_D(const QGraphicsPixmapItem);
9713     if (d->pixmap.isNull())
9714         return QRectF();
9715     if (d->flags & ItemIsSelectable) {
9716         qreal pw = 1.0;
9717         return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2);
9718     } else {
9719         return QRectF(d->offset, d->pixmap.size());
9720     }
9721 }
9722 
9723 /*!
9724     \reimp
9725 */
shape() const9726 QPainterPath QGraphicsPixmapItem::shape() const
9727 {
9728     Q_D(const QGraphicsPixmapItem);
9729     if (!d->hasShape) {
9730         QGraphicsPixmapItemPrivate *thatD = const_cast<QGraphicsPixmapItemPrivate *>(d);
9731         thatD->updateShape();
9732         thatD->hasShape = true;
9733     }
9734     return d_func()->shape;
9735 }
9736 
9737 /*!
9738     \reimp
9739 */
contains(const QPointF & point) const9740 bool QGraphicsPixmapItem::contains(const QPointF &point) const
9741 {
9742     return QGraphicsItem::contains(point);
9743 }
9744 
9745 /*!
9746     \reimp
9747 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)9748 void QGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
9749                                 QWidget *widget)
9750 {
9751     Q_D(QGraphicsPixmapItem);
9752     Q_UNUSED(widget);
9753 
9754     painter->setRenderHint(QPainter::SmoothPixmapTransform,
9755                            (d->transformationMode == Qt::SmoothTransformation));
9756 
9757     painter->drawPixmap(d->offset, d->pixmap);
9758 
9759     if (option->state & QStyle::State_Selected)
9760         qt_graphicsItem_highlightSelected(this, painter, option);
9761 }
9762 
9763 /*!
9764     \reimp
9765 */
isObscuredBy(const QGraphicsItem * item) const9766 bool QGraphicsPixmapItem::isObscuredBy(const QGraphicsItem *item) const
9767 {
9768     return QGraphicsItem::isObscuredBy(item);
9769 }
9770 
9771 /*!
9772     \reimp
9773 */
opaqueArea() const9774 QPainterPath QGraphicsPixmapItem::opaqueArea() const
9775 {
9776     return shape();
9777 }
9778 
9779 /*!
9780     \reimp
9781 */
type() const9782 int QGraphicsPixmapItem::type() const
9783 {
9784     return Type;
9785 }
9786 
9787 /*!
9788     Returns the item's shape mode. The shape mode describes how
9789     QGraphicsPixmapItem calculates its shape. The default mode is MaskShape.
9790 
9791     \sa setShapeMode(), ShapeMode
9792 */
shapeMode() const9793 QGraphicsPixmapItem::ShapeMode QGraphicsPixmapItem::shapeMode() const
9794 {
9795     return d_func()->shapeMode;
9796 }
9797 
9798 /*!
9799     Sets the item's shape mode to \a mode. The shape mode describes how
9800     QGraphicsPixmapItem calculates its shape. The default mode is MaskShape.
9801 
9802     \sa shapeMode(), ShapeMode
9803 */
setShapeMode(ShapeMode mode)9804 void QGraphicsPixmapItem::setShapeMode(ShapeMode mode)
9805 {
9806     Q_D(QGraphicsPixmapItem);
9807     if (d->shapeMode == mode)
9808         return;
9809     d->shapeMode = mode;
9810     d->hasShape = false;
9811 }
9812 
9813 /*!
9814     \internal
9815 */
supportsExtension(Extension extension) const9816 bool QGraphicsPixmapItem::supportsExtension(Extension extension) const
9817 {
9818     Q_UNUSED(extension);
9819     return false;
9820 }
9821 
9822 /*!
9823     \internal
9824 */
setExtension(Extension extension,const QVariant & variant)9825 void QGraphicsPixmapItem::setExtension(Extension extension, const QVariant &variant)
9826 {
9827     Q_UNUSED(extension);
9828     Q_UNUSED(variant);
9829 }
9830 
9831 /*!
9832     \internal
9833 */
extension(const QVariant & variant) const9834 QVariant QGraphicsPixmapItem::extension(const QVariant &variant) const
9835 {
9836     Q_UNUSED(variant);
9837     return QVariant();
9838 }
9839 
9840 /*!
9841     \class QGraphicsTextItem
9842     \brief The QGraphicsTextItem class provides a text item that you can add to
9843     a QGraphicsScene to display formatted text.
9844     \since 4.2
9845     \ingroup graphicsview-api
9846 
9847     If you only need to show plain text in an item, consider using QGraphicsSimpleTextItem
9848     instead.
9849 
9850     To set the item's text, pass a QString to QGraphicsTextItem's
9851     constructor, or call setHtml()/setPlainText().
9852 
9853     QGraphicsTextItem uses the text's formatted size and the associated font
9854     to provide a reasonable implementation of boundingRect(), shape(),
9855     and contains(). You can set the font by calling setFont().
9856 
9857     It is possible to make the item editable by setting the Qt::TextEditorInteraction flag
9858     using setTextInteractionFlags().
9859 
9860     The item's preferred text width can be set using setTextWidth() and obtained
9861     using textWidth().
9862 
9863     \note In order to align HTML text in the center, the item's text width must be set.
9864 
9865     \img graphicsview-textitem.png
9866 
9867     \note QGraphicsTextItem accepts \l{QGraphicsItem::acceptHoverEvents()}{hover events}
9868           by default. You can change this with \l{QGraphicsItem::}{setAcceptHoverEvents()}.
9869 
9870     \sa QGraphicsSimpleTextItem, QGraphicsPathItem, QGraphicsRectItem,
9871         QGraphicsEllipseItem, QGraphicsPixmapItem, QGraphicsPolygonItem,
9872         QGraphicsLineItem, {Graphics View Framework}
9873 */
9874 
9875 class QGraphicsTextItemPrivate
9876 {
9877 public:
QGraphicsTextItemPrivate()9878     QGraphicsTextItemPrivate()
9879         : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false), clickCausedFocus(0)
9880     { }
9881 
9882     mutable QTextControl *control;
9883     QTextControl *textControl() const;
9884 
controlOffset() const9885     inline QPointF controlOffset() const
9886     { return QPointF(0., pageNumber * control->document()->pageSize().height()); }
sendControlEvent(QEvent * e)9887     inline void sendControlEvent(QEvent *e)
9888     { if (control) control->processEvent(e, controlOffset()); }
9889 
9890     void _q_updateBoundingRect(const QSizeF &);
9891     void _q_update(QRectF);
9892     void _q_ensureVisible(QRectF);
9893     bool _q_mouseOnEdge(QGraphicsSceneMouseEvent *);
9894 
9895     QRectF boundingRect;
9896     int pageNumber;
9897     bool useDefaultImpl;
9898     bool tabChangesFocus;
9899 
9900     uint clickCausedFocus : 1;
9901 
9902     QGraphicsTextItem *qq;
9903 };
9904 
9905 
9906 /*!
9907     Constructs a QGraphicsTextItem, using \a text as the default plain
9908     text. \a parent is passed to QGraphicsItem's constructor.
9909 
9910     \sa QGraphicsScene::addItem()
9911 */
QGraphicsTextItem(const QString & text,QGraphicsItem * parent,QGraphicsScene * scene)9912 QGraphicsTextItem::QGraphicsTextItem(const QString &text, QGraphicsItem *parent
9913 #ifndef Q_QDOC
9914                                      // obsolete argument
9915                                      , QGraphicsScene *scene
9916 #endif
9917     )
9918     : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
9919 {
9920     dd->qq = this;
9921     if (!text.isEmpty())
9922         setPlainText(text);
9923     setAcceptDrops(true);
9924     setAcceptHoverEvents(true);
9925     setFlags(ItemUsesExtendedStyleOption);
9926 }
9927 
9928 /*!
9929     Constructs a QGraphicsTextItem. \a parent is passed to QGraphicsItem's
9930     constructor.
9931 
9932     \sa QGraphicsScene::addItem()
9933 */
QGraphicsTextItem(QGraphicsItem * parent,QGraphicsScene * scene)9934 QGraphicsTextItem::QGraphicsTextItem(QGraphicsItem *parent
9935 #ifndef Q_QDOC
9936                                      // obsolete argument
9937                                      , QGraphicsScene *scene
9938 #endif
9939     )
9940     : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
9941 {
9942     dd->qq = this;
9943     setAcceptDrops(true);
9944     setAcceptHoverEvents(true);
9945     setFlag(ItemUsesExtendedStyleOption);
9946 }
9947 
9948 /*!
9949     Destroys the QGraphicsTextItem.
9950 */
~QGraphicsTextItem()9951 QGraphicsTextItem::~QGraphicsTextItem()
9952 {
9953     delete dd;
9954 }
9955 
9956 /*!
9957     Returns the item's text converted to HTML, or an empty QString if no text has been set.
9958 
9959     \sa setHtml()
9960 */
toHtml() const9961 QString QGraphicsTextItem::toHtml() const
9962 {
9963 #ifndef QT_NO_TEXTHTMLPARSER
9964     if (dd->control)
9965         return dd->control->toHtml();
9966 #endif
9967     return QString();
9968 }
9969 
9970 /*!
9971     Sets the item's text to \a text, assuming that text is HTML formatted. If
9972     the item has keyboard input focus, this function will also call
9973     ensureVisible() to ensure that the text is visible in all viewports.
9974 
9975     \sa toHtml(), hasFocus(), QGraphicsSimpleTextItem
9976 */
setHtml(const QString & text)9977 void QGraphicsTextItem::setHtml(const QString &text)
9978 {
9979     dd->textControl()->setHtml(text);
9980 }
9981 
9982 /*!
9983     Returns the item's text converted to plain text, or an empty QString if no text has been set.
9984 
9985     \sa setPlainText()
9986 */
toPlainText() const9987 QString QGraphicsTextItem::toPlainText() const
9988 {
9989     if (dd->control)
9990         return dd->control->toPlainText();
9991     return QString();
9992 }
9993 
9994 /*!
9995     Sets the item's text to \a text. If the item has keyboard input focus,
9996     this function will also call ensureVisible() to ensure that the text is
9997     visible in all viewports.
9998 
9999     \sa toHtml(), hasFocus()
10000 */
setPlainText(const QString & text)10001 void QGraphicsTextItem::setPlainText(const QString &text)
10002 {
10003     dd->textControl()->setPlainText(text);
10004 }
10005 
10006 /*!
10007     Returns the item's font, which is used to render the text.
10008 
10009     \sa setFont()
10010 */
font() const10011 QFont QGraphicsTextItem::font() const
10012 {
10013     if (!dd->control)
10014         return QFont();
10015     return dd->control->document()->defaultFont();
10016 }
10017 
10018 /*!
10019     Sets the font used to render the text item to \a font.
10020 
10021     \sa font()
10022 */
setFont(const QFont & font)10023 void QGraphicsTextItem::setFont(const QFont &font)
10024 {
10025     dd->textControl()->document()->setDefaultFont(font);
10026 }
10027 
10028 /*!
10029     Sets the color for unformatted text to \a col.
10030 */
setDefaultTextColor(const QColor & col)10031 void QGraphicsTextItem::setDefaultTextColor(const QColor &col)
10032 {
10033     QTextControl *c = dd->textControl();
10034     QPalette pal = c->palette();
10035     QColor old = pal.color(QPalette::Text);
10036     pal.setColor(QPalette::Text, col);
10037     c->setPalette(pal);
10038     if (old != col)
10039         update();
10040 }
10041 
10042 /*!
10043     Returns the default text color that is used to for unformatted text.
10044 */
defaultTextColor() const10045 QColor QGraphicsTextItem::defaultTextColor() const
10046 {
10047     return dd->textControl()->palette().color(QPalette::Text);
10048 }
10049 
10050 /*!
10051     \reimp
10052 */
boundingRect() const10053 QRectF QGraphicsTextItem::boundingRect() const
10054 {
10055     return dd->boundingRect;
10056 }
10057 
10058 /*!
10059     \reimp
10060 */
shape() const10061 QPainterPath QGraphicsTextItem::shape() const
10062 {
10063     if (!dd->control)
10064         return QPainterPath();
10065     QPainterPath path;
10066     path.addRect(dd->boundingRect);
10067     return path;
10068 }
10069 
10070 /*!
10071     \reimp
10072 */
contains(const QPointF & point) const10073 bool QGraphicsTextItem::contains(const QPointF &point) const
10074 {
10075     return dd->boundingRect.contains(point);
10076 }
10077 
10078 /*!
10079     \reimp
10080 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)10081 void QGraphicsTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
10082                               QWidget *widget)
10083 {
10084     Q_UNUSED(widget);
10085     if (dd->control) {
10086         painter->save();
10087         QRectF r = option->exposedRect;
10088         painter->translate(-dd->controlOffset());
10089         r.translate(dd->controlOffset());
10090 
10091         QTextDocument *doc = dd->control->document();
10092         QTextDocumentLayout *layout = qobject_cast<QTextDocumentLayout *>(doc->documentLayout());
10093 
10094         // the layout might need to expand the root frame to
10095         // the viewport if NoWrap is set
10096         if (layout)
10097             layout->setViewport(dd->boundingRect);
10098 
10099         dd->control->drawContents(painter, r);
10100 
10101         if (layout)
10102             layout->setViewport(QRect());
10103 
10104         painter->restore();
10105     }
10106 
10107     if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus))
10108         qt_graphicsItem_highlightSelected(this, painter, option);
10109 }
10110 
10111 /*!
10112     \reimp
10113 */
isObscuredBy(const QGraphicsItem * item) const10114 bool QGraphicsTextItem::isObscuredBy(const QGraphicsItem *item) const
10115 {
10116     return QGraphicsItem::isObscuredBy(item);
10117 }
10118 
10119 /*!
10120     \reimp
10121 */
opaqueArea() const10122 QPainterPath QGraphicsTextItem::opaqueArea() const
10123 {
10124     return QGraphicsItem::opaqueArea();
10125 }
10126 
10127 /*!
10128     \reimp
10129 */
type() const10130 int QGraphicsTextItem::type() const
10131 {
10132     return Type;
10133 }
10134 
10135 /*!
10136     Sets the preferred width for the item's text. If the actual text
10137     is wider than the specified width then it will be broken into
10138     multiple lines.
10139 
10140     If \a width is set to -1 then the text will not be broken into
10141     multiple lines unless it is enforced through an explicit line
10142     break or a new paragraph.
10143 
10144     The default value is -1.
10145 
10146     Note that QGraphicsTextItem keeps a QTextDocument internally,
10147     which is used to calculate the text width.
10148 
10149     \sa textWidth(), QTextDocument::setTextWidth()
10150 */
setTextWidth(qreal width)10151 void QGraphicsTextItem::setTextWidth(qreal width)
10152 {
10153     dd->textControl()->setTextWidth(width);
10154 }
10155 
10156 /*!
10157     Returns the text width.
10158 
10159     The width is calculated with the QTextDocument that
10160     QGraphicsTextItem keeps internally.
10161 
10162     \sa setTextWidth(), QTextDocument::textWidth()
10163 */
textWidth() const10164 qreal QGraphicsTextItem::textWidth() const
10165 {
10166     if (!dd->control)
10167         return -1;
10168     return dd->control->textWidth();
10169 }
10170 
10171 /*!
10172     Adjusts the text item to a reasonable size.
10173 */
adjustSize()10174 void QGraphicsTextItem::adjustSize()
10175 {
10176     if (dd->control)
10177         dd->control->adjustSize();
10178 }
10179 
10180 /*!
10181     Sets the text document \a document on the item.
10182 */
setDocument(QTextDocument * document)10183 void QGraphicsTextItem::setDocument(QTextDocument *document)
10184 {
10185     dd->textControl()->setDocument(document);
10186     dd->_q_updateBoundingRect(dd->control->size());
10187 }
10188 
10189 /*!
10190     Returns the item's text document.
10191 */
document() const10192 QTextDocument *QGraphicsTextItem::document() const
10193 {
10194     return dd->textControl()->document();
10195 }
10196 
10197 /*!
10198     \reimp
10199 */
sceneEvent(QEvent * event)10200 bool QGraphicsTextItem::sceneEvent(QEvent *event)
10201 {
10202     QEvent::Type t = event->type();
10203     if (!dd->tabChangesFocus && (t == QEvent::KeyPress || t == QEvent::KeyRelease)) {
10204         int k = ((QKeyEvent *)event)->key();
10205         if (k == Qt::Key_Tab || k == Qt::Key_Backtab) {
10206             dd->sendControlEvent(event);
10207             return true;
10208         }
10209     }
10210     bool result = QGraphicsItem::sceneEvent(event);
10211 
10212     // Ensure input context is updated.
10213     switch (event->type()) {
10214     case QEvent::ContextMenu:
10215     case QEvent::FocusIn:
10216     case QEvent::FocusOut:
10217     case QEvent::GraphicsSceneDragEnter:
10218     case QEvent::GraphicsSceneDragLeave:
10219     case QEvent::GraphicsSceneDragMove:
10220     case QEvent::GraphicsSceneDrop:
10221     case QEvent::GraphicsSceneHoverEnter:
10222     case QEvent::GraphicsSceneHoverLeave:
10223     case QEvent::GraphicsSceneHoverMove:
10224     case QEvent::GraphicsSceneMouseDoubleClick:
10225     case QEvent::GraphicsSceneMousePress:
10226     case QEvent::GraphicsSceneMouseMove:
10227     case QEvent::GraphicsSceneMouseRelease:
10228     case QEvent::KeyPress:
10229     case QEvent::KeyRelease:
10230         // Reset the focus widget's input context, regardless
10231         // of how this item gained or lost focus.
10232         if (QWidget *fw = qApp->focusWidget()) {
10233 #ifndef QT_NO_IM
10234             if (QInputContext *qic = fw->inputContext()) {
10235                 if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)
10236                     qic->reset();
10237                 else
10238                     qic->update();
10239             }
10240 #endif //QT_NO_IM
10241         }
10242         break;
10243     case QEvent::ShortcutOverride:
10244         dd->sendControlEvent(event);
10245         return true;
10246     default:
10247         break;
10248     }
10249 
10250     return result;
10251 }
10252 
10253 /*!
10254     \reimp
10255 */
mousePressEvent(QGraphicsSceneMouseEvent * event)10256 void QGraphicsTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
10257 {
10258     if ((QGraphicsItem::d_ptr->flags & (ItemIsSelectable | ItemIsMovable))
10259         && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
10260         // User left-pressed on edge of selectable/movable item, use
10261         // base impl.
10262         dd->useDefaultImpl = true;
10263     } else if (event->buttons() == event->button()
10264                && dd->control->textInteractionFlags() == Qt::NoTextInteraction) {
10265         // User pressed first button on non-interactive item.
10266         dd->useDefaultImpl = true;
10267     }
10268     if (dd->useDefaultImpl) {
10269         QGraphicsItem::mousePressEvent(event);
10270         if (!event->isAccepted())
10271             dd->useDefaultImpl = false;
10272         return;
10273     }
10274 
10275     dd->sendControlEvent(event);
10276 }
10277 
10278 /*!
10279     \reimp
10280 */
mouseMoveEvent(QGraphicsSceneMouseEvent * event)10281 void QGraphicsTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
10282 {
10283     if (dd->useDefaultImpl) {
10284         QGraphicsItem::mouseMoveEvent(event);
10285         return;
10286     }
10287 
10288     dd->sendControlEvent(event);
10289 }
10290 
10291 /*!
10292     \reimp
10293 */
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)10294 void QGraphicsTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
10295 {
10296     if (dd->useDefaultImpl) {
10297         QGraphicsItem::mouseReleaseEvent(event);
10298         if (dd->control->textInteractionFlags() == Qt::NoTextInteraction
10299             && !event->buttons()) {
10300             // User released last button on non-interactive item.
10301             dd->useDefaultImpl = false;
10302         } else  if ((event->buttons() & Qt::LeftButton) == 0) {
10303             // User released the left button on an interactive item.
10304             dd->useDefaultImpl = false;
10305         }
10306         return;
10307     }
10308 
10309     QWidget *widget = event->widget();
10310     if (widget && (dd->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos())) {
10311         qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus);
10312     }
10313     dd->clickCausedFocus = 0;
10314     dd->sendControlEvent(event);
10315 }
10316 
10317 /*!
10318     \reimp
10319 */
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event)10320 void QGraphicsTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
10321 {
10322     if (dd->useDefaultImpl) {
10323         QGraphicsItem::mouseDoubleClickEvent(event);
10324         return;
10325     }
10326 
10327     if (!hasFocus()) {
10328         QGraphicsItem::mouseDoubleClickEvent(event);
10329         return;
10330     }
10331 
10332     dd->sendControlEvent(event);
10333 }
10334 
10335 /*!
10336     \reimp
10337 */
contextMenuEvent(QGraphicsSceneContextMenuEvent * event)10338 void QGraphicsTextItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
10339 {
10340     dd->sendControlEvent(event);
10341 }
10342 
10343 /*!
10344     \reimp
10345 */
keyPressEvent(QKeyEvent * event)10346 void QGraphicsTextItem::keyPressEvent(QKeyEvent *event)
10347 {
10348     dd->sendControlEvent(event);
10349 }
10350 
10351 /*!
10352     \reimp
10353 */
keyReleaseEvent(QKeyEvent * event)10354 void QGraphicsTextItem::keyReleaseEvent(QKeyEvent *event)
10355 {
10356     dd->sendControlEvent(event);
10357 }
10358 
10359 /*!
10360     \reimp
10361 */
focusInEvent(QFocusEvent * event)10362 void QGraphicsTextItem::focusInEvent(QFocusEvent *event)
10363 {
10364     dd->sendControlEvent(event);
10365     if (event->reason() == Qt::MouseFocusReason) {
10366         dd->clickCausedFocus = 1;
10367     }
10368     update();
10369 }
10370 
10371 /*!
10372     \reimp
10373 */
focusOutEvent(QFocusEvent * event)10374 void QGraphicsTextItem::focusOutEvent(QFocusEvent *event)
10375 {
10376     dd->sendControlEvent(event);
10377     update();
10378 }
10379 
10380 /*!
10381     \reimp
10382 */
dragEnterEvent(QGraphicsSceneDragDropEvent * event)10383 void QGraphicsTextItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
10384 {
10385     dd->sendControlEvent(event);
10386 }
10387 
10388 /*!
10389     \reimp
10390 */
dragLeaveEvent(QGraphicsSceneDragDropEvent * event)10391 void QGraphicsTextItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
10392 {
10393     dd->sendControlEvent(event);
10394 }
10395 
10396 /*!
10397     \reimp
10398 */
dragMoveEvent(QGraphicsSceneDragDropEvent * event)10399 void QGraphicsTextItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
10400 {
10401     dd->sendControlEvent(event);
10402 }
10403 
10404 /*!
10405     \reimp
10406 */
dropEvent(QGraphicsSceneDragDropEvent * event)10407 void QGraphicsTextItem::dropEvent(QGraphicsSceneDragDropEvent *event)
10408 {
10409     dd->sendControlEvent(event);
10410 }
10411 
10412 /*!
10413     \reimp
10414 */
inputMethodEvent(QInputMethodEvent * event)10415 void QGraphicsTextItem::inputMethodEvent(QInputMethodEvent *event)
10416 {
10417     dd->sendControlEvent(event);
10418 }
10419 
10420 /*!
10421     \reimp
10422 */
hoverEnterEvent(QGraphicsSceneHoverEvent * event)10423 void QGraphicsTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
10424 {
10425     dd->sendControlEvent(event);
10426 }
10427 
10428 /*!
10429     \reimp
10430 */
hoverMoveEvent(QGraphicsSceneHoverEvent * event)10431 void QGraphicsTextItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
10432 {
10433     dd->sendControlEvent(event);
10434 }
10435 
10436 /*!
10437     \reimp
10438 */
hoverLeaveEvent(QGraphicsSceneHoverEvent * event)10439 void QGraphicsTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
10440 {
10441     dd->sendControlEvent(event);
10442 }
10443 
10444 /*!
10445     \reimp
10446 */
inputMethodQuery(Qt::InputMethodQuery query) const10447 QVariant QGraphicsTextItem::inputMethodQuery(Qt::InputMethodQuery query) const
10448 {
10449     QVariant v;
10450     if (dd->control)
10451         v = dd->control->inputMethodQuery(query);
10452     if (v.type() == QVariant::RectF)
10453         v = v.toRectF().translated(-dd->controlOffset());
10454     else if (v.type() == QVariant::PointF)
10455         v = v.toPointF() - dd->controlOffset();
10456     else if (v.type() == QVariant::Rect)
10457         v = v.toRect().translated(-dd->controlOffset().toPoint());
10458     else if (v.type() == QVariant::Point)
10459         v = v.toPoint() - dd->controlOffset().toPoint();
10460     return v;
10461 }
10462 
10463 /*!
10464     \internal
10465 */
supportsExtension(Extension extension) const10466 bool QGraphicsTextItem::supportsExtension(Extension extension) const
10467 {
10468     Q_UNUSED(extension);
10469     return false;
10470 }
10471 
10472 /*!
10473     \internal
10474 */
setExtension(Extension extension,const QVariant & variant)10475 void QGraphicsTextItem::setExtension(Extension extension, const QVariant &variant)
10476 {
10477     Q_UNUSED(extension);
10478     Q_UNUSED(variant);
10479 }
10480 
10481 /*!
10482     \internal
10483 */
extension(const QVariant & variant) const10484 QVariant QGraphicsTextItem::extension(const QVariant &variant) const
10485 {
10486     Q_UNUSED(variant);
10487     return QVariant();
10488 }
10489 
10490 /*!
10491     \internal
10492 */
_q_update(QRectF rect)10493 void QGraphicsTextItemPrivate::_q_update(QRectF rect)
10494 {
10495     if (rect.isValid()) {
10496         rect.translate(-controlOffset());
10497     } else {
10498         rect = boundingRect;
10499     }
10500     if (rect.intersects(boundingRect))
10501         qq->update(rect);
10502 }
10503 
10504 /*!
10505     \internal
10506 */
_q_updateBoundingRect(const QSizeF & size)10507 void QGraphicsTextItemPrivate::_q_updateBoundingRect(const QSizeF &size)
10508 {
10509     if (!control) return; // can't happen
10510     const QSizeF pageSize = control->document()->pageSize();
10511     // paged items have a constant (page) size
10512     if (size == boundingRect.size() || pageSize.height() != -1)
10513         return;
10514     qq->prepareGeometryChange();
10515     boundingRect.setSize(size);
10516     qq->update();
10517 }
10518 
10519 /*!
10520     \internal
10521 */
_q_ensureVisible(QRectF rect)10522 void QGraphicsTextItemPrivate::_q_ensureVisible(QRectF rect)
10523 {
10524     if (qq->hasFocus()) {
10525         rect.translate(-controlOffset());
10526         qq->ensureVisible(rect, /*xmargin=*/0, /*ymargin=*/0);
10527     }
10528 }
10529 
textControl() const10530 QTextControl *QGraphicsTextItemPrivate::textControl() const
10531 {
10532     if (!control) {
10533         QGraphicsTextItem *that = const_cast<QGraphicsTextItem *>(qq);
10534         control = new QTextControl(that);
10535         control->setTextInteractionFlags(Qt::NoTextInteraction);
10536 
10537         QObject::connect(control, SIGNAL(updateRequest(QRectF)),
10538                          qq, SLOT(_q_update(QRectF)));
10539         QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)),
10540                          qq, SLOT(_q_updateBoundingRect(QSizeF)));
10541         QObject::connect(control, SIGNAL(visibilityRequest(QRectF)),
10542                          qq, SLOT(_q_ensureVisible(QRectF)));
10543         QObject::connect(control, SIGNAL(linkActivated(QString)),
10544                          qq, SIGNAL(linkActivated(QString)));
10545         QObject::connect(control, SIGNAL(linkHovered(QString)),
10546                          qq, SIGNAL(linkHovered(QString)));
10547 
10548         const QSizeF pgSize = control->document()->pageSize();
10549         if (pgSize.height() != -1) {
10550             qq->prepareGeometryChange();
10551             that->dd->boundingRect.setSize(pgSize);
10552             qq->update();
10553         } else {
10554             that->dd->_q_updateBoundingRect(control->size());
10555         }
10556     }
10557     return control;
10558 }
10559 
10560 /*!
10561     \internal
10562 */
_q_mouseOnEdge(QGraphicsSceneMouseEvent * event)10563 bool QGraphicsTextItemPrivate::_q_mouseOnEdge(QGraphicsSceneMouseEvent *event)
10564 {
10565     QPainterPath path;
10566     path.addRect(qq->boundingRect());
10567 
10568     QPainterPath docPath;
10569     const QTextFrameFormat format = control->document()->rootFrame()->frameFormat();
10570     docPath.addRect(
10571         qq->boundingRect().adjusted(
10572             format.leftMargin(),
10573             format.topMargin(),
10574             -format.rightMargin(),
10575             -format.bottomMargin()));
10576 
10577     return path.subtracted(docPath).contains(event->pos());
10578 }
10579 
10580 /*!
10581     \fn QGraphicsTextItem::linkActivated(const QString &link)
10582 
10583     This signal is emitted when the user clicks on a link on a text item
10584     that enables Qt::LinksAccessibleByMouse or Qt::LinksAccessibleByKeyboard.
10585     \a link is the link that was clicked.
10586 
10587     \sa setTextInteractionFlags()
10588 */
10589 
10590 /*!
10591     \fn QGraphicsTextItem::linkHovered(const QString &link)
10592 
10593     This signal is emitted when the user hovers over a link on a text item
10594     that enables Qt::LinksAccessibleByMouse. \a link is
10595     the link that was hovered over.
10596 
10597     \sa setTextInteractionFlags()
10598 */
10599 
10600 /*!
10601     Sets the flags \a flags to specify how the text item should react to user
10602     input.
10603 
10604     The default for a QGraphicsTextItem is Qt::NoTextInteraction. This function
10605     also affects the ItemIsFocusable QGraphicsItem flag by setting it if \a flags
10606     is different from Qt::NoTextInteraction and clearing it otherwise.
10607 
10608     By default, the text is read-only. To transform the item into an editor,
10609     set the Qt::TextEditable flag.
10610 */
setTextInteractionFlags(Qt::TextInteractionFlags flags)10611 void QGraphicsTextItem::setTextInteractionFlags(Qt::TextInteractionFlags flags)
10612 {
10613     if (flags == Qt::NoTextInteraction)
10614         setFlags(this->flags() & ~(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod));
10615     else
10616         setFlags(this->flags() | QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
10617 
10618     dd->textControl()->setTextInteractionFlags(flags);
10619 }
10620 
10621 /*!
10622     Returns the current text interaction flags.
10623 
10624     \sa setTextInteractionFlags()
10625 */
textInteractionFlags() const10626 Qt::TextInteractionFlags QGraphicsTextItem::textInteractionFlags() const
10627 {
10628     if (!dd->control)
10629         return Qt::NoTextInteraction;
10630     return dd->control->textInteractionFlags();
10631 }
10632 
10633 /*!
10634     \since 4.5
10635 
10636     If \a b is true, the \gui Tab key will cause the widget to change focus;
10637     otherwise, the tab key will insert a tab into the document.
10638 
10639     In some occasions text edits should not allow the user to input tabulators
10640     or change indentation using the \gui Tab key, as this breaks the focus
10641     chain. The default is false.
10642 
10643     \sa tabChangesFocus(), ItemIsFocusable, textInteractionFlags()
10644 */
setTabChangesFocus(bool b)10645 void QGraphicsTextItem::setTabChangesFocus(bool b)
10646 {
10647     dd->tabChangesFocus = b;
10648 }
10649 
10650 /*!
10651     \since 4.5
10652 
10653     Returns true if the \gui Tab key will cause the widget to change focus;
10654     otherwise, false is returned.
10655 
10656     By default, this behavior is disabled, and this function will return false.
10657 
10658     \sa setTabChangesFocus()
10659 */
tabChangesFocus() const10660 bool QGraphicsTextItem::tabChangesFocus() const
10661 {
10662     return dd->tabChangesFocus;
10663 }
10664 
10665 /*!
10666     \property QGraphicsTextItem::openExternalLinks
10667 
10668     Specifies whether QGraphicsTextItem should automatically open links using
10669     QDesktopServices::openUrl() instead of emitting the
10670     linkActivated signal.
10671 
10672     The default value is false.
10673 */
setOpenExternalLinks(bool open)10674 void QGraphicsTextItem::setOpenExternalLinks(bool open)
10675 {
10676     dd->textControl()->setOpenExternalLinks(open);
10677 }
10678 
openExternalLinks() const10679 bool QGraphicsTextItem::openExternalLinks() const
10680 {
10681     if (!dd->control)
10682         return false;
10683     return dd->control->openExternalLinks();
10684 }
10685 
10686 /*!
10687     \property QGraphicsTextItem::textCursor
10688 
10689     This property represents the visible text cursor in an editable
10690     text item.
10691 
10692     By default, if the item's text has not been set, this property
10693     contains a null text cursor; otherwise it contains a text cursor
10694     placed at the start of the item's document.
10695 */
setTextCursor(const QTextCursor & cursor)10696 void QGraphicsTextItem::setTextCursor(const QTextCursor &cursor)
10697 {
10698     dd->textControl()->setTextCursor(cursor);
10699 }
10700 
textCursor() const10701 QTextCursor QGraphicsTextItem::textCursor() const
10702 {
10703     if (!dd->control)
10704         return QTextCursor();
10705     return dd->control->textCursor();
10706 }
10707 
10708 class QGraphicsSimpleTextItemPrivate : public QAbstractGraphicsShapeItemPrivate
10709 {
10710     Q_DECLARE_PUBLIC(QGraphicsSimpleTextItem)
10711 public:
QGraphicsSimpleTextItemPrivate()10712     inline QGraphicsSimpleTextItemPrivate() {
10713         pen.setStyle(Qt::NoPen);
10714         brush.setStyle(Qt::SolidPattern);
10715     }
10716     QString text;
10717     QFont font;
10718     QRectF boundingRect;
10719 
10720     void updateBoundingRect();
10721 };
10722 
setupTextLayout(QTextLayout * layout)10723 static QRectF setupTextLayout(QTextLayout *layout)
10724 {
10725     layout->setCacheEnabled(true);
10726     layout->beginLayout();
10727     while (layout->createLine().isValid())
10728         ;
10729     layout->endLayout();
10730     qreal maxWidth = 0;
10731     qreal y = 0;
10732     for (int i = 0; i < layout->lineCount(); ++i) {
10733         QTextLine line = layout->lineAt(i);
10734         maxWidth = qMax(maxWidth, line.naturalTextWidth());
10735         line.setPosition(QPointF(0, y));
10736         y += line.height();
10737     }
10738     return QRectF(0, 0, maxWidth, y);
10739 }
10740 
updateBoundingRect()10741 void QGraphicsSimpleTextItemPrivate::updateBoundingRect()
10742 {
10743     Q_Q(QGraphicsSimpleTextItem);
10744     QRectF br;
10745     if (text.isEmpty()) {
10746         br = QRectF();
10747     } else {
10748         QString tmp = text;
10749         tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
10750         QStackTextEngine engine(tmp, font);
10751         QTextLayout layout(&engine);
10752         br = setupTextLayout(&layout);
10753     }
10754     if (br != boundingRect) {
10755         q->prepareGeometryChange();
10756         boundingRect = br;
10757         q->update();
10758     }
10759 }
10760 
10761 /*!
10762     \class QGraphicsSimpleTextItem
10763     \brief The QGraphicsSimpleTextItem class provides a simple text path item
10764     that you can add to a QGraphicsScene.
10765     \since 4.2
10766     \ingroup graphicsview-api
10767 
10768     To set the item's text, you can either pass a QString to
10769     QGraphicsSimpleTextItem's constructor, or call setText() to change the
10770     text later. To set the text fill color, call setBrush().
10771 
10772     The simple text item can have both a fill and an outline; setBrush() will
10773     set the text fill (i.e., text color), and setPen() sets the pen that will
10774     be used to draw the text outline. (The latter can be slow, especially for
10775     complex pens, and items with long text content.) If all you want is to
10776     draw a simple line of text, you should call setBrush() only, and leave the
10777     pen unset; QGraphicsSimpleTextItem's pen is by default Qt::NoPen.
10778 
10779     QGraphicsSimpleTextItem uses the text's formatted size and the associated
10780     font to provide a reasonable implementation of boundingRect(), shape(),
10781     and contains(). You can set the font by calling setFont().
10782 
10783     QGraphicsSimpleText does not display rich text; instead, you can use
10784     QGraphicsTextItem, which provides full text control capabilities.
10785 
10786     \img graphicsview-simpletextitem.png
10787 
10788     \sa QGraphicsTextItem, QGraphicsPathItem, QGraphicsRectItem,
10789     QGraphicsEllipseItem, QGraphicsPixmapItem, QGraphicsPolygonItem,
10790     QGraphicsLineItem, {Graphics View Framework}
10791 */
10792 
10793 /*!
10794     Constructs a QGraphicsSimpleTextItem.
10795 
10796     \a parent is passed to QGraphicsItem's constructor.
10797 
10798     \sa QGraphicsScene::addItem()
10799 */
QGraphicsSimpleTextItem(QGraphicsItem * parent,QGraphicsScene * scene)10800 QGraphicsSimpleTextItem::QGraphicsSimpleTextItem(QGraphicsItem *parent
10801 #ifndef Q_QDOC
10802                                                  // obsolete argument
10803                                                  , QGraphicsScene *scene
10804 #endif
10805     )
10806     : QAbstractGraphicsShapeItem(*new QGraphicsSimpleTextItemPrivate, parent, scene)
10807 {
10808 }
10809 
10810 /*!
10811     Constructs a QGraphicsSimpleTextItem, using \a text as the default plain text.
10812 
10813     \a parent is passed to QGraphicsItem's constructor.
10814 
10815     \sa QGraphicsScene::addItem()
10816 */
QGraphicsSimpleTextItem(const QString & text,QGraphicsItem * parent,QGraphicsScene * scene)10817 QGraphicsSimpleTextItem::QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent
10818 #ifndef Q_QDOC
10819                                                  // obsolete argument
10820                                                  , QGraphicsScene *scene
10821 #endif
10822     )
10823     : QAbstractGraphicsShapeItem(*new QGraphicsSimpleTextItemPrivate, parent, scene)
10824 {
10825     setText(text);
10826 }
10827 
10828 /*!
10829     Destroys the QGraphicsSimpleTextItem.
10830 */
~QGraphicsSimpleTextItem()10831 QGraphicsSimpleTextItem::~QGraphicsSimpleTextItem()
10832 {
10833 }
10834 
10835 /*!
10836     Sets the item's text to \a text. The text will be displayed as
10837     plain text. Newline characters ('\n') as well as characters of
10838     type QChar::LineSeparator will cause item to break the text into
10839     multiple lines.
10840 */
setText(const QString & text)10841 void QGraphicsSimpleTextItem::setText(const QString &text)
10842 {
10843     Q_D(QGraphicsSimpleTextItem);
10844     if (d->text == text)
10845         return;
10846     d->text = text;
10847     d->updateBoundingRect();
10848     update();
10849 }
10850 
10851 /*!
10852     Returns the item's text.
10853 */
text() const10854 QString QGraphicsSimpleTextItem::text() const
10855 {
10856     Q_D(const QGraphicsSimpleTextItem);
10857     return d->text;
10858 }
10859 
10860 /*!
10861     Sets the font that is used to draw the item's text to \a font.
10862 */
setFont(const QFont & font)10863 void QGraphicsSimpleTextItem::setFont(const QFont &font)
10864 {
10865     Q_D(QGraphicsSimpleTextItem);
10866     d->font = font;
10867     d->updateBoundingRect();
10868 }
10869 
10870 /*!
10871     Returns the font that is used to draw the item's text.
10872 */
font() const10873 QFont QGraphicsSimpleTextItem::font() const
10874 {
10875     Q_D(const QGraphicsSimpleTextItem);
10876     return d->font;
10877 }
10878 
10879 /*!
10880     \reimp
10881 */
boundingRect() const10882 QRectF QGraphicsSimpleTextItem::boundingRect() const
10883 {
10884     Q_D(const QGraphicsSimpleTextItem);
10885     return d->boundingRect;
10886 }
10887 
10888 /*!
10889     \reimp
10890 */
shape() const10891 QPainterPath QGraphicsSimpleTextItem::shape() const
10892 {
10893     Q_D(const QGraphicsSimpleTextItem);
10894     QPainterPath path;
10895     path.addRect(d->boundingRect);
10896     return path;
10897 }
10898 
10899 /*!
10900     \reimp
10901 */
contains(const QPointF & point) const10902 bool QGraphicsSimpleTextItem::contains(const QPointF &point) const
10903 {
10904     Q_D(const QGraphicsSimpleTextItem);
10905     return d->boundingRect.contains(point);
10906 }
10907 
10908 /*!
10909     \reimp
10910 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)10911 void QGraphicsSimpleTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
10912 {
10913     Q_UNUSED(widget);
10914     Q_D(QGraphicsSimpleTextItem);
10915 
10916     painter->setFont(d->font);
10917 
10918     QString tmp = d->text;
10919     tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
10920     QStackTextEngine engine(tmp, d->font);
10921     QTextLayout layout(&engine);
10922     setupTextLayout(&layout);
10923 
10924     QPen p;
10925     p.setBrush(d->brush);
10926     painter->setPen(p);
10927     if (d->pen.style() == Qt::NoPen && d->brush.style() == Qt::SolidPattern) {
10928         painter->setBrush(Qt::NoBrush);
10929     } else {
10930         QTextLayout::FormatRange range;
10931         range.start = 0;
10932         range.length = layout.text().length();
10933         range.format.setTextOutline(d->pen);
10934         QList<QTextLayout::FormatRange> formats;
10935         formats.append(range);
10936         layout.setAdditionalFormats(formats);
10937     }
10938 
10939     layout.draw(painter, QPointF(0, 0));
10940 
10941     if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus))
10942         qt_graphicsItem_highlightSelected(this, painter, option);
10943 }
10944 
10945 /*!
10946     \reimp
10947 */
isObscuredBy(const QGraphicsItem * item) const10948 bool QGraphicsSimpleTextItem::isObscuredBy(const QGraphicsItem *item) const
10949 {
10950     return QAbstractGraphicsShapeItem::isObscuredBy(item);
10951 }
10952 
10953 /*!
10954     \reimp
10955 */
opaqueArea() const10956 QPainterPath QGraphicsSimpleTextItem::opaqueArea() const
10957 {
10958     return QAbstractGraphicsShapeItem::opaqueArea();
10959 }
10960 
10961 /*!
10962     \reimp
10963 */
type() const10964 int QGraphicsSimpleTextItem::type() const
10965 {
10966     return Type;
10967 }
10968 
10969 /*!
10970     \internal
10971 */
supportsExtension(Extension extension) const10972 bool QGraphicsSimpleTextItem::supportsExtension(Extension extension) const
10973 {
10974     Q_UNUSED(extension);
10975     return false;
10976 }
10977 
10978 /*!
10979     \internal
10980 */
setExtension(Extension extension,const QVariant & variant)10981 void QGraphicsSimpleTextItem::setExtension(Extension extension, const QVariant &variant)
10982 {
10983     Q_UNUSED(extension);
10984     Q_UNUSED(variant);
10985 }
10986 
10987 /*!
10988     \internal
10989 */
extension(const QVariant & variant) const10990 QVariant QGraphicsSimpleTextItem::extension(const QVariant &variant) const
10991 {
10992     Q_UNUSED(variant);
10993     return QVariant();
10994 }
10995 
10996 /*!
10997     \class QGraphicsItemGroup
10998     \brief The QGraphicsItemGroup class provides a container that treats
10999     a group of items as a single item.
11000     \since 4.2
11001     \ingroup graphicsview-api
11002 
11003     A QGraphicsItemGroup is a special type of compound item that
11004     treats itself and all its children as one item (i.e., all events
11005     and geometries for all children are merged together). It's common
11006     to use item groups in presentation tools, when the user wants to
11007     group several smaller items into one big item in order to simplify
11008     moving and copying of items.
11009 
11010     If all you want is to store items inside other items, you can use
11011     any QGraphicsItem directly by passing a suitable parent to
11012     setParentItem().
11013 
11014     The boundingRect() function of QGraphicsItemGroup returns the
11015     bounding rectangle of all items in the item group.
11016     QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on
11017     its children (i.e., with respect to the geometry of the group
11018     item, the children are treated as if they were transformable).
11019 
11020     There are two ways to construct an item group. The easiest and
11021     most common approach is to pass a list of items (e.g., all
11022     selected items) to QGraphicsScene::createItemGroup(), which
11023     returns a new QGraphicsItemGroup item. The other approach is to
11024     manually construct a QGraphicsItemGroup item, add it to the scene
11025     calling QGraphicsScene::addItem(), and then add items to the group
11026     manually, one at a time by calling addToGroup(). To dismantle
11027     ("ungroup") an item group, you can either call
11028     QGraphicsScene::destroyItemGroup(), or you can manually remove all
11029     items from the group by calling removeFromGroup().
11030 
11031     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 17
11032 
11033     The operation of adding and removing items preserves the items'
11034     scene-relative position and transformation, as opposed to calling
11035     setParentItem(), where only the child item's parent-relative
11036     position and transformation are kept.
11037 
11038     The addtoGroup() function reparents the target item to this item
11039     group, keeping the item's position and transformation intact
11040     relative to the scene. Visually, this means that items added via
11041     addToGroup() will remain completely unchanged as a result of this
11042     operation, regardless of the item or the group's current position
11043     or transformation; although the item's position and matrix are
11044     likely to change.
11045 
11046     The removeFromGroup() function has similar semantics to
11047     setParentItem(); it reparents the item to the parent item of the
11048     item group. As with addToGroup(), the item's scene-relative
11049     position and transformation remain intact.
11050 
11051     \sa QGraphicsItem, {Graphics View Framework}
11052 */
11053 
11054 class QGraphicsItemGroupPrivate : public QGraphicsItemPrivate
11055 {
11056 public:
11057     QRectF itemsBoundingRect;
11058 };
11059 
11060 /*!
11061     Constructs a QGraphicsItemGroup. \a parent is passed to QGraphicsItem's
11062     constructor.
11063 
11064     \sa QGraphicsScene::addItem()
11065 */
QGraphicsItemGroup(QGraphicsItem * parent,QGraphicsScene * scene)11066 QGraphicsItemGroup::QGraphicsItemGroup(QGraphicsItem *parent
11067 #ifndef Q_QDOC
11068                                        // obsolete argument
11069                                        , QGraphicsScene *scene
11070 #endif
11071     )
11072     : QGraphicsItem(*new QGraphicsItemGroupPrivate, parent, scene)
11073 {
11074     setHandlesChildEvents(true);
11075 }
11076 
11077 /*!
11078     Destroys the QGraphicsItemGroup.
11079 */
~QGraphicsItemGroup()11080 QGraphicsItemGroup::~QGraphicsItemGroup()
11081 {
11082 }
11083 
11084 /*!
11085     Adds the given \a item and item's child items to this item group.
11086     The item and child items will be reparented to this group, but its
11087     position and transformation relative to the scene will stay intact.
11088 
11089     \sa removeFromGroup(), QGraphicsScene::createItemGroup()
11090 */
addToGroup(QGraphicsItem * item)11091 void QGraphicsItemGroup::addToGroup(QGraphicsItem *item)
11092 {
11093     Q_D(QGraphicsItemGroup);
11094     if (!item) {
11095         qWarning("QGraphicsItemGroup::addToGroup: cannot add null item");
11096         return;
11097     }
11098     if (item == this) {
11099         qWarning("QGraphicsItemGroup::addToGroup: cannot add a group to itself");
11100         return;
11101     }
11102 
11103     // COMBINE
11104     bool ok;
11105     QTransform itemTransform = item->itemTransform(this, &ok);
11106 
11107     if (!ok) {
11108         qWarning("QGraphicsItemGroup::addToGroup: could not find a valid transformation from item to group coordinates");
11109         return;
11110     }
11111 
11112     QTransform newItemTransform(itemTransform);
11113     item->setPos(mapFromItem(item, 0, 0));
11114     item->setParentItem(this);
11115 
11116     // removing position from translation component of the new transform
11117     if (!item->pos().isNull())
11118         newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
11119 
11120     // removing additional transformations properties applied with itemTransform()
11121     QPointF origin = item->transformOriginPoint();
11122     QMatrix4x4 m;
11123     QList<QGraphicsTransform*> transformList = item->transformations();
11124     for (int i = 0; i < transformList.size(); ++i)
11125         transformList.at(i)->applyTo(&m);
11126     newItemTransform *= m.toTransform().inverted();
11127     newItemTransform.translate(origin.x(), origin.y());
11128     newItemTransform.rotate(-item->rotation());
11129     newItemTransform.scale(1/item->scale(), 1/item->scale());
11130     newItemTransform.translate(-origin.x(), -origin.y());
11131 
11132     // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
11133 
11134     item->setTransform(newItemTransform);
11135     item->d_func()->setIsMemberOfGroup(true);
11136     prepareGeometryChange();
11137     d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect());
11138     update();
11139 }
11140 
11141 /*!
11142     Removes the specified \a item from this group. The item will be
11143     reparented to this group's parent item, or to 0 if this group has
11144     no parent.  Its position and transformation relative to the scene
11145     will stay intact.
11146 
11147     \sa addToGroup(), QGraphicsScene::destroyItemGroup()
11148 */
removeFromGroup(QGraphicsItem * item)11149 void QGraphicsItemGroup::removeFromGroup(QGraphicsItem *item)
11150 {
11151     Q_D(QGraphicsItemGroup);
11152     if (!item) {
11153         qWarning("QGraphicsItemGroup::removeFromGroup: cannot remove null item");
11154         return;
11155     }
11156 
11157     QGraphicsItem *newParent = d_ptr->parent;
11158 
11159     // COMBINE
11160     bool ok;
11161     QTransform itemTransform;
11162     if (newParent)
11163         itemTransform = item->itemTransform(newParent, &ok);
11164     else
11165         itemTransform = item->sceneTransform();
11166 
11167     QPointF oldPos = item->mapToItem(newParent, 0, 0);
11168     item->setParentItem(newParent);
11169     item->setPos(oldPos);
11170 
11171     // removing position from translation component of the new transform
11172     if (!item->pos().isNull())
11173         itemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
11174 
11175     // removing additional transformations properties applied
11176     // with itemTransform() or sceneTransform()
11177     QPointF origin = item->transformOriginPoint();
11178     QMatrix4x4 m;
11179     QList<QGraphicsTransform*> transformList = item->transformations();
11180     for (int i = 0; i < transformList.size(); ++i)
11181         transformList.at(i)->applyTo(&m);
11182     itemTransform *= m.toTransform().inverted();
11183     itemTransform.translate(origin.x(), origin.y());
11184     itemTransform.rotate(-item->rotation());
11185     itemTransform.scale(1 / item->scale(), 1 / item->scale());
11186     itemTransform.translate(-origin.x(), -origin.y());
11187 
11188     // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
11189 
11190     item->setTransform(itemTransform);
11191     item->d_func()->setIsMemberOfGroup(item->group() != 0);
11192 
11193     // ### Quite expensive. But removeFromGroup() isn't called very often.
11194     prepareGeometryChange();
11195     d->itemsBoundingRect = childrenBoundingRect();
11196 }
11197 
11198 /*!
11199     \reimp
11200 
11201     Returns the bounding rect of this group item, and all its children.
11202 */
boundingRect() const11203 QRectF QGraphicsItemGroup::boundingRect() const
11204 {
11205     Q_D(const QGraphicsItemGroup);
11206     return d->itemsBoundingRect;
11207 }
11208 
11209 /*!
11210     \reimp
11211 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)11212 void QGraphicsItemGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
11213                                QWidget *widget)
11214 {
11215     Q_UNUSED(widget);
11216     if (option->state & QStyle::State_Selected) {
11217         Q_D(QGraphicsItemGroup);
11218         painter->setBrush(Qt::NoBrush);
11219         painter->drawRect(d->itemsBoundingRect);
11220     }
11221 }
11222 
11223 /*!
11224     \reimp
11225 */
isObscuredBy(const QGraphicsItem * item) const11226 bool QGraphicsItemGroup::isObscuredBy(const QGraphicsItem *item) const
11227 {
11228     return QGraphicsItem::isObscuredBy(item);
11229 }
11230 
11231 /*!
11232     \reimp
11233 */
opaqueArea() const11234 QPainterPath QGraphicsItemGroup::opaqueArea() const
11235 {
11236     return QGraphicsItem::opaqueArea();
11237 }
11238 
11239 /*!
11240     \reimp
11241 */
type() const11242 int QGraphicsItemGroup::type() const
11243 {
11244     return Type;
11245 }
11246 
11247 #ifndef QT_NO_GRAPHICSEFFECT
boundingRect(Qt::CoordinateSystem system) const11248 QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
11249 {
11250     const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
11251     if (!info && deviceCoordinates) {
11252         // Device coordinates without info not yet supported.
11253         qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
11254         return QRectF();
11255     }
11256 
11257     QRectF rect = item->boundingRect();
11258     if (!item->d_ptr->children.isEmpty())
11259         rect |= item->childrenBoundingRect();
11260 
11261     if (deviceCoordinates) {
11262         Q_ASSERT(info->painter);
11263         rect = info->painter->worldTransform().mapRect(rect);
11264     }
11265 
11266     return rect;
11267 }
11268 
draw(QPainter * painter)11269 void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
11270 {
11271     if (!info) {
11272         qWarning("QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw");
11273         return;
11274     }
11275 
11276     Q_ASSERT(item->d_ptr->scene);
11277     QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
11278     if (painter == info->painter) {
11279         scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
11280                      info->widget, info->opacity, info->effectTransform, info->wasDirtySceneTransform,
11281                      info->drawItem);
11282     } else {
11283         QTransform effectTransform = info->painter->worldTransform().inverted();
11284         effectTransform *= painter->worldTransform();
11285         scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
11286                      info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
11287                      info->drawItem);
11288     }
11289 }
11290 
11291 // sourceRect must be in the given coordinate system
paddedEffectRect(Qt::CoordinateSystem system,QGraphicsEffect::PixmapPadMode mode,const QRectF & sourceRect,bool * unpadded) const11292 QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
11293 {
11294     QRectF effectRectF;
11295 
11296     if (unpadded)
11297         *unpadded = false;
11298 
11299     if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) {
11300         if (info) {
11301             QRectF deviceRect = system == Qt::DeviceCoordinates ? sourceRect : info->painter->worldTransform().mapRect(sourceRect);
11302             effectRectF = item->graphicsEffect()->boundingRectFor(deviceRect);
11303             if (unpadded)
11304                 *unpadded = (effectRectF.size() == sourceRect.size());
11305             if (info && system == Qt::LogicalCoordinates)
11306                 effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF);
11307         } else {
11308             // no choice but to send a logical coordinate bounding rect to boundingRectFor
11309             effectRectF = item->graphicsEffect()->boundingRectFor(sourceRect);
11310         }
11311     } else if (mode == QGraphicsEffect::PadToTransparentBorder) {
11312         // adjust by 1.5 to account for cosmetic pens
11313         effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5);
11314     } else {
11315         effectRectF = sourceRect;
11316         if (unpadded)
11317             *unpadded = true;
11318     }
11319 
11320     return effectRectF.toAlignedRect();
11321 }
11322 
pixmap(Qt::CoordinateSystem system,QPoint * offset,QGraphicsEffect::PixmapPadMode mode) const11323 QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
11324                                                  QGraphicsEffect::PixmapPadMode mode) const
11325 {
11326     const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
11327     if (!info && deviceCoordinates) {
11328         // Device coordinates without info not yet supported.
11329         qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
11330         return QPixmap();
11331     }
11332     if (!item->d_ptr->scene)
11333         return QPixmap();
11334     QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
11335 
11336     bool unpadded;
11337     const QRectF sourceRect = boundingRect(system);
11338     QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded);
11339 
11340     if (offset)
11341         *offset = effectRect.topLeft();
11342 
11343     bool untransformed = !deviceCoordinates
11344             || info->painter->worldTransform().type() <= QTransform::TxTranslate;
11345     if (untransformed && unpadded && isPixmap()) {
11346         if (offset)
11347             *offset = boundingRect(system).topLeft().toPoint();
11348         return static_cast<QGraphicsPixmapItem *>(item)->pixmap();
11349     }
11350 
11351     if (effectRect.isEmpty())
11352         return QPixmap();
11353 
11354     QPixmap pixmap(effectRect.size());
11355     pixmap.fill(Qt::transparent);
11356     QPainter pixmapPainter(&pixmap);
11357     pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);
11358 
11359     QTransform effectTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y());
11360     if (deviceCoordinates && info->effectTransform)
11361         effectTransform *= *info->effectTransform;
11362 
11363     if (!info) {
11364         // Logical coordinates without info.
11365         QTransform sceneTransform = item->sceneTransform();
11366         QTransform newEffectTransform = sceneTransform.inverted();
11367         newEffectTransform *= effectTransform;
11368         scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0),
11369                      &newEffectTransform, false, true);
11370     } else if (deviceCoordinates) {
11371         // Device coordinates with info.
11372         scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
11373                      info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
11374                      info->drawItem);
11375     } else {
11376         // Item coordinates with info.
11377         QTransform newEffectTransform = info->transformPtr->inverted();
11378         newEffectTransform *= effectTransform;
11379         scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
11380                      info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform,
11381                      info->drawItem);
11382     }
11383 
11384     pixmapPainter.end();
11385 
11386     return pixmap;
11387 }
11388 #endif //QT_NO_GRAPHICSEFFECT
11389 
11390 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug debug,QGraphicsItem * item)11391 QDebug operator<<(QDebug debug, QGraphicsItem *item)
11392 {
11393     if (!item) {
11394         debug << "QGraphicsItem(0)";
11395         return debug;
11396     }
11397 
11398     if (QGraphicsObject *o = item->toGraphicsObject())
11399         debug << o->metaObject()->className();
11400     else
11401         debug << "QGraphicsItem";
11402     debug << "(this =" << (void*)item
11403           << ", parent =" << (void*)item->parentItem()
11404           << ", pos =" << item->pos()
11405           << ", z =" << item->zValue() << ", flags = "
11406           << item->flags() << ")";
11407     return debug;
11408 }
11409 
operator <<(QDebug debug,QGraphicsObject * item)11410 QDebug operator<<(QDebug debug, QGraphicsObject *item)
11411 {
11412     if (!item) {
11413         debug << "QGraphicsObject(0)";
11414         return debug;
11415     }
11416 
11417     debug.nospace() << item->metaObject()->className() << '(' << (void*)item;
11418     if (!item->objectName().isEmpty())
11419         debug << ", name = " << item->objectName();
11420     debug.nospace() << ", parent = " << ((void*)item->parentItem())
11421           << ", pos = " << item->pos()
11422           << ", z = " << item->zValue() << ", flags = "
11423           << item->flags() << ')';
11424     return debug.space();
11425 }
11426 
operator <<(QDebug debug,QGraphicsItem::GraphicsItemChange change)11427 QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change)
11428 {
11429     const char *str = "UnknownChange";
11430     switch (change) {
11431     case QGraphicsItem::ItemChildAddedChange:
11432         str = "ItemChildAddedChange";
11433         break;
11434     case QGraphicsItem::ItemChildRemovedChange:
11435         str = "ItemChildRemovedChange";
11436         break;
11437     case QGraphicsItem::ItemCursorChange:
11438         str = "ItemCursorChange";
11439         break;
11440     case QGraphicsItem::ItemCursorHasChanged:
11441         str = "ItemCursorHasChanged";
11442         break;
11443     case QGraphicsItem::ItemEnabledChange:
11444         str = "ItemEnabledChange";
11445         break;
11446     case QGraphicsItem::ItemEnabledHasChanged:
11447         str = "ItemEnabledHasChanged";
11448         break;
11449     case QGraphicsItem::ItemFlagsChange:
11450         str = "ItemFlagsChange";
11451         break;
11452     case QGraphicsItem::ItemFlagsHaveChanged:
11453         str = "ItemFlagsHaveChanged";
11454         break;
11455     case QGraphicsItem::ItemMatrixChange:
11456         str = "ItemMatrixChange";
11457         break;
11458     case QGraphicsItem::ItemParentChange:
11459         str = "ItemParentChange";
11460         break;
11461     case QGraphicsItem::ItemParentHasChanged:
11462         str = "ItemParentHasChanged";
11463         break;
11464     case QGraphicsItem::ItemPositionChange:
11465         str = "ItemPositionChange";
11466         break;
11467     case QGraphicsItem::ItemPositionHasChanged:
11468         str = "ItemPositionHasChanged";
11469         break;
11470     case QGraphicsItem::ItemSceneChange:
11471         str = "ItemSceneChange";
11472         break;
11473     case QGraphicsItem::ItemSceneHasChanged:
11474         str = "ItemSceneHasChanged";
11475         break;
11476     case QGraphicsItem::ItemSelectedChange:
11477         str = "ItemSelectedChange";
11478         break;
11479     case QGraphicsItem::ItemSelectedHasChanged:
11480         str = "ItemSelectedHasChanged";
11481         break;
11482     case QGraphicsItem::ItemToolTipChange:
11483         str = "ItemToolTipChange";
11484         break;
11485     case QGraphicsItem::ItemToolTipHasChanged:
11486         str = "ItemToolTipHasChanged";
11487         break;
11488     case QGraphicsItem::ItemTransformChange:
11489         str = "ItemTransformChange";
11490         break;
11491     case QGraphicsItem::ItemTransformHasChanged:
11492         str = "ItemTransformHasChanged";
11493         break;
11494     case QGraphicsItem::ItemVisibleChange:
11495         str = "ItemVisibleChange";
11496         break;
11497     case QGraphicsItem::ItemVisibleHasChanged:
11498         str = "ItemVisibleHasChanged";
11499         break;
11500     case QGraphicsItem::ItemZValueChange:
11501         str = "ItemZValueChange";
11502         break;
11503     case QGraphicsItem::ItemZValueHasChanged:
11504         str = "ItemZValueHasChanged";
11505         break;
11506     case QGraphicsItem::ItemOpacityChange:
11507         str = "ItemOpacityChange";
11508         break;
11509     case QGraphicsItem::ItemOpacityHasChanged:
11510         str = "ItemOpacityHasChanged";
11511         break;
11512     case QGraphicsItem::ItemScenePositionHasChanged:
11513         str = "ItemScenePositionHasChanged";
11514         break;
11515     case QGraphicsItem::ItemRotationChange:
11516         str = "ItemRotationChange";
11517         break;
11518     case QGraphicsItem::ItemRotationHasChanged:
11519         str = "ItemRotationHasChanged";
11520         break;
11521     case QGraphicsItem::ItemScaleChange:
11522         str = "ItemScaleChange";
11523         break;
11524     case QGraphicsItem::ItemScaleHasChanged:
11525         str = "ItemScaleHasChanged";
11526         break;
11527     case QGraphicsItem::ItemTransformOriginPointChange:
11528         str = "ItemTransformOriginPointChange";
11529         break;
11530     case QGraphicsItem::ItemTransformOriginPointHasChanged:
11531         str = "ItemTransformOriginPointHasChanged";
11532         break;
11533     }
11534     debug << str;
11535     return debug;
11536 }
11537 
operator <<(QDebug debug,QGraphicsItem::GraphicsItemFlag flag)11538 QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
11539 {
11540     const char *str = "UnknownFlag";
11541     switch (flag) {
11542     case QGraphicsItem::ItemIsMovable:
11543         str = "ItemIsMovable";
11544         break;
11545     case QGraphicsItem::ItemIsSelectable:
11546         str = "ItemIsSelectable";
11547         break;
11548     case QGraphicsItem::ItemIsFocusable:
11549         str = "ItemIsFocusable";
11550         break;
11551     case QGraphicsItem::ItemClipsToShape:
11552         str = "ItemClipsToShape";
11553         break;
11554     case QGraphicsItem::ItemClipsChildrenToShape:
11555         str = "ItemClipsChildrenToShape";
11556         break;
11557     case QGraphicsItem::ItemIgnoresTransformations:
11558         str = "ItemIgnoresTransformations";
11559         break;
11560     case QGraphicsItem::ItemIgnoresParentOpacity:
11561         str = "ItemIgnoresParentOpacity";
11562         break;
11563     case QGraphicsItem::ItemDoesntPropagateOpacityToChildren:
11564         str = "ItemDoesntPropagateOpacityToChildren";
11565         break;
11566     case QGraphicsItem::ItemStacksBehindParent:
11567         str = "ItemStacksBehindParent";
11568         break;
11569     case QGraphicsItem::ItemUsesExtendedStyleOption:
11570         str = "ItemUsesExtendedStyleOption";
11571         break;
11572     case QGraphicsItem::ItemHasNoContents:
11573         str = "ItemHasNoContents";
11574         break;
11575     case QGraphicsItem::ItemSendsGeometryChanges:
11576         str = "ItemSendsGeometryChanges";
11577         break;
11578     case QGraphicsItem::ItemAcceptsInputMethod:
11579         str = "ItemAcceptsInputMethod";
11580         break;
11581     case QGraphicsItem::ItemNegativeZStacksBehindParent:
11582         str = "ItemNegativeZStacksBehindParent";
11583         break;
11584     case QGraphicsItem::ItemIsPanel:
11585         str = "ItemIsPanel";
11586         break;
11587     case QGraphicsItem::ItemIsFocusScope:
11588         str = "ItemIsFocusScope";
11589         break;
11590     case QGraphicsItem::ItemSendsScenePositionChanges:
11591         str = "ItemSendsScenePositionChanges";
11592         break;
11593     case QGraphicsItem::ItemStopsClickFocusPropagation:
11594         str = "ItemStopsClickFocusPropagation";
11595         break;
11596     case QGraphicsItem::ItemStopsFocusHandling:
11597         str = "ItemStopsFocusHandling";
11598         break;
11599     }
11600     debug << str;
11601     return debug;
11602 }
11603 
operator <<(QDebug debug,QGraphicsItem::GraphicsItemFlags flags)11604 QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags)
11605 {
11606     debug << '(';
11607     bool f = false;
11608     for (int i = 0; i < 17; ++i) {
11609         if (flags & (1 << i)) {
11610             if (f)
11611                 debug << '|';
11612             f = true;
11613             debug << QGraphicsItem::GraphicsItemFlag(int(flags & (1 << i)));
11614         }
11615     }
11616     debug << ')';
11617     return debug;
11618 }
11619 
11620 #endif
11621 
11622 QT_END_NAMESPACE
11623 
11624 #include "moc_qgraphicsitem.cpp"
11625 
11626 #endif // QT_NO_GRAPHICSVIEW
11627