1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets 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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40/*!
41 \class QGraphicsItem
42 \brief The QGraphicsItem class is the base class for all graphical
43 items in a QGraphicsScene.
44 \since 4.2
45
46 \ingroup graphicsview-api
47 \inmodule QtWidgets
48
49 It provides a light-weight foundation for writing your own custom items.
50 This includes defining the item's geometry, collision detection, its
51 painting implementation and item interaction through its event handlers.
52 QGraphicsItem is part of the \l{Graphics View Framework}
53
54 \image graphicsview-items.png
55
56 For convenience, Qt provides a set of standard graphics items for the most
57 common shapes. These are:
58
59 \list
60 \li QGraphicsEllipseItem provides an ellipse item
61 \li QGraphicsLineItem provides a line item
62 \li QGraphicsPathItem provides an arbitrary path item
63 \li QGraphicsPixmapItem provides a pixmap item
64 \li QGraphicsPolygonItem provides a polygon item
65 \li QGraphicsRectItem provides a rectangular item
66 \li QGraphicsSimpleTextItem provides a simple text label item
67 \li QGraphicsTextItem provides an advanced text browser item
68 \endlist
69
70 All of an item's geometric information is based on its local coordinate
71 system. The item's position, pos(), is the only function that does not
72 operate in local coordinates, as it returns a position in parent
73 coordinates. \l {The Graphics View Coordinate System} describes the coordinate
74 system in detail.
75
76 You can set whether an item should be visible (i.e., drawn, and accepting
77 events), by calling setVisible(). Hiding an item will also hide its
78 children. Similarly, you can enable or disable an item by calling
79 setEnabled(). If you disable an item, all its children will also be
80 disabled. By default, items are both visible and enabled. To toggle
81 whether an item is selected or not, first enable selection by setting
82 the ItemIsSelectable flag, and then call setSelected(). Normally,
83 selection is toggled by the scene, as a result of user interaction.
84
85 To write your own graphics item, you first create a subclass of
86 QGraphicsItem, and then start by implementing its two pure virtual public
87 functions: boundingRect(), which returns an estimate of the area painted
88 by the item, and paint(), which implements the actual painting. For
89 example:
90
91 \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 0
92
93 The boundingRect() function has many different purposes.
94 QGraphicsScene bases its item index on boundingRect(), and
95 QGraphicsView uses it both for culling invisible items, and for
96 determining the area that needs to be recomposed when drawing
97 overlapping items. In addition, QGraphicsItem's collision
98 detection mechanisms use boundingRect() to provide an efficient
99 cut-off. The fine grained collision algorithm in
100 collidesWithItem() is based on calling shape(), which returns an
101 accurate outline of the item's shape as a QPainterPath.
102
103 QGraphicsScene expects all items boundingRect() and shape() to
104 remain unchanged unless it is notified. If you want to change an
105 item's geometry in any way, you must first call
106 prepareGeometryChange() to allow QGraphicsScene to update its
107 bookkeeping.
108
109 Collision detection can be done in two ways:
110
111 \list 1
112
113 \li Reimplement shape() to return an accurate shape for your item,
114 and rely on the default implementation of collidesWithItem() to do
115 shape-shape intersection. This can be rather expensive if the
116 shapes are complex.
117
118 \li Reimplement collidesWithItem() to provide your own custom item
119 and shape collision algorithm.
120
121 \endlist
122
123 The contains() function can be called to determine whether the item \e
124 contains a point or not. This function can also be reimplemented by the
125 item. The default behavior of contains() is based on calling shape().
126
127 Items can contain other items, and also be contained by other items. All
128 items can have a parent item and a list of children. Unless the item has
129 no parent, its position is in \e parent coordinates (i.e., the parent's
130 local coordinates). Parent items propagate both their position and their
131 transformation to all children.
132
133 \image graphicsview-parentchild.png
134
135 \target Transformations
136 \section1 Transformations
137
138 QGraphicsItem supports projective transformations in addition to its base
139 position, pos(). There are several ways to change an item's transformation.
140 For simple transformations, you can call either of the convenience
141 functions setRotation() or setScale(), or you can pass any transformation
142 matrix to setTransform(). For advanced transformation control you also have
143 the option of setting several combined transformations by calling
144 setTransformations().
145
146 Item transformations accumulate from parent to child, so if both a parent
147 and child item are rotated 90 degrees, the child's total transformation
148 will be 180 degrees. Similarly, if the item's parent is scaled to 2x its
149 original size, its children will also be twice as large. An item's
150 transformation does not affect its own local geometry; all geometry
151 functions (e.g., contains(), update(), and all the mapping functions) still
152 operate in local coordinates. For convenience, QGraphicsItem provides the
153 functions sceneTransform(), which returns the item's total transformation
154 matrix (including its position and all parents' positions and
155 transformations), and scenePos(), which returns its position in scene
156 coordinates. To reset an item's matrix, call resetTransform().
157
158 Certain transformation operations produce a different outcome depending on
159 the order in which they are applied. For example, if you scale an
160 transform, and then rotate it, you may get a different result than if the
161 transform was rotated first. However, the order you set the transformation
162 properties on QGraphicsItem does not affect the resulting transformation;
163 QGraphicsItem always applies the properties in a fixed, defined order:
164
165 \list
166 \li The item's base transform is applied (transform())
167 \li The item's transformations list is applied in order (transformations())
168 \li The item is rotated relative to its transform origin point (rotation(), transformOriginPoint())
169 \li The item is scaled relative to its transform origin point (scale(), transformOriginPoint())
170 \endlist
171
172 \section1 Painting
173
174 The paint() function is called by QGraphicsView to paint the item's
175 contents. The item has no background or default fill of its own; whatever
176 is behind the item will shine through all areas that are not explicitly
177 painted in this function. You can call update() to schedule a repaint,
178 optionally passing the rectangle that needs a repaint. Depending on
179 whether or not the item is visible in a view, the item may or may not be
180 repainted; there is no equivalent to QWidget::repaint() in QGraphicsItem.
181
182 Items are painted by the view, starting with the parent items and then
183 drawing children, in ascending stacking order. You can set an item's
184 stacking order by calling setZValue(), and test it by calling
185 zValue(), where items with low z-values are painted before items with
186 high z-values. Stacking order applies to sibling items; parents are always
187 drawn before their children.
188
189 \section1 Sorting
190
191 All items are drawn in a defined, stable order, and this same order decides
192 which items will receive mouse input first when you click on the scene.
193 Normally you don't have to worry about sorting, as the items follow a
194 "natural order", following the logical structure of the scene.
195
196 An item's children are stacked on top of the parent, and sibling items are
197 stacked by insertion order (i.e., in the same order that they were either
198 added to the scene, or added to the same parent). If you add item A, and
199 then B, then B will be on top of A. If you then add C, the items' stacking
200 order will be A, then B, then C.
201
202 \image graphicsview-zorder.png
203
204 This example shows the stacking order of all limbs of the robot from the
205 \l{graphicsview/dragdroprobot}{Drag and Drop Robot} example. The torso is
206 the root item (all other items are children or descendants of the torso),
207 so it is drawn first. Next, the head is drawn, as it is the first item in
208 the torso's list of children. Then the upper left arm is drawn. As the
209 lower arm is a child of the upper arm, the lower arm is then drawn,
210 followed by the upper arm's next sibling, which is the upper right arm, and
211 so on.
212
213 For advanced users, there are ways to alter how your items are sorted:
214
215 \list
216 \li You can call setZValue() on an item to explicitly stack it on top of, or
217 under, other sibling items. The default Z value for an item is 0. Items
218 with the same Z value are stacked by insertion order.
219
220 \li You can call stackBefore() to reorder the list of children. This will
221 directly modify the insertion order.
222
223 \li You can set the ItemStacksBehindParent flag to stack a child item behind
224 its parent.
225 \endlist
226
227 The stacking order of two sibling items also counts for each item's
228 children and descendant items. So if one item is on top of another, then
229 all its children will also be on top of all the other item's children as
230 well.
231
232 \section1 Events
233
234 QGraphicsItem receives events from QGraphicsScene through the virtual
235 function sceneEvent(). This function distributes the most common events
236 to a set of convenience event handlers:
237
238 \list
239 \li contextMenuEvent() handles context menu events
240 \li focusInEvent() and focusOutEvent() handle focus in and out events
241 \li hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() handles
242 hover enter, move and leave events
243 \li inputMethodEvent() handles input events, for accessibility support
244 \li keyPressEvent() and keyReleaseEvent() handle key press and release events
245 \li mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and
246 mouseDoubleClickEvent() handles mouse press, move, release, click and
247 doubleclick events
248 \endlist
249
250 You can filter events for any other item by installing event filters. This
251 functionality is separate from Qt's regular event filters (see
252 QObject::installEventFilter()), which only work on subclasses of QObject. After
253 installing your item as an event filter for another item by calling
254 installSceneEventFilter(), the filtered events will be received by the virtual
255 function sceneEventFilter(). You can remove item event filters by calling
256 removeSceneEventFilter().
257
258 \section1 Custom Data
259
260 Sometimes it's useful to register custom data with an item, be it a custom
261 item, or a standard item. You can call setData() on any item to store data
262 in it using a key-value pair (the key being an integer, and the value is a
263 QVariant). To get custom data from an item, call data(). This
264 functionality is completely untouched by Qt itself; it is provided for the
265 user's convenience.
266
267 \sa QGraphicsScene, QGraphicsView, {Graphics View Framework}
268*/
269
270/*!
271 \enum QGraphicsItem::anonymous
272
273 The value returned by the virtual type() function in standard
274 graphics item classes in Qt. All such standard graphics item classes
275 in Qt are associated with a unique value for Type, e.g. the value
276 returned by QGraphicsPathItem::type() is 2.
277
278 \value Type
279
280 \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 18
281
282 \value UserType The lowest value returned by the virtual type()
283 function for custom subclasses of QGraphicsItem.
284
285 \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 1
286*/
287
288/*!
289 \enum QGraphicsPathItem::anonymous
290
291 The value returned by the virtual type() function.
292
293 \value Type A graphics path item
294*/
295
296/*!
297 \enum QGraphicsRectItem::anonymous
298
299 The value returned by the virtual type() function.
300
301 \value Type A graphics rect item
302*/
303
304/*!
305 \enum QGraphicsEllipseItem::anonymous
306
307 The value returned by the virtual type() function.
308
309 \value Type A graphics ellipse item
310*/
311
312/*!
313 \enum QGraphicsPolygonItem::anonymous
314
315 The value returned by the virtual type() function.
316
317 \value Type A graphics polygon item
318*/
319
320/*!
321 \enum QGraphicsPixmapItem::anonymous
322
323 The value returned by the virtual type() function.
324
325 \value Type A graphics pixmap item
326*/
327
328/*!
329 \enum QGraphicsTextItem::anonymous
330
331 The value returned by the virtual type() function.
332
333 \value Type A graphics text item
334*/
335
336/*!
337 \enum QGraphicsSimpleTextItem::anonymous
338
339 The value returned by the virtual type() function.
340
341 \value Type A graphics simple text item
342*/
343
344/*!
345 \enum QGraphicsItemGroup::anonymous
346
347 The value returned by the virtual type() function.
348
349 \value Type A graphics item group
350*/
351
352/*!
353 \enum QGraphicsLineItem::anonymous
354
355 The value returned by the virtual type() function.
356
357 \value Type A graphics line item
358*/
359
360/*!
361 \enum QGraphicsItem::GraphicsItemFlag
362
363 This enum describes different flags that you can set on an item to
364 toggle different features in the item's behavior.
365
366 All flags are disabled by default.
367
368 \value ItemIsMovable The item supports interactive movement using
369 the mouse. By clicking on the item and then dragging, the item
370 will move together with the mouse cursor. If the item has
371 children, all children are also moved. If the item is part of a
372 selection, all selected items are also moved. This feature is
373 provided as a convenience through the base implementation of
374 QGraphicsItem's mouse event handlers.
375
376 \value ItemIsSelectable The item supports selection. Enabling this
377 feature will enable setSelected() to toggle selection for the
378 item. It will also let the item be selected automatically as a
379 result of calling QGraphicsScene::setSelectionArea(), by clicking
380 on an item, or by using rubber band selection in QGraphicsView.
381
382 \value ItemIsFocusable The item supports keyboard input focus (i.e., it is
383 an input item). Enabling this flag will allow the item to accept focus,
384 which again allows the delivery of key events to
385 QGraphicsItem::keyPressEvent() and QGraphicsItem::keyReleaseEvent().
386
387 \value ItemClipsToShape The item clips to its own shape. The item cannot
388 draw or receive mouse, tablet, drag and drop or hover events outside its
389 shape. It is disabled by default. This behavior is enforced by
390 QGraphicsView::drawItems() or QGraphicsScene::drawItems(). This flag was
391 introduced in Qt 4.3.
392
393 \value ItemClipsChildrenToShape The item clips the painting of all its
394 descendants to its own shape. Items that are either direct or indirect
395 children of this item cannot draw outside this item's shape. By default,
396 this flag is disabled; children can draw anywhere. This behavior is
397 enforced by QGraphicsView::drawItems() or
398 QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3.
399 \note This flag is similar to ItemContainsChildrenInShape but in addition
400 enforces the containment by clipping the children.
401
402 \value ItemIgnoresTransformations The item ignores inherited
403 transformations (i.e., its position is still anchored to its parent, but
404 the parent or view rotation, zoom or shear transformations are ignored).
405 This flag is useful for keeping text label items horizontal and unscaled,
406 so they will still be readable if the view is transformed. When set, the
407 item's view geometry and scene geometry will be maintained separately. You
408 must call deviceTransform() to map coordinates and detect collisions in
409 the view. By default, this flag is disabled. This flag was introduced in
410 Qt 4.3. \note With this flag set you can still scale the item itself, and
411 that scale transformation will influence the item's children.
412
413 \value ItemIgnoresParentOpacity The item ignores its parent's opacity. The
414 item's effective opacity is the same as its own; it does not combine with
415 the parent's opacity. This flags allows your item to keep its absolute
416 opacity even if the parent is semitransparent. This flag was introduced in
417 Qt 4.5.
418
419 \value ItemDoesntPropagateOpacityToChildren The item doesn't propagate its
420 opacity to its children. This flag allows you to create a semitransparent
421 item that does not affect the opacity of its children. This flag was
422 introduced in Qt 4.5.
423
424 \value ItemStacksBehindParent The item is stacked behind its parent. By
425 default, child items are stacked on top of the parent item. But setting
426 this flag, the child will be stacked behind it. This flag is useful for
427 drop shadow effects and for decoration objects that follow the parent
428 item's geometry without drawing on top of it. This flag was introduced
429 in Qt 4.5.
430
431 \value ItemUsesExtendedStyleOption The item makes use of either
432 \l{QStyleOptionGraphicsItem::} {exposedRect} or
433 \l{QStyleOptionGraphicsItem::} {matrix} in
434 QStyleOptionGraphicsItem. By default, the
435 \l{QStyleOptionGraphicsItem::} {exposedRect} is initialized to the
436 item's boundingRect() and the
437 \l{QStyleOptionGraphicsItem::}{matrix} is untransformed. You can
438 enable this flag for the style options to be set up with more
439 fine-grained values. Note that
440 QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag
441 and always initialized to 1. Use
442 QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need
443 a higher value. This flag was introduced in Qt 4.6.
444
445 \value ItemHasNoContents The item does not paint anything (i.e., calling
446 paint() on the item has no effect). You should set this flag on items that
447 do not need to be painted to ensure that Graphics View avoids unnecessary
448 painting preparations. This flag was introduced in Qt 4.6.
449
450 \value ItemSendsGeometryChanges The item enables itemChange()
451 notifications for ItemPositionChange, ItemPositionHasChanged,
452 ItemMatrixChange, ItemTransformChange, ItemTransformHasChanged,
453 ItemRotationChange, ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged,
454 ItemTransformOriginPointChange, and ItemTransformOriginPointHasChanged. For
455 performance reasons, these notifications are disabled by default. You must
456 enable this flag to receive notifications for position and transform
457 changes. This flag was introduced in Qt 4.6.
458
459 \value ItemAcceptsInputMethod The item supports input methods typically
460 used for Asian languages.
461 This flag was introduced in Qt 4.6.
462
463 \value ItemNegativeZStacksBehindParent The item automatically
464 stacks behind it's parent if it's z-value is negative. This flag
465 enables setZValue() to toggle ItemStacksBehindParent. This flag
466 was introduced in Qt 4.6.
467
468 \value ItemIsPanel The item is a panel. A panel provides activation and
469 contained focus handling. Only one panel can be active at a time (see
470 QGraphicsItem::isActive()). When no panel is active, QGraphicsScene
471 activates all non-panel items. Window items (i.e.,
472 QGraphicsItem::isWindow() returns \c true) are panels. This flag was
473 introduced in Qt 4.6.
474
475 \omitvalue ItemIsFocusScope \omit Internal only (for now). \endomit
476
477 \value ItemSendsScenePositionChanges The item enables itemChange()
478 notifications for ItemScenePositionHasChanged. For performance reasons,
479 these notifications are disabled by default. You must enable this flag
480 to receive notifications for scene position changes. This flag was
481 introduced in Qt 4.6.
482
483 \omitvalue ItemStopsClickFocusPropagation \omit The item stops propagating
484 click focus to items underneath when being clicked on. This flag
485 allows you create a non-focusable item that can be clicked on without
486 changing the focus. \endomit
487
488 \omitvalue ItemStopsFocusHandling \omit Same as
489 ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag
490 allows you to completely take over focus handling.
491 This flag was introduced in Qt 4.7. \endomit
492
493 \value ItemContainsChildrenInShape This flag indicates that all of the
494 item's direct or indirect children only draw within the item's shape.
495 Unlike ItemClipsChildrenToShape, this restriction is not enforced. Set
496 ItemContainsChildrenInShape when you manually assure that drawing
497 is bound to the item's shape and want to avoid the cost associated with
498 enforcing the clip. Setting this flag enables more efficient drawing and
499 collision detection. The flag is disabled by default.
500 \note If both this flag and ItemClipsChildrenToShape are set, the clip
501 will be enforced. This is equivalent to just setting
502 ItemClipsChildrenToShape.
503
504 This flag was introduced in Qt 5.4.
505*/
506
507/*!
508 \enum QGraphicsItem::GraphicsItemChange
509
510 This enum describes the state changes that are notified by
511 QGraphicsItem::itemChange(). The notifications are sent as the state
512 changes, and in some cases, adjustments can be made (see the documentation
513 for each change for details).
514
515 Note: Be careful with calling functions on the QGraphicsItem itself inside
516 itemChange(), as certain function calls can lead to unwanted
517 recursion. For example, you cannot call setPos() in itemChange() on an
518 ItemPositionChange notification, as the setPos() function will again call
519 itemChange(ItemPositionChange). Instead, you can return the new, adjusted
520 position from itemChange().
521
522 \value ItemEnabledChange The item's enabled state changes. If the item is
523 presently enabled, it will become disabled, and vice verca. The value
524 argument is the new enabled state (i.e., true or false). Do not call
525 setEnabled() in itemChange() as this notification is delivered. Instead,
526 you can return the new state from itemChange().
527
528 \value ItemEnabledHasChanged The item's enabled state has changed. The
529 value argument is the new enabled state (i.e., true or false). Do not call
530 setEnabled() in itemChange() as this notification is delivered. The return
531 value is ignored.
532
533 \value ItemMatrixChange The item's affine transformation matrix is
534 changing. This value is obsolete; you can use ItemTransformChange instead.
535
536 \value ItemPositionChange The item's position changes. This notification
537 is sent if the ItemSendsGeometryChanges flag is enabled, and when the
538 item's local position changes, relative to its parent (i.e., as a result
539 of calling setPos() or moveBy()). The value argument is the new position
540 (i.e., a QPointF). You can call pos() to get the original position. Do
541 not call setPos() or moveBy() in itemChange() as this notification is
542 delivered; instead, you can return the new, adjusted position from
543 itemChange(). After this notification, QGraphicsItem immediately sends the
544 ItemPositionHasChanged notification if the position changed.
545
546 \value ItemPositionHasChanged The item's position has changed. This
547 notification is sent if the ItemSendsGeometryChanges flag is enabled, and
548 after the item's local position, relative to its parent, has changed. The
549 value argument is the new position (the same as pos()), and QGraphicsItem
550 ignores the return value for this notification (i.e., a read-only
551 notification).
552
553 \value ItemTransformChange The item's transformation matrix changes. This
554 notification is sent if the ItemSendsGeometryChanges flag is enabled, and
555 when the item's local transformation matrix changes (i.e., as a result of
556 calling setTransform(). The value argument is the new matrix (i.e., a
557 QTransform); to get the old matrix, call transform(). Do not call
558 setTransform() or set any of the transformation properties in itemChange()
559 as this notification is delivered; instead, you can return the new matrix
560 from itemChange(). This notification is not sent if you change the
561 transformation properties.
562
563 \value ItemTransformHasChanged The item's transformation matrix has
564 changed either because setTransform is called, or one of the
565 transformation properties is changed. This notification is sent if the
566 ItemSendsGeometryChanges flag is enabled, and after the item's local
567 transformation matrix has changed. The value argument is the new matrix
568 (same as transform()), and QGraphicsItem ignores the return value for this
569 notification (i.e., a read-only notification).
570
571 \value ItemRotationChange The item's rotation property changes. This
572 notification is sent if the ItemSendsGeometryChanges flag is enabled, and
573 when the item's rotation property changes (i.e., as a result of calling
574 setRotation()). The value argument is the new rotation (i.e., a double);
575 to get the old rotation, call rotation(). Do not call setRotation() in
576 itemChange() as this notification is delivered; instead, you can return
577 the new rotation from itemChange().
578
579 \value ItemRotationHasChanged The item's rotation property has changed.
580 This notification is sent if the ItemSendsGeometryChanges flag is enabled,
581 and after the item's rotation property has changed. The value argument is
582 the new rotation (i.e., a double), and QGraphicsItem ignores the return
583 value for this notification (i.e., a read-only notification). Do not call
584 setRotation() in itemChange() as this notification is delivered.
585
586 \value ItemScaleChange The item's scale property changes. This notification
587 is sent if the ItemSendsGeometryChanges flag is enabled, and when the item's
588 scale property changes (i.e., as a result of calling setScale()). The value
589 argument is the new scale (i.e., a double); to get the old scale, call
590 scale(). Do not call setScale() in itemChange() as this notification is
591 delivered; instead, you can return the new scale from itemChange().
592
593 \value ItemScaleHasChanged The item's scale property has changed. This
594 notification is sent if the ItemSendsGeometryChanges flag is enabled, and
595 after the item's scale property has changed. The value argument is the new
596 scale (i.e., a double), and QGraphicsItem ignores the return value for this
597 notification (i.e., a read-only notification). Do not call setScale() in
598 itemChange() as this notification is delivered.
599
600 \value ItemTransformOriginPointChange The item's transform origin point
601 property changes. This notification is sent if the ItemSendsGeometryChanges
602 flag is enabled, and when the item's transform origin point property changes
603 (i.e., as a result of calling setTransformOriginPoint()). The value argument
604 is the new origin point (i.e., a QPointF); to get the old origin point, call
605 transformOriginPoint(). Do not call setTransformOriginPoint() in itemChange()
606 as this notification is delivered; instead, you can return the new transform
607 origin point from itemChange().
608
609 \value ItemTransformOriginPointHasChanged The item's transform origin point
610 property has changed. This notification is sent if the ItemSendsGeometryChanges
611 flag is enabled, and after the item's transform origin point property has
612 changed. The value argument is the new origin point (i.e., a QPointF), and
613 QGraphicsItem ignores the return value for this notification (i.e., a read-only
614 notification). Do not call setTransformOriginPoint() in itemChange() as this
615 notification is delivered.
616
617 \value ItemSelectedChange The item's selected state changes. If the item is
618 presently selected, it will become unselected, and vice verca. The value
619 argument is the new selected state (i.e., true or false). Do not call
620 setSelected() in itemChange() as this notification is delivered; instead, you
621 can return the new selected state from itemChange().
622
623 \value ItemSelectedHasChanged The item's selected state has changed. The
624 value argument is the new selected state (i.e., true or false). Do not
625 call setSelected() in itemChange() as this notification is delivered. The
626 return value is ignored.
627
628 \value ItemVisibleChange The item's visible state changes. If the item is
629 presently visible, it will become invisible, and vice verca. The value
630 argument is the new visible state (i.e., true or false). Do not call
631 setVisible() in itemChange() as this notification is delivered; instead,
632 you can return the new visible state from itemChange().
633
634 \value ItemVisibleHasChanged The item's visible state has changed. The
635 value argument is the new visible state (i.e., true or false). Do not call
636 setVisible() in itemChange() as this notification is delivered. The return
637 value is ignored.
638
639 \value ItemParentChange The item's parent changes. The value argument is
640 the new parent item (i.e., a QGraphicsItem pointer). Do not call
641 setParentItem() in itemChange() as this notification is delivered;
642 instead, you can return the new parent from itemChange().
643
644 \value ItemParentHasChanged The item's parent has changed. The value
645 argument is the new parent (i.e., a pointer to a QGraphicsItem). Do not
646 call setParentItem() in itemChange() as this notification is
647 delivered. The return value is ignored.
648
649 \value ItemChildAddedChange A child is added to this item. The value
650 argument is the new child item (i.e., a QGraphicsItem pointer). Do not
651 pass this item to any item's setParentItem() function as this notification
652 is delivered. The return value is unused; you cannot adjust anything in
653 this notification. Note that the new child might not be fully constructed
654 when this notification is sent; calling pure virtual functions on
655 the child can lead to a crash.
656
657 \value ItemChildRemovedChange A child is removed from this item. The value
658 argument is the child item that is about to be removed (i.e., a
659 QGraphicsItem pointer). The return value is unused; you cannot adjust
660 anything in this notification.
661
662 \value ItemSceneChange The item is moved to a new scene. This notification is
663 also sent when the item is added to its initial scene, and when it is removed.
664 The item's scene() is the old scene, or \nullptr if the item has not been added
665 to a scene yet. The value argument is the new scene (i.e., a QGraphicsScene
666 pointer), or \nullptr if the item is removed from a scene. Do not
667 override this change by passing this item to QGraphicsScene::addItem() as this
668 notification is delivered; instead, you can return the new scene from
669 itemChange(). Use this feature with caution; objecting to a scene change can
670 quickly lead to unwanted recursion.
671
672 \value ItemSceneHasChanged The item's scene has changed. The item's scene() is
673 the new scene. This notification is also sent when the item is added to its
674 initial scene, and when it is removed.The value argument is the new scene
675 (i.e., a pointer to a QGraphicsScene). Do not call setScene() in itemChange()
676 as this notification is delivered. The return value is ignored.
677
678 \value ItemCursorChange The item's cursor changes. The value argument is
679 the new cursor (i.e., a QCursor). Do not call setCursor() in itemChange()
680 as this notification is delivered. Instead, you can return a new cursor
681 from itemChange().
682
683 \value ItemCursorHasChanged The item's cursor has changed. The value
684 argument is the new cursor (i.e., a QCursor). Do not call setCursor() as
685 this notification is delivered. The return value is ignored.
686
687 \value ItemToolTipChange The item's tooltip changes. The value argument is
688 the new tooltip (i.e., a QToolTip). Do not call setToolTip() in
689 itemChange() as this notification is delivered. Instead, you can return a
690 new tooltip from itemChange().
691
692 \value ItemToolTipHasChanged The item's tooltip has changed. The value
693 argument is the new tooltip (i.e., a QToolTip). Do not call setToolTip()
694 as this notification is delivered. The return value is ignored.
695
696 \value ItemFlagsChange The item's flags change. The value argument is the
697 new flags (i.e., a quint32). Do not call setFlags() in itemChange() as
698 this notification is delivered. Instead, you can return the new flags from
699 itemChange().
700
701 \value ItemFlagsHaveChanged The item's flags have changed. The value
702 argument is the new flags (i.e., a quint32). Do not call setFlags() in
703 itemChange() as this notification is delivered. The return value is
704 ignored.
705
706 \value ItemZValueChange The item's Z-value changes. The value argument is
707 the new Z-value (i.e., a double). Do not call setZValue() in itemChange()
708 as this notification is delivered. Instead, you can return a new Z-value
709 from itemChange().
710
711 \value ItemZValueHasChanged The item's Z-value has changed. The value
712 argument is the new Z-value (i.e., a double). Do not call setZValue() as
713 this notification is delivered. The return value is ignored.
714
715 \value ItemOpacityChange The item's opacity changes. The value argument is
716 the new opacity (i.e., a double). Do not call setOpacity() in itemChange()
717 as this notification is delivered. Instead, you can return a new opacity
718 from itemChange().
719
720 \value ItemOpacityHasChanged The item's opacity has changed. The value
721 argument is the new opacity (i.e., a double). Do not call setOpacity() as
722 this notification is delivered. The return value is ignored.
723
724 \value ItemScenePositionHasChanged The item's scene position has changed.
725 This notification is sent if the ItemSendsScenePositionChanges flag is
726 enabled, and after the item's scene position has changed (i.e., the
727 position or transformation of the item itself or the position or
728 transformation of any ancestor has changed). The value argument is the
729 new scene position (the same as scenePos()), and QGraphicsItem ignores
730 the return value for this notification (i.e., a read-only notification).
731*/
732
733/*!
734 \enum QGraphicsItem::CacheMode
735 \since 4.4
736
737 This enum describes QGraphicsItem's cache modes. Caching is used to speed
738 up rendering by allocating and rendering to an off-screen pixel buffer,
739 which can be reused when the item requires redrawing. For some paint
740 devices, the cache is stored directly in graphics memory, which makes
741 rendering very quick.
742
743 \value NoCache The default; all item caching is
744 disabled. QGraphicsItem::paint() is called every time the item needs
745 redrawing.
746
747 \value ItemCoordinateCache Caching is enabled for the item's logical
748 (local) coordinate system. QGraphicsItem creates an off-screen pixel
749 buffer with a configurable size / resolution that you can pass to
750 QGraphicsItem::setCacheMode(). Rendering quality will typically degrade,
751 depending on the resolution of the cache and the item transformation. The
752 first time the item is redrawn, it will render itself into the cache, and
753 the cache is then reused for every subsequent expose. The cache is also
754 reused as the item is transformed. To adjust the resolution of the cache,
755 you can call setCacheMode() again.
756
757 \value DeviceCoordinateCache Caching is enabled at the paint device level,
758 in device coordinates. This mode is for items that can move, but are not
759 rotated, scaled or sheared. If the item is transformed directly or
760 indirectly, the cache will be regenerated automatically. Unlike
761 ItemCoordinateCacheMode, DeviceCoordinateCache always renders at maximum
762 quality.
763
764 \sa QGraphicsItem::setCacheMode()
765*/
766
767/*!
768 \enum QGraphicsItem::Extension
769 \internal
770
771 Note: This is provided as a hook to avoid future problems related
772 to adding virtual functions. See also extension(),
773 supportsExtension() and setExtension().
774*/
775
776/*!
777 \enum QGraphicsItem::PanelModality
778 \since 4.6
779
780 This enum specifies the behavior of a modal panel. A modal panel
781 is one that blocks input to other panels. Note that items that
782 are children of a modal panel are not blocked.
783
784 The values are:
785
786 \value NonModal The panel is not modal and does not block input to
787 other panels. This is the default value for panels.
788
789 \value PanelModal The panel is modal to a single item hierarchy
790 and blocks input to its parent pane, all grandparent panels, and
791 all siblings of its parent and grandparent panels.
792
793 \value SceneModal The window is modal to the entire scene and
794 blocks input to all panels.
795
796 \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel
797*/
798
799#include "qgraphicsitem.h"
800
801#include "qgraphicsscene.h"
802#include "qgraphicsscene_p.h"
803#include "qgraphicssceneevent.h"
804#include "qgraphicsview.h"
805#include "qgraphicswidget.h"
806#include "qgraphicsproxywidget.h"
807#include "qgraphicsscenebsptreeindex_p.h"
808#include <QtCore/qbitarray.h>
809#include <QtCore/qpoint.h>
810#include <QtCore/qstack.h>
811#include <QtCore/qtimer.h>
812#include <QtCore/qvariant.h>
813#include <QtCore/qvarlengtharray.h>
814#include <QtCore/qnumeric.h>
815#include <QtWidgets/qapplication.h>
816#include <QtGui/qbitmap.h>
817#include <QtGui/qpainter.h>
818#include <QtGui/qpainterpath.h>
819#include <QtGui/qpixmapcache.h>
820#include <QtWidgets/qstyleoption.h>
821#include <QtGui/qevent.h>
822#include <QtGui/qinputmethod.h>
823#if QT_CONFIG(graphicseffect)
824#include <QtWidgets/qgraphicseffect.h>
825#endif
826
827#include <private/qgraphicsitem_p.h>
828#include <private/qgraphicswidget_p.h>
829#include <private/qwidgettextcontrol_p.h>
830#include <private/qtextdocumentlayout_p.h>
831#include <private/qtextengine_p.h>
832#include <private/qwidget_p.h>
833#include <private/qapplication_p.h>
834#include <private/qgesturemanager_p.h>
835#include <private/qdebug_p.h>
836
837QT_BEGIN_NAMESPACE
838
839static inline void _q_adjustRect(QRect *rect)
840{
841 Q_ASSERT(rect);
842 if (!rect->width())
843 rect->adjust(0, 0, 1, 0);
844 if (!rect->height())
845 rect->adjust(0, 0, 0, 1);
846}
847
848/*
849 ### Move this into QGraphicsItemPrivate
850 */
851class QGraphicsItemCustomDataStore
852{
853public:
854 QHash<const QGraphicsItem *, QMap<int, QVariant> > data;
855};
856Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)
857
858/*!
859 \internal
860
861 Returns a QPainterPath of \a path when stroked with the \a pen.
862 Ignoring dash pattern.
863*/
864static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen)
865{
866 // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
867 // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
868 const qreal penWidthZero = qreal(0.00000001);
869
870 if (path == QPainterPath() || pen == Qt::NoPen)
871 return path;
872 QPainterPathStroker ps;
873 ps.setCapStyle(pen.capStyle());
874 if (pen.widthF() <= 0.0)
875 ps.setWidth(penWidthZero);
876 else
877 ps.setWidth(pen.widthF());
878 ps.setJoinStyle(pen.joinStyle());
879 ps.setMiterLimit(pen.miterLimit());
880 QPainterPath p = ps.createStroke(path);
881 p.addPath(path);
882 return p;
883}
884
885/*!
886 \internal
887*/
888QGraphicsItemPrivate::QGraphicsItemPrivate()
889 : z(0),
890 opacity(1.),
891 scene(nullptr),
892 parent(nullptr),
893 transformData(nullptr),
894 graphicsEffect(nullptr),
895 index(-1),
896 siblingIndex(-1),
897 itemDepth(-1),
898 focusProxy(nullptr),
899 subFocusItem(nullptr),
900 focusScopeItem(nullptr),
901 imHints(Qt::ImhNone),
902 panelModality(QGraphicsItem::NonModal),
903 acceptedMouseButtons(0x1f),
904 visible(true),
905 explicitlyHidden(false),
906 enabled(true),
907 explicitlyDisabled(false),
908 selected(false),
909 acceptsHover(false),
910 acceptDrops(false),
911 isMemberOfGroup(false),
912 handlesChildEvents(false),
913 itemDiscovered(false),
914 hasCursor(false),
915 ancestorFlags(0),
916 cacheMode(0),
917 hasBoundingRegionGranularity(false),
918 isWidget(false),
919 dirty(false),
920 dirtyChildren(false),
921 localCollisionHack(false),
922 inSetPosHelper(false),
923 needSortChildren(false),
924 allChildrenDirty(false),
925 fullUpdatePending(false),
926 flags(0),
927 paintedViewBoundingRectsNeedRepaint(false),
928 dirtySceneTransform(true),
929 geometryChanged(true),
930 inDestructor(false),
931 isObject(false),
932 ignoreVisible(false),
933 ignoreOpacity(false),
934 acceptTouchEvents(false),
935 acceptedTouchBeginEvent(false),
936 filtersDescendantEvents(false),
937 sceneTransformTranslateOnly(false),
938 notifyBoundingRectChanged(false),
939 notifyInvalidated(false),
940 mouseSetsFocus(true),
941 explicitActivate(false),
942 wantsActive(false),
943 holesInSiblingIndex(false),
944 sequentialOrdering(true),
945 updateDueToGraphicsEffect(false),
946 scenePosDescendants(false),
947 pendingPolish(false),
948 mayHaveChildWithGraphicsEffect(false),
949 isDeclarativeItem(false),
950 sendParentChangeNotification(false),
951 dirtyChildrenBoundingRect(true),
952 globalStackingOrder(-1),
953 q_ptr(nullptr)
954{
955}
956
957/*!
958 \internal
959*/
960QGraphicsItemPrivate::~QGraphicsItemPrivate()
961{
962}
963
964/*!
965 \internal
966
967 Propagates the ancestor flag \a flag with value \a enabled to all this
968 item's children. If \a root is false, the flag is also set on this item
969 (default is true).
970*/
971void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
972 AncestorFlag flag, bool enabled, bool root)
973{
974 Q_Q(QGraphicsItem);
975 if (root) {
976 // For root items only. This is the item that has either enabled or
977 // disabled \a childFlag, or has been reparented.
978 switch (int(childFlag)) {
979 case -2:
980 flag = AncestorFiltersChildEvents;
981 enabled = q->filtersChildEvents();
982 break;
983 case -1:
984 flag = AncestorHandlesChildEvents;
985 enabled = q->handlesChildEvents();
986 break;
987 case QGraphicsItem::ItemClipsChildrenToShape:
988 flag = AncestorClipsChildren;
989 enabled = flags & QGraphicsItem::ItemClipsChildrenToShape;
990 break;
991 case QGraphicsItem::ItemIgnoresTransformations:
992 flag = AncestorIgnoresTransformations;
993 enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
994 break;
995 case QGraphicsItem::ItemContainsChildrenInShape:
996 flag = AncestorContainsChildren;
997 enabled = flags & QGraphicsItem::ItemContainsChildrenInShape;
998 break;
999 default:
1000 return;
1001 }
1002
1003 if (parent) {
1004 // Inherit the enabled-state from our parents.
1005 if ((parent->d_ptr->ancestorFlags & flag)
1006 || (int(parent->d_ptr->flags & childFlag) == childFlag)
1007 || (int(childFlag) == -1 && parent->d_ptr->handlesChildEvents)
1008 || (int(childFlag) == -2 && parent->d_ptr->filtersDescendantEvents)) {
1009 enabled = true;
1010 ancestorFlags |= flag;
1011 } else {
1012 ancestorFlags &= ~flag;
1013 }
1014 } else {
1015 // Top-level root items don't have any ancestors, so there are no
1016 // ancestor flags either.
1017 ancestorFlags = 0;
1018 }
1019 } else {
1020 // Don't set or propagate the ancestor flag if it's already correct.
1021 if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled))
1022 return;
1023
1024 // Set the flag.
1025 if (enabled)
1026 ancestorFlags |= flag;
1027 else
1028 ancestorFlags &= ~flag;
1029
1030 // Don't process children if the item has the main flag set on itself.
1031 if ((int(childFlag) != -1 && int(flags & childFlag) == childFlag)
1032 || (int(childFlag) == -1 && handlesChildEvents)
1033 || (int(childFlag) == -2 && filtersDescendantEvents))
1034 return;
1035 }
1036
1037 for (int i = 0; i < children.size(); ++i)
1038 children.at(i)->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false);
1039}
1040
1041void QGraphicsItemPrivate::updateAncestorFlags()
1042{
1043 int flags = 0;
1044 if (parent) {
1045 // Inherit the parent's ancestor flags.
1046 QGraphicsItemPrivate *pd = parent->d_ptr.data();
1047 flags = pd->ancestorFlags;
1048
1049 // Add in flags from the parent.
1050 if (pd->filtersDescendantEvents)
1051 flags |= AncestorFiltersChildEvents;
1052 if (pd->handlesChildEvents)
1053 flags |= AncestorHandlesChildEvents;
1054 if (pd->flags & QGraphicsItem::ItemClipsChildrenToShape)
1055 flags |= AncestorClipsChildren;
1056 if (pd->flags & QGraphicsItem::ItemIgnoresTransformations)
1057 flags |= AncestorIgnoresTransformations;
1058 if (pd->flags & QGraphicsItem::ItemContainsChildrenInShape)
1059 flags |= AncestorContainsChildren;
1060 }
1061
1062 if (ancestorFlags == flags)
1063 return; // No change; stop propagation.
1064 ancestorFlags = flags;
1065
1066 // Propagate to children recursively.
1067 for (int i = 0; i < children.size(); ++i)
1068 children.at(i)->d_ptr->updateAncestorFlags();
1069}
1070
1071/*!
1072 \internal
1073
1074 Propagates item group membership.
1075*/
1076void QGraphicsItemPrivate::setIsMemberOfGroup(bool enabled)
1077{
1078 Q_Q(QGraphicsItem);
1079 isMemberOfGroup = enabled;
1080 if (!qgraphicsitem_cast<QGraphicsItemGroup *>(q)) {
1081 foreach (QGraphicsItem *child, children)
1082 child->d_func()->setIsMemberOfGroup(enabled);
1083 }
1084}
1085
1086/*!
1087 \internal
1088
1089 Maps any item pos properties of \a event to \a item's coordinate system.
1090*/
1091void QGraphicsItemPrivate::remapItemPos(QEvent *event, QGraphicsItem *item)
1092{
1093 Q_Q(QGraphicsItem);
1094 switch (event->type()) {
1095 case QEvent::GraphicsSceneMouseMove:
1096 case QEvent::GraphicsSceneMousePress:
1097 case QEvent::GraphicsSceneMouseRelease:
1098 case QEvent::GraphicsSceneMouseDoubleClick: {
1099 QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
1100 mouseEvent->setPos(item->mapFromItem(q, mouseEvent->pos()));
1101 mouseEvent->setLastPos(item->mapFromItem(q, mouseEvent->pos()));
1102 for (int i = 0x1; i <= 0x10; i <<= 1) {
1103 if (mouseEvent->buttons() & i) {
1104 Qt::MouseButton button = Qt::MouseButton(i);
1105 mouseEvent->setButtonDownPos(button, item->mapFromItem(q, mouseEvent->buttonDownPos(button)));
1106 }
1107 }
1108 break;
1109 }
1110 case QEvent::GraphicsSceneWheel: {
1111 QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event);
1112 wheelEvent->setPos(item->mapFromItem(q, wheelEvent->pos()));
1113 break;
1114 }
1115 case QEvent::GraphicsSceneContextMenu: {
1116 QGraphicsSceneContextMenuEvent *contextEvent = static_cast<QGraphicsSceneContextMenuEvent *>(event);
1117 contextEvent->setPos(item->mapFromItem(q, contextEvent->pos()));
1118 break;
1119 }
1120 case QEvent::GraphicsSceneHoverMove: {
1121 QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
1122 hoverEvent->setPos(item->mapFromItem(q, hoverEvent->pos()));
1123 break;
1124 }
1125 default:
1126 break;
1127 }
1128}
1129
1130/*!
1131 \internal
1132
1133 Maps the point \a pos from scene to item coordinates. If \a view is passed and the item
1134 is untransformable, this function will correctly map \a pos from the scene using the
1135 view's transformation.
1136*/
1137
1138QTransform QGraphicsItemPrivate::genericMapFromSceneTransform(const QWidget *viewport) const
1139{
1140 Q_Q(const QGraphicsItem);
1141 if (!itemIsUntransformable())
1142 return sceneTransform.inverted();
1143 const QGraphicsView *view = viewport
1144 ? qobject_cast<QGraphicsView *>(viewport->parentWidget())
1145 : nullptr;
1146 if (view == nullptr)
1147 return sceneTransform.inverted();
1148 // ### More ping pong than needed.
1149 const QTransform viewportTransform = view->viewportTransform();
1150 return viewportTransform * q->deviceTransform(viewportTransform).inverted();
1151}
1152
1153QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos,
1154 const QWidget *viewport) const
1155{
1156 return genericMapFromSceneTransform(viewport).map(pos);
1157}
1158
1159/*!
1160 \internal
1161
1162 Combines this item's position and transform onto \a transform.
1163
1164 If you need to change this function (e.g., adding more transformation
1165 modes / options), make sure to change all places marked with COMBINE.
1166*/
1167void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const
1168{
1169 // COMBINE
1170 if (viewTransform && itemIsUntransformable()) {
1171 *x = q_ptr->deviceTransform(*viewTransform);
1172 } else {
1173 if (transformData)
1174 *x *= transformData->computedFullTransform();
1175 if (!pos.isNull())
1176 *x *= QTransform::fromTranslate(pos.x(), pos.y());
1177 }
1178}
1179
1180/*!
1181 \internal
1182
1183 Combines this item's position and transform onto \a transform.
1184
1185 If you need to change this function (e.g., adding more transformation
1186 modes / options), make sure to change QGraphicsItem::deviceTransform() as
1187 well.
1188*/
1189void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const
1190{
1191 // COMBINE
1192 if (viewTransform && itemIsUntransformable()) {
1193 *x = q_ptr->deviceTransform(*viewTransform);
1194 } else {
1195 x->translate(pos.x(), pos.y());
1196 if (transformData)
1197 *x = transformData->computedFullTransform(x);
1198 }
1199}
1200
1201void QGraphicsItemPrivate::updateSceneTransformFromParent()
1202{
1203 if (parent) {
1204 Q_ASSERT(!parent->d_ptr->dirtySceneTransform);
1205 if (parent->d_ptr->sceneTransformTranslateOnly) {
1206 sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(),
1207 parent->d_ptr->sceneTransform.dy() + pos.y());
1208 } else {
1209 sceneTransform = parent->d_ptr->sceneTransform;
1210 sceneTransform.translate(pos.x(), pos.y());
1211 }
1212 if (transformData) {
1213 sceneTransform = transformData->computedFullTransform(&sceneTransform);
1214 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1215 } else {
1216 sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly;
1217 }
1218 } else if (!transformData) {
1219 sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
1220 sceneTransformTranslateOnly = 1;
1221 } else if (transformData->onlyTransform) {
1222 sceneTransform = transformData->transform;
1223 if (!pos.isNull())
1224 sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y());
1225 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1226 } else if (pos.isNull()) {
1227 sceneTransform = transformData->computedFullTransform();
1228 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1229 } else {
1230 sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
1231 sceneTransform = transformData->computedFullTransform(&sceneTransform);
1232 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
1233 }
1234 dirtySceneTransform = 0;
1235}
1236
1237/*!
1238 \internal
1239
1240 Make sure not to trigger any pure virtual function calls (e.g.,
1241 prepareGeometryChange) if the item is in its destructor, i.e.
1242 inDestructor is 1.
1243*/
1244void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const QVariant *newParentVariant,
1245 const QVariant *thisPointerVariant)
1246{
1247 Q_Q(QGraphicsItem);
1248 if (newParent == parent)
1249 return;
1250
1251 if (isWidget)
1252 static_cast<QGraphicsWidgetPrivate *>(this)->fixFocusChainBeforeReparenting((newParent &&
1253 newParent->isWidget()) ? static_cast<QGraphicsWidget *>(newParent) : 0,
1254 scene);
1255 if (scene) {
1256 // Deliver the change to the index
1257 if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
1258 scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParent);
1259
1260 // Disable scene pos notifications for old ancestors
1261 if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
1262 scene->d_func()->setScenePosItemEnabled(q, false);
1263 }
1264
1265 if (subFocusItem && parent) {
1266 // Make sure none of the old parents point to this guy.
1267 subFocusItem->d_ptr->clearSubFocus(parent);
1268 }
1269
1270 // We anticipate geometry changes. If the item is deleted, it will be
1271 // removed from the index at a later stage, and the whole scene will be
1272 // updated.
1273 if (!inDestructor)
1274 q_ptr->prepareGeometryChange();
1275
1276 if (parent) {
1277 // Remove from current parent
1278 parent->d_ptr->removeChild(q);
1279 if (thisPointerVariant)
1280 parent->itemChange(QGraphicsItem::ItemChildRemovedChange, *thisPointerVariant);
1281 }
1282
1283 // Update toplevelitem list. If this item is being deleted, its parent
1284 // will be 0 but we don't want to register/unregister it in the TLI list.
1285 if (scene && !inDestructor) {
1286 if (parent && !newParent) {
1287 scene->d_func()->registerTopLevelItem(q);
1288 } else if (!parent && newParent) {
1289 scene->d_func()->unregisterTopLevelItem(q);
1290 }
1291 }
1292
1293 // Ensure any last parent focus scope does not point to this item or any of
1294 // its descendents.
1295 QGraphicsItem *p = parent;
1296 QGraphicsItem *parentFocusScopeItem = 0;
1297 while (p) {
1298 if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
1299 // If this item's focus scope's focus scope item points
1300 // to this item or a descendent, then clear it.
1301 QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
1302 if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
1303 parentFocusScopeItem = fsi;
1304 p->d_ptr->focusScopeItem = 0;
1305 fsi->d_ptr->focusScopeItemChange(false);
1306 }
1307 break;
1308 }
1309 p = p->d_ptr->parent;
1310 }
1311
1312 // Update graphics effect optimization flag
1313 if (newParent && (graphicsEffect || mayHaveChildWithGraphicsEffect))
1314 newParent->d_ptr->updateChildWithGraphicsEffectFlagRecursively();
1315
1316 // Update focus scope item ptr in new scope.
1317 QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
1318 if (newFocusScopeItem && newParent) {
1319 QGraphicsItem *p = newParent;
1320 while (p) {
1321 if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
1322 if (subFocusItem && subFocusItem != q_ptr) {
1323 // Find the subFocusItem's topmost focus scope within the new parent's focusscope
1324 QGraphicsItem *ancestorScope = 0;
1325 QGraphicsItem *p2 = subFocusItem->d_ptr->parent;
1326 while (p2 && p2 != p) {
1327 if (p2->d_ptr->flags & QGraphicsItem::ItemIsFocusScope)
1328 ancestorScope = p2;
1329 if (p2->d_ptr->flags & QGraphicsItem::ItemIsPanel)
1330 break;
1331 if (p2 == q_ptr)
1332 break;
1333 p2 = p2->d_ptr->parent;
1334 }
1335 if (ancestorScope)
1336 newFocusScopeItem = ancestorScope;
1337 }
1338
1339 p->d_ptr->focusScopeItem = newFocusScopeItem;
1340 newFocusScopeItem->d_ptr->focusScopeItemChange(true);
1341 // Ensure the new item is no longer the subFocusItem. The
1342 // only way to set focus on a child of a focus scope is
1343 // by setting focus on the scope itself.
1344 if (subFocusItem && !p->focusItem())
1345 subFocusItem->d_ptr->clearSubFocus();
1346 break;
1347 }
1348 p = p->d_ptr->parent;
1349 }
1350 }
1351
1352 // Resolve depth.
1353 invalidateDepthRecursively();
1354
1355 if ((parent = newParent)) {
1356 if (parent->d_func()->scene && parent->d_func()->scene != scene) {
1357 // Move this item to its new parent's scene
1358 parent->d_func()->scene->addItem(q);
1359 } else if (!parent->d_func()->scene && scene) {
1360 // Remove this item from its former scene
1361 scene->removeItem(q);
1362 }
1363
1364 parent->d_ptr->addChild(q);
1365 if (thisPointerVariant)
1366 parent->itemChange(QGraphicsItem::ItemChildAddedChange, *thisPointerVariant);
1367 if (scene) {
1368 // Re-enable scene pos notifications for new ancestors
1369 if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
1370 scene->d_func()->setScenePosItemEnabled(q, true);
1371 }
1372
1373 // Propagate dirty flags to the new parent
1374 markParentDirty(/*updateBoundingRect=*/true);
1375
1376 // Inherit ancestor flags from the new parent.
1377 updateAncestorFlags();
1378
1379 // Update item visible / enabled.
1380 if (parent->d_ptr->visible != visible) {
1381 if (!parent->d_ptr->visible || !explicitlyHidden)
1382 setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ false);
1383 }
1384 if (parent->isEnabled() != enabled) {
1385 if (!parent->d_ptr->enabled || !explicitlyDisabled)
1386 setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ false);
1387 }
1388
1389 // Auto-activate if visible and the parent is active.
1390 if (visible && parent->isActive())
1391 q->setActive(true);
1392 } else {
1393 // Inherit ancestor flags from the new parent.
1394 updateAncestorFlags();
1395
1396 if (!inDestructor) {
1397 // Update item visible / enabled.
1398 if (!visible && !explicitlyHidden)
1399 setVisibleHelper(true, /* explicit = */ false);
1400 if (!enabled && !explicitlyDisabled)
1401 setEnabledHelper(true, /* explicit = */ false);
1402 }
1403 }
1404
1405 dirtySceneTransform = 1;
1406 if (!inDestructor && (transformData || (newParent && newParent->d_ptr->transformData)))
1407 transformChanged();
1408
1409 // Restore the sub focus chain.
1410 if (subFocusItem) {
1411 subFocusItem->d_ptr->setSubFocus(newParent);
1412 if (parent && parent->isActive())
1413 subFocusItem->setFocus();
1414 }
1415
1416 // Deliver post-change notification
1417 if (newParentVariant)
1418 q->itemChange(QGraphicsItem::ItemParentHasChanged, *newParentVariant);
1419
1420 if (isObject)
1421 emit static_cast<QGraphicsObject *>(q)->parentChanged();
1422}
1423
1424/*!
1425 \internal
1426
1427 Returns the bounding rect of this item's children (excluding itself).
1428*/
1429void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem)
1430{
1431 Q_Q(QGraphicsItem);
1432
1433 QRectF childrenRect;
1434 QRectF *result = rect;
1435 rect = &childrenRect;
1436 const bool setTopMostEffectItem = !topMostEffectItem;
1437
1438 for (int i = 0; i < children.size(); ++i) {
1439 QGraphicsItem *child = children.at(i);
1440 QGraphicsItemPrivate *childd = child->d_ptr.data();
1441 if (setTopMostEffectItem)
1442 topMostEffectItem = child;
1443 bool hasPos = !childd->pos.isNull();
1444 if (hasPos || childd->transformData) {
1445 // COMBINE
1446 QTransform matrix = childd->transformToParent();
1447 if (x)
1448 matrix *= *x;
1449 *rect |= matrix.mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
1450 if (!childd->children.isEmpty())
1451 childd->childrenBoundingRectHelper(&matrix, rect, topMostEffectItem);
1452 } else {
1453 if (x)
1454 *rect |= x->mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
1455 else
1456 *rect |= child->d_ptr->effectiveBoundingRect(topMostEffectItem);
1457 if (!childd->children.isEmpty())
1458 childd->childrenBoundingRectHelper(x, rect, topMostEffectItem);
1459 }
1460 }
1461
1462 if (flags & QGraphicsItem::ItemClipsChildrenToShape){
1463 if (x)
1464 *rect &= x->mapRect(q->boundingRect());
1465 else
1466 *rect &= q->boundingRect();
1467 }
1468
1469 *result |= *rect;
1470}
1471
1472void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
1473 const QRegion &exposedRegion, bool allItems) const
1474{
1475 Q_ASSERT(option);
1476 Q_Q(const QGraphicsItem);
1477
1478 // Initialize standard QStyleOption values.
1479 const QRectF brect = q->boundingRect();
1480 option->state = QStyle::State_None;
1481 option->rect = brect.toRect();
1482 option->levelOfDetail = 1;
1483 option->exposedRect = brect;
1484
1485 // Style animations require a QObject-based animation target.
1486 // If a plain QGraphicsItem is used to draw animated controls,
1487 // QStyle is let to send animation updates to the whole scene.
1488 option->styleObject = q_ptr->toGraphicsObject();
1489 if (!option->styleObject)
1490 option->styleObject = scene;
1491
1492 if (selected)
1493 option->state |= QStyle::State_Selected;
1494 if (enabled)
1495 option->state |= QStyle::State_Enabled;
1496 if (q->hasFocus())
1497 option->state |= QStyle::State_HasFocus;
1498 if (scene) {
1499 if (scene->d_func()->hoverItems.contains(q_ptr))
1500 option->state |= QStyle::State_MouseOver;
1501 if (q == scene->mouseGrabberItem())
1502 option->state |= QStyle::State_Sunken;
1503 }
1504
1505 if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption))
1506 return;
1507
1508 // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect).
1509 option->matrix = worldTransform.toAffine(); //### discards perspective
1510
1511 if (!allItems) {
1512 // Determine the item's exposed area
1513 option->exposedRect = QRectF();
1514 const QTransform reverseMap = worldTransform.inverted();
1515 for (const QRect &exposedRect : exposedRegion) {
1516 option->exposedRect |= reverseMap.mapRect(QRectF(exposedRect));
1517 if (option->exposedRect.contains(brect))
1518 break;
1519 }
1520 option->exposedRect &= brect;
1521 }
1522}
1523
1524/*!
1525 \internal
1526
1527 Empty all cached pixmaps from the pixmap cache.
1528*/
1529void QGraphicsItemCache::purge()
1530{
1531 QPixmapCache::remove(key);
1532 key = QPixmapCache::Key();
1533 const auto &constDeviceData = deviceData; // avoid detach
1534 for (const auto &data : constDeviceData)
1535 QPixmapCache::remove(data.key);
1536 deviceData.clear();
1537 allExposed = true;
1538 exposed.clear();
1539}
1540
1541/*!
1542 Constructs a QGraphicsItem with the given \a parent item.
1543 It does not modify the parent object returned by QObject::parent().
1544
1545 If \a parent is \nullptr, you can add the item to a scene by calling
1546 QGraphicsScene::addItem(). The item will then become a top-level item.
1547
1548 \sa QGraphicsScene::addItem(), setParentItem()
1549*/
1550QGraphicsItem::QGraphicsItem(QGraphicsItem *parent)
1551 : d_ptr(new QGraphicsItemPrivate)
1552{
1553 d_ptr->q_ptr = this;
1554 setParentItem(parent);
1555}
1556
1557/*!
1558 \internal
1559*/
1560QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent)
1561 : d_ptr(&dd)
1562{
1563 d_ptr->q_ptr = this;
1564 setParentItem(parent);
1565}
1566
1567/*!
1568 Destroys the QGraphicsItem and all its children. If this item is currently
1569 associated with a scene, the item will be removed from the scene before it
1570 is deleted.
1571
1572 \note It is more efficient to remove the item from the QGraphicsScene before
1573 destroying the item.
1574*/
1575QGraphicsItem::~QGraphicsItem()
1576{
1577 if (d_ptr->isObject) {
1578 QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
1579 QObjectPrivate *p = QObjectPrivate::get(o);
1580 p->wasDeleted = true;
1581 if (p->declarativeData) {
1582 p->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1583 if (static_cast<QAbstractDeclarativeDataImpl*>(p->declarativeData)->ownedByQml1) {
1584 if (QAbstractDeclarativeData::destroyed_qml1)
1585 QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o);
1586 } else {
1587 if (QAbstractDeclarativeData::destroyed)
1588 QAbstractDeclarativeData::destroyed(p->declarativeData, o);
1589 }
1590 p->declarativeData = 0;
1591 p->wasDeleted = false;
1592 }
1593 }
1594
1595 d_ptr->inDestructor = 1;
1596 d_ptr->removeExtraItemCache();
1597
1598#ifndef QT_NO_GESTURES
1599 if (d_ptr->isObject && !d_ptr->gestureContext.isEmpty()) {
1600 QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
1601 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1602 const auto types = d_ptr->gestureContext.keys(); // FIXME: iterate over the map directly?
1603 for (Qt::GestureType type : types)
1604 manager->cleanupCachedGestures(o, type);
1605 }
1606 }
1607#endif
1608
1609 clearFocus();
1610 setFocusProxy(0);
1611
1612 // Update focus scope item ptr.
1613 QGraphicsItem *p = d_ptr->parent;
1614 while (p) {
1615 if (p->flags() & ItemIsFocusScope) {
1616 if (p->d_ptr->focusScopeItem == this)
1617 p->d_ptr->focusScopeItem = 0;
1618 break;
1619 }
1620 p = p->d_ptr->parent;
1621 }
1622
1623 if (!d_ptr->children.isEmpty()) {
1624 while (!d_ptr->children.isEmpty())
1625 delete d_ptr->children.first();
1626 Q_ASSERT(d_ptr->children.isEmpty());
1627 }
1628
1629 if (d_ptr->scene) {
1630 d_ptr->scene->d_func()->removeItemHelper(this);
1631 } else {
1632 d_ptr->resetFocusProxy();
1633 setParentItem(0);
1634 }
1635
1636#if QT_CONFIG(graphicseffect)
1637 delete d_ptr->graphicsEffect;
1638#endif // QT_CONFIG(graphicseffect)
1639 if (d_ptr->transformData) {
1640 for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
1641 QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
1642 static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
1643 delete t;
1644 }
1645 }
1646 delete d_ptr->transformData;
1647
1648 if (QGraphicsItemCustomDataStore *dataStore = qt_dataStore())
1649 dataStore->data.remove(this);
1650}
1651
1652/*!
1653 Returns the current scene for the item, or \nullptr if the item is
1654 not stored in a scene.
1655
1656 To add or move an item to a scene, call QGraphicsScene::addItem().
1657*/
1658QGraphicsScene *QGraphicsItem::scene() const
1659{
1660 return d_ptr->scene;
1661}
1662
1663/*!
1664 Returns a pointer to this item's item group, or \nullptr if this
1665 item is not member of a group.
1666
1667 \sa QGraphicsItemGroup, QGraphicsScene::createItemGroup()
1668*/
1669QGraphicsItemGroup *QGraphicsItem::group() const
1670{
1671 if (!d_ptr->isMemberOfGroup)
1672 return nullptr;
1673 QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
1674 while ((parent = parent->d_ptr->parent)) {
1675 if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(parent))
1676 return group;
1677 }
1678 // Unreachable; if d_ptr->isMemberOfGroup is != 0, then one parent of this
1679 // item is a group item.
1680 return nullptr;
1681}
1682
1683/*!
1684 Adds this item to the item group \a group. If \a group is \nullptr, this item is
1685 removed from any current group and added as a child of the previous
1686 group's parent.
1687
1688 \sa group(), QGraphicsScene::createItemGroup()
1689*/
1690void QGraphicsItem::setGroup(QGraphicsItemGroup *group)
1691{
1692 if (!group) {
1693 if (QGraphicsItemGroup *group = this->group())
1694 group->removeFromGroup(this);
1695 } else {
1696 group->addToGroup(this);
1697 }
1698}
1699
1700/*!
1701 Returns a pointer to this item's parent item. If this item does not have a
1702 parent, \nullptr is returned.
1703
1704 \sa setParentItem(), childItems()
1705*/
1706QGraphicsItem *QGraphicsItem::parentItem() const
1707{
1708 return d_ptr->parent;
1709}
1710
1711/*!
1712 Returns this item's top-level item. The top-level item is the item's
1713 topmost ancestor item whose parent is \nullptr. If an item has no
1714 parent, its own pointer is returned (i.e., a top-level item is its
1715 own top-level item).
1716
1717 \sa parentItem()
1718*/
1719QGraphicsItem *QGraphicsItem::topLevelItem() const
1720{
1721 QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
1722 while (QGraphicsItem *grandPa = parent->parentItem())
1723 parent = grandPa;
1724 return parent;
1725}
1726
1727/*!
1728 \since 4.6
1729
1730 Returns a pointer to the item's parent, cast to a QGraphicsObject. Returns
1731 \nullptr if the parent item is not a QGraphicsObject.
1732
1733 \sa parentItem(), childItems()
1734*/
1735QGraphicsObject *QGraphicsItem::parentObject() const
1736{
1737 QGraphicsItem *p = d_ptr->parent;
1738 return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : nullptr;
1739}
1740
1741/*!
1742 \since 4.4
1743
1744 Returns a pointer to the item's parent widget. The item's parent widget is
1745 the closest parent item that is a widget.
1746
1747 \sa parentItem(), childItems()
1748*/
1749QGraphicsWidget *QGraphicsItem::parentWidget() const
1750{
1751 QGraphicsItem *p = parentItem();
1752 while (p && !p->isWidget())
1753 p = p->parentItem();
1754 return (p && p->isWidget()) ? static_cast<QGraphicsWidget *>(p) : 0;
1755}
1756
1757/*!
1758 \since 4.4
1759
1760 Returns a pointer to the item's top level widget (i.e., the item's
1761 ancestor whose parent is \nullptr, or whose parent is not a widget), or
1762 \nullptr if this item does not have a top level widget. If the item
1763 is its own top level widget, this function returns a pointer to the
1764 item itself.
1765*/
1766QGraphicsWidget *QGraphicsItem::topLevelWidget() const
1767{
1768 if (const QGraphicsWidget *p = parentWidget())
1769 return p->topLevelWidget();
1770 return isWidget() ? static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)) : nullptr;
1771}
1772
1773/*!
1774 \since 4.4
1775
1776 Returns the item's window, or \nullptr if this item does not have a
1777 window. If the item is a window, it will return itself. Otherwise
1778 it will return the closest ancestor that is a window.
1779
1780 \sa QGraphicsWidget::isWindow()
1781*/
1782QGraphicsWidget *QGraphicsItem::window() const
1783{
1784 QGraphicsItem *p = panel();
1785 if (p && p->isWindow())
1786 return static_cast<QGraphicsWidget *>(p);
1787 return nullptr;
1788}
1789
1790/*!
1791 \since 4.6
1792
1793 Returns the item's panel, or \nullptr if this item does not have a
1794 panel. If the item is a panel, it will return itself. Otherwise it
1795 will return the closest ancestor that is a panel.
1796
1797 \sa isPanel(), ItemIsPanel
1798*/
1799QGraphicsItem *QGraphicsItem::panel() const
1800{
1801 if (d_ptr->flags & ItemIsPanel)
1802 return const_cast<QGraphicsItem *>(this);
1803 return d_ptr->parent ? d_ptr->parent->panel() : nullptr;
1804}
1805
1806/*!
1807 \since 4.6
1808
1809 Return the graphics item cast to a QGraphicsObject, if the class is actually a
1810 graphics object, 0 otherwise.
1811*/
1812QGraphicsObject *QGraphicsItem::toGraphicsObject()
1813{
1814 return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : 0;
1815}
1816
1817/*!
1818 \since 4.6
1819
1820 Return the graphics item cast to a QGraphicsObject, if the class is actually a
1821 graphics object, 0 otherwise.
1822*/
1823const QGraphicsObject *QGraphicsItem::toGraphicsObject() const
1824{
1825 return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0;
1826}
1827
1828/*!
1829 Sets this item's parent item to \a newParent. If this item already
1830 has a parent, it is first removed from the previous parent. If \a
1831 newParent is 0, this item will become a top-level item.
1832
1833 Note that this implicitly adds this graphics item to the scene of
1834 the parent. You should not \l{QGraphicsScene::addItem()}{add} the
1835 item to the scene yourself.
1836
1837 The behavior when calling this function on an item that is an ancestor of
1838 \a newParent is undefined.
1839
1840 \sa parentItem(), childItems()
1841*/
1842void QGraphicsItem::setParentItem(QGraphicsItem *newParent)
1843{
1844 if (newParent == this) {
1845 qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
1846 return;
1847 }
1848 if (newParent == d_ptr->parent)
1849 return;
1850
1851 const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange,
1852 QVariant::fromValue<QGraphicsItem *>(newParent)));
1853 newParent = qvariant_cast<QGraphicsItem *>(newParentVariant);
1854 if (newParent == d_ptr->parent)
1855 return;
1856
1857 const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this));
1858 d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant);
1859}
1860
1861/*!
1862 \fn QList<QGraphicsItem *> QGraphicsItem::children() const
1863 \obsolete
1864
1865 Use childItems() instead.
1866
1867 \sa setParentItem()
1868*/
1869
1870/*!
1871 \since 4.4
1872
1873 Returns a list of this item's children.
1874
1875 The items are sorted by stacking order. This takes into account both the
1876 items' insertion order and their Z-values.
1877
1878 \sa setParentItem(), zValue(), {QGraphicsItem#Sorting}{Sorting}
1879*/
1880QList<QGraphicsItem *> QGraphicsItem::childItems() const
1881{
1882 const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren();
1883 return d_ptr->children;
1884}
1885
1886/*!
1887 \since 4.4
1888 Returns \c true if this item is a widget (i.e., QGraphicsWidget); otherwise,
1889 returns \c false.
1890*/
1891bool QGraphicsItem::isWidget() const
1892{
1893 return d_ptr->isWidget;
1894}
1895
1896/*!
1897 \since 4.4
1898 Returns \c true if the item is a QGraphicsWidget window, otherwise returns
1899 false.
1900
1901 \sa QGraphicsWidget::windowFlags()
1902*/
1903bool QGraphicsItem::isWindow() const
1904{
1905 return d_ptr->isWidget && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
1906}
1907
1908/*!
1909 \since 4.6
1910 Returns \c true if the item is a panel; otherwise returns \c false.
1911
1912 \sa QGraphicsItem::panel(), ItemIsPanel
1913*/
1914bool QGraphicsItem::isPanel() const
1915{
1916 return d_ptr->flags & ItemIsPanel;
1917}
1918
1919/*!
1920 Returns this item's flags. The flags describe what configurable features
1921 of the item are enabled and not. For example, if the flags include
1922 ItemIsFocusable, the item can accept input focus.
1923
1924 By default, no flags are enabled.
1925
1926 \sa setFlags(), setFlag()
1927*/
1928QGraphicsItem::GraphicsItemFlags QGraphicsItem::flags() const
1929{
1930 return GraphicsItemFlags(d_ptr->flags);
1931}
1932
1933/*!
1934 If \a enabled is true, the item flag \a flag is enabled; otherwise, it is
1935 disabled.
1936
1937 \sa flags(), setFlags()
1938*/
1939void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled)
1940{
1941 if (enabled)
1942 setFlags(GraphicsItemFlags(d_ptr->flags) | flag);
1943 else
1944 setFlags(GraphicsItemFlags(d_ptr->flags) & ~flag);
1945}
1946
1947/*!
1948 Sets the item flags to \a flags. All flags in \a flags are enabled; all
1949 flags not in \a flags are disabled.
1950
1951 If the item had focus and \a flags does not enable ItemIsFocusable, the
1952 item loses focus as a result of calling this function. Similarly, if the
1953 item was selected, and \a flags does not enabled ItemIsSelectable, the
1954 item is automatically unselected.
1955
1956 By default, no flags are enabled. (QGraphicsWidget enables the
1957 ItemSendsGeometryChanges flag by default in order to track position
1958 changes.)
1959
1960 \sa flags(), setFlag()
1961*/
1962void QGraphicsItem::setFlags(GraphicsItemFlags flags)
1963{
1964 // Notify change and check for adjustment.
1965 if (quint32(d_ptr->flags) == quint32(flags))
1966 return;
1967 flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt());
1968 if (quint32(d_ptr->flags) == quint32(flags))
1969 return;
1970 if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
1971 d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, &flags);
1972
1973 // Flags that alter the geometry of the item (or its children).
1974 const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable);
1975 bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
1976 if (fullUpdate)
1977 d_ptr->updatePaintedViewBoundingRects(/*children=*/true);
1978
1979 // Keep the old flags to compare the diff.
1980 GraphicsItemFlags oldFlags = GraphicsItemFlags(d_ptr->flags);
1981
1982 // Update flags.
1983 d_ptr->flags = flags;
1984
1985 if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
1986 // Clear focus on the item if it has focus when the focusable flag
1987 // is unset.
1988 clearFocus();
1989 }
1990
1991 if (!(d_ptr->flags & ItemIsSelectable) && isSelected()) {
1992 // Unselect the item if it is selected when the selectable flag is
1993 // unset.
1994 setSelected(false);
1995 }
1996
1997 if ((flags & ItemClipsChildrenToShape) != (oldFlags & ItemClipsChildrenToShape)) {
1998 // Item children clipping changes. Propagate the ancestor flag to
1999 // all children.
2000 d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
2001 // The childrenBoundingRect is clipped to the boundingRect in case of ItemClipsChildrenToShape,
2002 // which means we have to invalidate the cached childrenBoundingRect whenever this flag changes.
2003 d_ptr->dirtyChildrenBoundingRect = 1;
2004 d_ptr->markParentDirty(true);
2005 }
2006
2007 if ((flags & ItemContainsChildrenInShape) != (oldFlags & ItemContainsChildrenInShape)) {
2008 // Item children containtment changes. Propagate the ancestor flag to all children.
2009 d_ptr->updateAncestorFlag(ItemContainsChildrenInShape);
2010 }
2011
2012 if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
2013 // Item children clipping changes. Propagate the ancestor flag to
2014 // all children.
2015 d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
2016 }
2017
2018 if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) {
2019 // NB! We change the flags directly here, so we must also update d_ptr->flags.
2020 // Note that this has do be done before the ItemStacksBehindParent check
2021 // below; otherwise we will loose the change.
2022
2023 // Update stack-behind.
2024 if (d_ptr->z < qreal(0.0))
2025 flags |= ItemStacksBehindParent;
2026 else
2027 flags &= ~ItemStacksBehindParent;
2028 d_ptr->flags = flags;
2029 }
2030
2031 if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
2032 // NB! This check has to come after the ItemNegativeZStacksBehindParent
2033 // check above. Be careful.
2034
2035 // Ensure child item sorting is up to date when toggling this flag.
2036 if (d_ptr->parent)
2037 d_ptr->parent->d_ptr->needSortChildren = 1;
2038 else if (d_ptr->scene)
2039 d_ptr->scene->d_func()->needSortTopLevelItems = 1;
2040 }
2041
2042 if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) {
2043 // Update input method sensitivity in any views.
2044 if (d_ptr->scene)
2045 d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
2046 }
2047
2048 if ((flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
2049 bool becomesPanel = (flags & ItemIsPanel);
2050 if ((d_ptr->panelModality != NonModal) && d_ptr->scene) {
2051 // update the panel's modal state
2052 if (becomesPanel)
2053 d_ptr->scene->d_func()->enterModal(this);
2054 else
2055 d_ptr->scene->d_func()->leaveModal(this);
2056 }
2057 if (d_ptr->isWidget && (becomesPanel || parentWidget())) {
2058 QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this);
2059 QGraphicsWidget *focusFirst = w;
2060 QGraphicsWidget *focusLast = w;
2061 for (;;) {
2062 QGraphicsWidget *test = focusLast->d_func()->focusNext;
2063 if (!w->isAncestorOf(test) || test == w)
2064 break;
2065 focusLast = test;
2066 }
2067
2068 if (becomesPanel) {
2069 // unlink own widgets from focus chain
2070 QGraphicsWidget *beforeMe = w->d_func()->focusPrev;
2071 QGraphicsWidget *afterMe = focusLast->d_func()->focusNext;
2072 beforeMe->d_func()->focusNext = afterMe;
2073 afterMe->d_func()->focusPrev = beforeMe;
2074 focusFirst->d_func()->focusPrev = focusLast;
2075 focusLast->d_func()->focusNext = focusFirst;
2076 if (!isAncestorOf(focusFirst->d_func()->focusNext))
2077 focusFirst->d_func()->focusNext = w;
2078 } else if (QGraphicsWidget *pw = parentWidget()) {
2079 // link up own widgets to focus chain
2080 QGraphicsWidget *beforeMe = pw;
2081 QGraphicsWidget *afterMe = pw->d_func()->focusNext;
2082 beforeMe->d_func()->focusNext = w;
2083 afterMe->d_func()->focusPrev = focusLast;
2084 w->d_func()->focusPrev = beforeMe;
2085 focusLast->d_func()->focusNext = afterMe;
2086 }
2087 }
2088 }
2089
2090 if (d_ptr->scene) {
2091 if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) {
2092 if (flags & ItemSendsScenePositionChanges)
2093 d_ptr->scene->d_func()->registerScenePosItem(this);
2094 else
2095 d_ptr->scene->d_func()->unregisterScenePosItem(this);
2096 }
2097 d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
2098 }
2099
2100 // Notify change.
2101 itemChange(ItemFlagsHaveChanged, quint32(flags));
2102}
2103
2104/*!
2105 \since 4.4
2106 Returns the cache mode for this item. The default mode is NoCache (i.e.,
2107 cache is disabled and all painting is immediate).
2108
2109 \sa setCacheMode()
2110*/
2111QGraphicsItem::CacheMode QGraphicsItem::cacheMode() const
2112{
2113 return QGraphicsItem::CacheMode(d_ptr->cacheMode);
2114}
2115
2116/*!
2117 \since 4.4
2118 Sets the item's cache mode to \a mode.
2119
2120 The optional \a logicalCacheSize argument is used only by
2121 ItemCoordinateCache mode, and describes the resolution of the cache
2122 buffer; if \a logicalCacheSize is (100, 100), QGraphicsItem will fit the
2123 item into 100x100 pixels in graphics memory, regardless of the logical
2124 size of the item itself. By default QGraphicsItem uses the size of
2125 boundingRect(). For all other cache modes than ItemCoordinateCache, \a
2126 logicalCacheSize is ignored.
2127
2128 Caching can speed up rendering if your item spends a significant time
2129 redrawing itself. In some cases the cache can also slow down rendering, in
2130 particular when the item spends less time redrawing than QGraphicsItem
2131 spends redrawing from the cache.
2132
2133 When caching is enabled, an item's paint() function will generally draw into an
2134 offscreen pixmap cache; for any subsequent
2135 repaint requests, the Graphics View framework will redraw from the
2136 cache. This approach works particularly well with QGLWidget, which stores
2137 all the cache as OpenGL textures.
2138
2139 Be aware that QPixmapCache's cache limit may need to be changed to obtain
2140 optimal performance.
2141
2142 You can read more about the different cache modes in the CacheMode
2143 documentation.
2144
2145 \note Enabling caching does not imply that the item's paint() function will be
2146 called only in response to an explicit update() call. For instance, under
2147 memory pressure, Qt may decide to drop some of the cache information;
2148 in such cases an item's paint() function will be called even if there
2149 was no update() call (that is, exactly as if there were no caching enabled).
2150
2151 \sa CacheMode, QPixmapCache::setCacheLimit()
2152*/
2153void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
2154{
2155 CacheMode lastMode = CacheMode(d_ptr->cacheMode);
2156 d_ptr->cacheMode = mode;
2157 bool noVisualChange = (mode == NoCache && lastMode == NoCache)
2158 || (mode == NoCache && lastMode == DeviceCoordinateCache)
2159 || (mode == DeviceCoordinateCache && lastMode == NoCache)
2160 || (mode == DeviceCoordinateCache && lastMode == DeviceCoordinateCache);
2161 if (mode == NoCache) {
2162 d_ptr->removeExtraItemCache();
2163 } else {
2164 QGraphicsItemCache *cache = d_ptr->extraItemCache();
2165
2166 // Reset old cache
2167 cache->purge();
2168
2169 if (mode == ItemCoordinateCache) {
2170 if (lastMode == mode && cache->fixedSize == logicalCacheSize)
2171 noVisualChange = true;
2172 cache->fixedSize = logicalCacheSize;
2173 }
2174 }
2175 if (!noVisualChange)
2176 update();
2177}
2178
2179/*!
2180 \since 4.6
2181
2182 Returns the modality for this item.
2183*/
2184QGraphicsItem::PanelModality QGraphicsItem::panelModality() const
2185{
2186 return d_ptr->panelModality;
2187}
2188
2189/*!
2190 \since 4.6
2191
2192 Sets the modality for this item to \a panelModality.
2193
2194 Changing the modality of a visible item takes effect immediately.
2195*/
2196void QGraphicsItem::setPanelModality(PanelModality panelModality)
2197{
2198 if (d_ptr->panelModality == panelModality)
2199 return;
2200
2201 PanelModality previousModality = d_ptr->panelModality;
2202 bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible());
2203 if (enterLeaveModal && panelModality == NonModal)
2204 d_ptr->scene->d_func()->leaveModal(this);
2205 d_ptr->panelModality = panelModality;
2206 if (enterLeaveModal && d_ptr->panelModality != NonModal)
2207 d_ptr->scene->d_func()->enterModal(this, previousModality);
2208}
2209
2210/*!
2211 \since 4.6
2212
2213 Returns \c true if this item is blocked by a modal panel, false otherwise. If \a blockingPanel is
2214 non-zero, \a blockingPanel will be set to the modal panel that is blocking this item. If this
2215 item is not blocked, \a blockingPanel will not be set by this function.
2216
2217 This function always returns \c false for items not in a scene.
2218
2219 \sa panelModality(), setPanelModality(), PanelModality
2220*/
2221bool QGraphicsItem::isBlockedByModalPanel(QGraphicsItem **blockingPanel) const
2222{
2223 if (!d_ptr->scene)
2224 return false;
2225
2226
2227 QGraphicsItem *dummy = 0;
2228 if (!blockingPanel)
2229 blockingPanel = &dummy;
2230
2231 const QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func();
2232 if (scene_d->modalPanels.isEmpty())
2233 return false;
2234
2235 // ###
2236 if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this)
2237 return false;
2238
2239 for (int i = 0; i < scene_d->modalPanels.count(); ++i) {
2240 QGraphicsItem *modalPanel = scene_d->modalPanels.at(i);
2241 if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
2242 // Scene modal panels block all non-descendents.
2243 if (modalPanel != this && !modalPanel->isAncestorOf(this)) {
2244 *blockingPanel = modalPanel;
2245 return true;
2246 }
2247 } else {
2248 // Window modal panels block ancestors and siblings/cousins.
2249 if (modalPanel != this
2250 && !modalPanel->isAncestorOf(this)
2251 && commonAncestorItem(modalPanel)) {
2252 *blockingPanel = modalPanel;
2253 return true;
2254 }
2255 }
2256 }
2257 return false;
2258}
2259
2260#ifndef QT_NO_TOOLTIP
2261/*!
2262 Returns the item's tool tip, or an empty QString if no tool tip has been
2263 set.
2264
2265 \sa setToolTip(), QToolTip
2266*/
2267QString QGraphicsItem::toolTip() const
2268{
2269 return d_ptr->extra(QGraphicsItemPrivate::ExtraToolTip).toString();
2270}
2271
2272/*!
2273 Sets the item's tool tip to \a toolTip. If \a toolTip is empty, the item's
2274 tool tip is cleared.
2275
2276 \sa toolTip(), QToolTip
2277*/
2278void QGraphicsItem::setToolTip(const QString &toolTip)
2279{
2280 const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip));
2281 d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString());
2282 itemChange(ItemToolTipHasChanged, toolTipVariant);
2283}
2284#endif // QT_NO_TOOLTIP
2285
2286#ifndef QT_NO_CURSOR
2287/*!
2288 Returns the current cursor shape for the item. The mouse cursor
2289 will assume this shape when it's over this item.
2290 See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
2291 range of useful shapes.
2292
2293 An editor item might want to use an I-beam cursor:
2294
2295 \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 2
2296
2297 If no cursor has been set, the cursor of the item beneath is used.
2298
2299 \sa setCursor(), hasCursor(), unsetCursor(), QWidget::cursor,
2300 QApplication::overrideCursor()
2301*/
2302QCursor QGraphicsItem::cursor() const
2303{
2304 return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor));
2305}
2306
2307/*!
2308 Sets the current cursor shape for the item to \a cursor. The mouse cursor
2309 will assume this shape when it's over this item.
2310 See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
2311 range of useful shapes.
2312
2313 An editor item might want to use an I-beam cursor:
2314
2315 \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 3
2316
2317 If no cursor has been set, the cursor of the item beneath is used.
2318
2319 \sa cursor(), hasCursor(), unsetCursor(), QWidget::cursor,
2320 QApplication::overrideCursor()
2321*/
2322void QGraphicsItem::setCursor(const QCursor &cursor)
2323{
2324 const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor)));
2325 d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant));
2326 d_ptr->hasCursor = 1;
2327 if (d_ptr->scene) {
2328 d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
2329 const auto views = d_ptr->scene->views();
2330 for (QGraphicsView *view : views) {
2331 view->viewport()->setMouseTracking(true);
2332 // Note: Some of this logic is duplicated in QGraphicsView's mouse events.
2333 if (view->underMouse()) {
2334 const auto itemsUnderCursor = view->items(view->mapFromGlobal(QCursor::pos()));
2335 for (QGraphicsItem *itemUnderCursor : itemsUnderCursor) {
2336 if (itemUnderCursor->hasCursor()) {
2337 QMetaObject::invokeMethod(view, "_q_setViewportCursor",
2338 Q_ARG(QCursor, itemUnderCursor->cursor()));
2339 break;
2340 }
2341 }
2342 break;
2343 }
2344 }
2345 }
2346 itemChange(ItemCursorHasChanged, cursorVariant);
2347}
2348
2349/*!
2350 Returns \c true if this item has a cursor set; otherwise, false is returned.
2351
2352 By default, items don't have any cursor set. cursor() will return a
2353 standard pointing arrow cursor.
2354
2355 \sa unsetCursor()
2356*/
2357bool QGraphicsItem::hasCursor() const
2358{
2359 return d_ptr->hasCursor;
2360}
2361
2362/*!
2363 Clears the cursor from this item.
2364
2365 \sa hasCursor(), setCursor()
2366*/
2367void QGraphicsItem::unsetCursor()
2368{
2369 if (!d_ptr->hasCursor)
2370 return;
2371 d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraCursor);
2372 d_ptr->hasCursor = 0;
2373 if (d_ptr->scene) {
2374 const auto views = d_ptr->scene->views();
2375 for (QGraphicsView *view : views) {
2376 if (view->underMouse() && view->itemAt(view->mapFromGlobal(QCursor::pos())) == this) {
2377 QMetaObject::invokeMethod(view, "_q_unsetViewportCursor");
2378 break;
2379 }
2380 }
2381 }
2382}
2383
2384#endif // QT_NO_CURSOR
2385
2386/*!
2387 Returns \c true if the item is visible; otherwise, false is returned.
2388
2389 Note that the item's general visibility is unrelated to whether or not it
2390 is actually being visualized by a QGraphicsView.
2391
2392 \sa setVisible()
2393*/
2394bool QGraphicsItem::isVisible() const
2395{
2396 return d_ptr->visible;
2397}
2398
2399/*!
2400 \since 4.4
2401 Returns \c true if the item is visible to \a parent; otherwise, false is
2402 returned. \a parent can be \nullptr, in which case this function will return
2403 whether the item is visible to the scene or not.
2404
2405 An item may not be visible to its ancestors even if isVisible() is true. It
2406 may also be visible to its ancestors even if isVisible() is false. If
2407 any ancestor is hidden, the item itself will be implicitly hidden, in which
2408 case this function will return false.
2409
2410 \sa isVisible(), setVisible()
2411*/
2412bool QGraphicsItem::isVisibleTo(const QGraphicsItem *parent) const
2413{
2414 const QGraphicsItem *p = this;
2415 if (d_ptr->explicitlyHidden)
2416 return false;
2417 do {
2418 if (p == parent)
2419 return true;
2420 if (p->d_ptr->explicitlyHidden)
2421 return false;
2422 } while ((p = p->d_ptr->parent));
2423 return parent == 0;
2424}
2425
2426/*!
2427 \internal
2428
2429 Sets this item's visibility to \a newVisible. If \a explicitly is true,
2430 this item will be "explicitly" \a newVisible; otherwise, it.. will not be.
2431*/
2432void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
2433 bool update, bool hiddenByPanel)
2434{
2435 Q_Q(QGraphicsItem);
2436
2437 // Update explicit bit.
2438 if (explicitly)
2439 explicitlyHidden = newVisible ? 0 : 1;
2440
2441 // Check if there's nothing to do.
2442 if (visible == quint32(newVisible))
2443 return;
2444
2445 // Don't show child if parent is not visible
2446 if (parent && newVisible && !parent->d_ptr->visible)
2447 return;
2448
2449 // Modify the property.
2450 const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange,
2451 quint32(newVisible)));
2452 newVisible = newVisibleVariant.toBool();
2453 if (visible == quint32(newVisible))
2454 return;
2455 visible = newVisible;
2456
2457 // Schedule redrawing
2458 if (update) {
2459 QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
2460 if (c)
2461 c->purge();
2462 if (scene) {
2463#if QT_CONFIG(graphicseffect)
2464 invalidateParentGraphicsEffectsRecursively();
2465#endif // QT_CONFIG(graphicseffect)
2466 scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
2467 }
2468 }
2469
2470 // Certain properties are dropped as an item becomes invisible.
2471 bool hasFocus = q_ptr->hasFocus();
2472 if (!newVisible) {
2473 if (scene) {
2474 if (scene->d_func()->mouseGrabberItems.contains(q))
2475 q->ungrabMouse();
2476 if (scene->d_func()->keyboardGrabberItems.contains(q))
2477 q->ungrabKeyboard();
2478 if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
2479 scene->d_func()->leaveModal(q_ptr);
2480 }
2481 if (hasFocus && scene) {
2482 // Hiding the focus item or the closest non-panel ancestor of the focus item
2483 QGraphicsItem *focusItem = scene->focusItem();
2484 bool clear = true;
2485 if (isWidget && !focusItem->isPanel()) {
2486 do {
2487 if (focusItem == q_ptr) {
2488 clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
2489 break;
2490 }
2491 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
2492 }
2493 if (clear)
2494 clearFocusHelper(/* giveFocusToParent = */ false, hiddenByPanel);
2495 }
2496 if (q_ptr->isSelected())
2497 q_ptr->setSelected(false);
2498 } else {
2499 geometryChanged = 1;
2500 paintedViewBoundingRectsNeedRepaint = 1;
2501 if (scene) {
2502 if (isWidget) {
2503 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
2504 if (widget->windowType() == Qt::Popup)
2505 scene->d_func()->addPopup(widget);
2506 }
2507 if (q->isPanel() && panelModality != QGraphicsItem::NonModal) {
2508 scene->d_func()->enterModal(q_ptr);
2509 }
2510 }
2511 }
2512
2513 // Update children with explicitly = false.
2514 const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape
2515 || flags & QGraphicsItem::ItemContainsChildrenInShape)
2516 && !(flags & QGraphicsItem::ItemHasNoContents));
2517 foreach (QGraphicsItem *child, children) {
2518 if (!newVisible || !child->d_ptr->explicitlyHidden)
2519 child->d_ptr->setVisibleHelper(newVisible, false, updateChildren, hiddenByPanel);
2520 }
2521
2522 // Update activation
2523 if (scene && q->isPanel()) {
2524 if (newVisible) {
2525 if (parent && parent->isActive())
2526 q->setActive(true);
2527 } else {
2528 if (q->isActive())
2529 scene->setActivePanel(parent);
2530 }
2531 }
2532
2533 // Enable subfocus
2534 if (scene) {
2535 if (newVisible) {
2536 // Item is shown
2537 QGraphicsItem *p = parent;
2538 bool done = false;
2539 while (p) {
2540 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
2541 QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
2542 if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
2543 done = true;
2544 while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
2545 fsi = fsi->d_ptr->focusScopeItem;
2546 fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
2547 /* focusFromHide = */ false);
2548 }
2549 break;
2550 }
2551 p = p->d_ptr->parent;
2552 }
2553 if (!done) {
2554 QGraphicsItem *fi = subFocusItem;
2555 if (fi && fi != scene->focusItem()) {
2556 scene->setFocusItem(fi);
2557 } else if (flags & QGraphicsItem::ItemIsFocusScope &&
2558 !scene->focusItem() &&
2559 q->isAncestorOf(scene->d_func()->lastFocusItem)) {
2560 q_ptr->setFocus();
2561 }
2562 }
2563 } else {
2564 // Item is hidden
2565 if (hasFocus) {
2566 QGraphicsItem *p = parent;
2567 while (p) {
2568 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
2569 if (p->d_ptr->visible) {
2570 p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
2571 /* focusFromHide = */ true);
2572 }
2573 break;
2574 }
2575 p = p->d_ptr->parent;
2576 }
2577 }
2578 }
2579 }
2580
2581 // Deliver post-change notification.
2582 q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant);
2583
2584 if (isObject)
2585 emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged();
2586}
2587
2588/*!
2589 If \a visible is true, the item is made visible. Otherwise, the item is
2590 made invisible. Invisible items are not painted, nor do they receive any
2591 events. In particular, mouse events pass right through invisible items,
2592 and are delivered to any item that may be behind. Invisible items are also
2593 unselectable, they cannot take input focus, and are not detected by
2594 QGraphicsScene's item location functions.
2595
2596 If an item becomes invisible while grabbing the mouse, (i.e., while it is
2597 receiving mouse events,) it will automatically lose the mouse grab, and
2598 the grab is not regained by making the item visible again; it must receive
2599 a new mouse press to regain the mouse grab.
2600
2601 Similarly, an invisible item cannot have focus, so if the item has focus
2602 when it becomes invisible, it will lose focus, and the focus is not
2603 regained by simply making the item visible again.
2604
2605 If you hide a parent item, all its children will also be hidden. If you
2606 show a parent item, all children will be shown, unless they have been
2607 explicitly hidden (i.e., if you call setVisible(false) on a child, it will
2608 not be reshown even if its parent is hidden, and then shown again).
2609
2610 Items are visible by default; it is unnecessary to call
2611 setVisible() on a new item.
2612
2613 \note An item with opacity set to 0 will still be considered visible,
2614 although it will be treated like an invisible item: mouse events will pass
2615 through it, it will not be included in the items returned by
2616 QGraphicsView::items(), and so on. However, the item will retain the focus.
2617
2618 \sa isVisible(), show(), hide(), setOpacity()
2619*/
2620void QGraphicsItem::setVisible(bool visible)
2621{
2622 d_ptr->setVisibleHelper(visible,
2623 /* explicit = */ true,
2624 /* update = */ true,
2625 /* hiddenByPanel = */ isPanel());
2626}
2627
2628/*!
2629 \fn void QGraphicsItem::hide()
2630
2631 Hides the item (items are visible by default).
2632
2633 This convenience function is equivalent to calling \c setVisible(false).
2634
2635 \sa show(), setVisible()
2636*/
2637
2638/*!
2639 \fn void QGraphicsItem::show()
2640
2641 Shows the item (items are visible by default).
2642
2643 This convenience function is equivalent to calling \c setVisible(true).
2644
2645 \sa hide(), setVisible()
2646*/
2647
2648/*!
2649 Returns \c true if the item is enabled; otherwise, false is returned.
2650
2651 \sa setEnabled()
2652*/
2653bool QGraphicsItem::isEnabled() const
2654{
2655 return d_ptr->enabled;
2656}
2657
2658/*!
2659 \internal
2660
2661 Sets this item's visibility to \a newEnabled. If \a explicitly is true,
2662 this item will be "explicitly" \a newEnabled; otherwise, it.. will not be.
2663*/
2664void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bool update)
2665{
2666 // Update explicit bit.
2667 if (explicitly)
2668 explicitlyDisabled = newEnabled ? 0 : 1;
2669
2670 // Check if there's nothing to do.
2671 if (enabled == quint32(newEnabled))
2672 return;
2673
2674 // Certain properties are dropped when an item is disabled.
2675 if (!newEnabled) {
2676 if (scene && scene->mouseGrabberItem() == q_ptr)
2677 q_ptr->ungrabMouse();
2678 if (q_ptr->hasFocus()) {
2679 // Disabling the closest non-panel ancestor of the focus item
2680 // causes focus to pop to the next item, otherwise it's cleared.
2681 QGraphicsItem *focusItem = scene->focusItem();
2682 bool clear = true;
2683 if (isWidget && !focusItem->isPanel() && q_ptr->isAncestorOf(focusItem)) {
2684 do {
2685 if (focusItem == q_ptr) {
2686 clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
2687 break;
2688 }
2689 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
2690 }
2691 if (clear)
2692 q_ptr->clearFocus();
2693 }
2694 if (q_ptr->isSelected())
2695 q_ptr->setSelected(false);
2696 }
2697
2698 // Modify the property.
2699 const QVariant newEnabledVariant(q_ptr->itemChange(QGraphicsItem::ItemEnabledChange,
2700 quint32(newEnabled)));
2701 enabled = newEnabledVariant.toBool();
2702
2703 // Schedule redraw.
2704 if (update)
2705 q_ptr->update();
2706
2707 foreach (QGraphicsItem *child, children) {
2708 if (!newEnabled || !child->d_ptr->explicitlyDisabled)
2709 child->d_ptr->setEnabledHelper(newEnabled, /* explicitly = */ false);
2710 }
2711
2712 // Deliver post-change notification.
2713 q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant);
2714
2715 if (isObject)
2716 emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged();
2717}
2718
2719/*!
2720 If \a enabled is true, the item is enabled; otherwise, it is disabled.
2721
2722 Disabled items are visible, but they do not receive any events, and cannot
2723 take focus nor be selected. Mouse events are discarded; they are not
2724 propagated unless the item is also invisible, or if it does not accept
2725 mouse events (see acceptedMouseButtons()). A disabled item cannot become the
2726 mouse grabber, and as a result of this, an item loses the grab if it
2727 becomes disabled when grabbing the mouse, just like it loses focus if it
2728 had focus when it was disabled.
2729
2730 Disabled items are traditionally drawn using grayed-out colors (see \l
2731 QPalette::Disabled).
2732
2733 If you disable a parent item, all its children will also be disabled. If
2734 you enable a parent item, all children will be enabled, unless they have
2735 been explicitly disabled (i.e., if you call setEnabled(false) on a child,
2736 it will not be reenabled if its parent is disabled, and then enabled
2737 again).
2738
2739 Items are enabled by default.
2740
2741 \note If you install an event filter, you can still intercept events
2742 before they are delivered to items; this mechanism disregards the item's
2743 enabled state.
2744
2745 \sa isEnabled()
2746*/
2747void QGraphicsItem::setEnabled(bool enabled)
2748{
2749 d_ptr->setEnabledHelper(enabled, /* explicitly = */ true);
2750}
2751
2752/*!
2753 Returns \c true if this item is selected; otherwise, false is returned.
2754
2755 Items that are in a group inherit the group's selected state.
2756
2757 Items are not selected by default.
2758
2759 \sa setSelected(), QGraphicsScene::setSelectionArea()
2760*/
2761bool QGraphicsItem::isSelected() const
2762{
2763 if (QGraphicsItemGroup *group = this->group())
2764 return group->isSelected();
2765 return d_ptr->selected;
2766}
2767
2768/*!
2769 If \a selected is true and this item is selectable, this item is selected;
2770 otherwise, it is unselected.
2771
2772 If the item is in a group, the whole group's selected state is toggled by
2773 this function. If the group is selected, all items in the group are also
2774 selected, and if the group is not selected, no item in the group is
2775 selected.
2776
2777 Only visible, enabled, selectable items can be selected. If \a selected
2778 is true and this item is either invisible or disabled or unselectable,
2779 this function does nothing.
2780
2781 By default, items cannot be selected. To enable selection, set the
2782 ItemIsSelectable flag.
2783
2784 This function is provided for convenience, allowing individual toggling of
2785 the selected state of an item. However, a more common way of selecting
2786 items is to call QGraphicsScene::setSelectionArea(), which will call this
2787 function for all visible, enabled, and selectable items within a specified
2788 area on the scene.
2789
2790 \sa isSelected(), QGraphicsScene::selectedItems()
2791*/
2792void QGraphicsItem::setSelected(bool selected)
2793{
2794 if (QGraphicsItemGroup *group = this->group()) {
2795 group->setSelected(selected);
2796 return;
2797 }
2798
2799 if (!(d_ptr->flags & ItemIsSelectable) || !d_ptr->enabled || !d_ptr->visible)
2800 selected = false;
2801 if (d_ptr->selected == selected)
2802 return;
2803 const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected)));
2804 bool newSelected = newSelectedVariant.toBool();
2805 if (d_ptr->selected == newSelected)
2806 return;
2807 d_ptr->selected = newSelected;
2808
2809 update();
2810 if (d_ptr->scene) {
2811 QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
2812 if (selected) {
2813 sceneD->selectedItems << this;
2814 } else {
2815 // QGraphicsScene::selectedItems() lazily pulls out all items that are
2816 // no longer selected.
2817 }
2818 if (!sceneD->selectionChanging)
2819 emit d_ptr->scene->selectionChanged();
2820 }
2821
2822 // Deliver post-change notification.
2823 itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant);
2824}
2825
2826/*!
2827 \since 4.5
2828
2829 Returns this item's local opacity, which is between 0.0 (transparent) and
2830 1.0 (opaque). This value is combined with parent and ancestor values into
2831 the effectiveOpacity(). The effective opacity decides how the item is
2832 rendered and also affects its visibility when queried by functions such as
2833 QGraphicsView::items().
2834
2835 The opacity property decides the state of the painter passed to the
2836 paint() function. If the item is cached, i.e., ItemCoordinateCache or
2837 DeviceCoordinateCache, the effective property will be applied to the item's
2838 cache as it is rendered.
2839
2840 The default opacity is 1.0; fully opaque.
2841
2842 \sa setOpacity(), paint(), ItemIgnoresParentOpacity,
2843 ItemDoesntPropagateOpacityToChildren
2844*/
2845qreal QGraphicsItem::opacity() const
2846{
2847 return d_ptr->opacity;
2848}
2849
2850/*!
2851 \since 4.5
2852
2853 Returns this item's \e effective opacity, which is between 0.0
2854 (transparent) and 1.0 (opaque). This value is a combination of this item's
2855 local opacity, and its parent and ancestors' opacities. The effective
2856 opacity decides how the item is rendered.
2857
2858 \sa opacity(), setOpacity(), paint(), ItemIgnoresParentOpacity,
2859 ItemDoesntPropagateOpacityToChildren
2860*/
2861qreal QGraphicsItem::effectiveOpacity() const
2862{
2863 return d_ptr->effectiveOpacity();
2864}
2865
2866/*!
2867 \since 4.5
2868
2869 Sets this item's local \a opacity, between 0.0 (transparent) and 1.0
2870 (opaque). The item's local opacity is combined with parent and ancestor
2871 opacities into the effectiveOpacity().
2872
2873 By default, opacity propagates from parent to child, so if a parent's
2874 opacity is 0.5 and the child is also 0.5, the child's effective opacity
2875 will be 0.25.
2876
2877 The opacity property decides the state of the painter passed to the
2878 paint() function. If the item is cached, i.e., ItemCoordinateCache or
2879 DeviceCoordinateCache, the effective property will be applied to the
2880 item's cache as it is rendered.
2881
2882 There are two item flags that affect how the item's opacity is combined
2883 with the parent: ItemIgnoresParentOpacity and
2884 ItemDoesntPropagateOpacityToChildren.
2885
2886 \note Setting the opacity of an item to 0 will not make the item invisible
2887 (according to isVisible()), but the item will be treated like an invisible
2888 one. See the documentation of setVisible() for more information.
2889
2890 \sa opacity(), effectiveOpacity(), setVisible()
2891*/
2892void QGraphicsItem::setOpacity(qreal opacity)
2893{
2894 // Notify change.
2895 const QVariant newOpacityVariant(itemChange(ItemOpacityChange, opacity));
2896
2897 // Normalized opacity
2898 qreal newOpacity = qBound(qreal(0), newOpacityVariant.toReal(), qreal(1));
2899
2900 // No change? Done.
2901 if (newOpacity == d_ptr->opacity)
2902 return;
2903
2904 bool wasFullyTransparent = d_ptr->isOpacityNull();
2905 d_ptr->opacity = newOpacity;
2906
2907 // Notify change.
2908 itemChange(ItemOpacityHasChanged, newOpacityVariant);
2909
2910 // Update.
2911 if (d_ptr->scene) {
2912#if QT_CONFIG(graphicseffect)
2913 d_ptr->invalidateParentGraphicsEffectsRecursively();
2914 if (!(d_ptr->flags & ItemDoesntPropagateOpacityToChildren))
2915 d_ptr->invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::OpacityChanged);
2916#endif // QT_CONFIG(graphicseffect)
2917 d_ptr->scene->d_func()->markDirty(this, QRectF(),
2918 /*invalidateChildren=*/true,
2919 /*force=*/false,
2920 /*ignoreOpacity=*/d_ptr->isOpacityNull());
2921 if (wasFullyTransparent)
2922 d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
2923 }
2924
2925 if (d_ptr->isObject)
2926 emit static_cast<QGraphicsObject *>(this)->opacityChanged();
2927}
2928
2929/*!
2930 Returns a pointer to this item's effect if it has one; otherwise \nullptr.
2931
2932 \since 4.6
2933*/
2934#if QT_CONFIG(graphicseffect)
2935QGraphicsEffect *QGraphicsItem::graphicsEffect() const
2936{
2937 return d_ptr->graphicsEffect;
2938}
2939
2940/*!
2941 Sets \a effect as the item's effect. If there already is an effect installed
2942 on this item, QGraphicsItem will delete the existing effect before installing
2943 the new \a effect. You can delete an existing effect by calling
2944 setGraphicsEffect(\nullptr).
2945
2946 If \a effect is the installed effect on a different item, setGraphicsEffect() will remove
2947 the effect from the item and install it on this item.
2948
2949 QGraphicsItem takes ownership of \a effect.
2950
2951 \note This function will apply the effect on itself and all its children.
2952
2953 \since 4.6
2954*/
2955void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
2956{
2957 if (d_ptr->graphicsEffect == effect)
2958 return;
2959
2960 if (d_ptr->graphicsEffect) {
2961 delete d_ptr->graphicsEffect;
2962 d_ptr->graphicsEffect = 0;
2963 } else if (d_ptr->parent) {
2964 d_ptr->parent->d_ptr->updateChildWithGraphicsEffectFlagRecursively();
2965 }
2966
2967 if (effect) {
2968 // Set new effect.
2969 QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
2970 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
2971 d_ptr->graphicsEffect = effect;
2972 effect->d_func()->setGraphicsEffectSource(source);
2973 prepareGeometryChange();
2974 }
2975}
2976#endif // QT_CONFIG(graphicseffect)
2977
2978void QGraphicsItemPrivate::updateChildWithGraphicsEffectFlagRecursively()
2979{
2980#if QT_CONFIG(graphicseffect)
2981 QGraphicsItemPrivate *itemPrivate = this;
2982 do {
2983 // parent chain already notified?
2984 if (itemPrivate->mayHaveChildWithGraphicsEffect)
2985 return;
2986 itemPrivate->mayHaveChildWithGraphicsEffect = 1;
2987 } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
2988#endif
2989}
2990
2991/*!
2992 \internal
2993 \since 4.6
2994 Returns the effective bounding rect of the given item space rect.
2995 If the item has no effect, the rect is returned unmodified.
2996 If the item has an effect, the effective rect can be extend beyond the
2997 item's bounding rect, depending on the effect.
2998
2999 \sa boundingRect()
3000*/
3001QRectF QGraphicsItemPrivate::effectiveBoundingRect(const QRectF &rect) const
3002{
3003#if QT_CONFIG(graphicseffect)
3004 Q_Q(const QGraphicsItem);
3005 QGraphicsEffect *effect = graphicsEffect;
3006 if (scene && effect && effect->isEnabled()) {
3007 if (scene->d_func()->views.isEmpty())
3008 return effect->boundingRectFor(rect);
3009 QRectF sceneRect = q->mapRectToScene(rect);
3010 QRectF sceneEffectRect;
3011 const auto views = scene->views();
3012 for (QGraphicsView *view : views) {
3013 QRectF deviceRect = view->d_func()->mapRectFromScene(sceneRect);
3014 QRect deviceEffectRect = effect->boundingRectFor(deviceRect).toAlignedRect();
3015 sceneEffectRect |= view->d_func()->mapRectToScene(deviceEffectRect);
3016 }
3017 return q->mapRectFromScene(sceneEffectRect);
3018 }
3019#endif // QT_CONFIG(graphicseffect)
3020 return rect;
3021}
3022
3023/*!
3024 \internal
3025 \since 4.6
3026 Returns the effective bounding rect of the item.
3027 If the item has no effect, this is the same as the item's bounding rect.
3028 If the item has an effect, the effective rect can be larger than the item's
3029 bouding rect, depending on the effect.
3030
3031 \sa boundingRect()
3032*/
3033QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectItem) const
3034{
3035#if QT_CONFIG(graphicseffect)
3036 Q_Q(const QGraphicsItem);
3037 QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
3038 if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
3039 || ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
3040 || topMostEffectItem == q)
3041 return brect;
3042
3043 const QGraphicsItem *effectParent = parent;
3044 while (effectParent) {
3045 QGraphicsEffect *effect = effectParent->d_ptr->graphicsEffect;
3046 if (scene && effect && effect->isEnabled()) {
3047 const QRectF brectInParentSpace = q->mapRectToItem(effectParent, brect);
3048 const QRectF effectRectInParentSpace = effectParent->d_ptr->effectiveBoundingRect(brectInParentSpace);
3049 brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
3050 }
3051 if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
3052 || effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
3053 || topMostEffectItem == effectParent) {
3054 return brect;
3055 }
3056 effectParent = effectParent->d_ptr->parent;
3057 }
3058
3059 return brect;
3060#else //QT_CONFIG(graphicseffect)
3061 Q_UNUSED(topMostEffectItem);
3062 return q_ptr->boundingRect();
3063#endif // QT_CONFIG(graphicseffect)
3064
3065}
3066
3067/*!
3068 \internal
3069 \since 4.6
3070 Returns the effective bounding rect of this item in scene coordinates,
3071 by combining sceneTransform() with boundingRect(), taking into account
3072 the effect that the item might have.
3073
3074 If the item has no effect, this is the same as sceneBoundingRect().
3075
3076 \sa effectiveBoundingRect(), sceneBoundingRect()
3077*/
3078QRectF QGraphicsItemPrivate::sceneEffectiveBoundingRect() const
3079{
3080 // Find translate-only offset
3081 // COMBINE
3082 QPointF offset;
3083 const QGraphicsItem *parentItem = q_ptr;
3084 const QGraphicsItemPrivate *itemd;
3085 do {
3086 itemd = parentItem->d_ptr.data();
3087 if (itemd->transformData)
3088 break;
3089 offset += itemd->pos;
3090 } while ((parentItem = itemd->parent));
3091
3092 QRectF br = effectiveBoundingRect();
3093 br.translate(offset);
3094 return !parentItem ? br : parentItem->sceneTransform().mapRect(br);
3095}
3096
3097/*!
3098 Returns \c true if this item can accept drag and drop events; otherwise,
3099 returns \c false. By default, items do not accept drag and drop events; items
3100 are transparent to drag and drop.
3101
3102 \sa setAcceptDrops()
3103*/
3104bool QGraphicsItem::acceptDrops() const
3105{
3106 return d_ptr->acceptDrops;
3107}
3108
3109/*!
3110 If \a on is true, this item will accept drag and drop events; otherwise,
3111 it is transparent for drag and drop events. By default, items do not
3112 accept drag and drop events.
3113
3114 \sa acceptDrops()
3115*/
3116void QGraphicsItem::setAcceptDrops(bool on)
3117{
3118 d_ptr->acceptDrops = on;
3119}
3120
3121/*!
3122 Returns the mouse buttons that this item accepts mouse events for. By
3123 default, all mouse buttons are accepted.
3124
3125 If an item accepts a mouse button, it will become the mouse
3126 grabber item when a mouse press event is delivered for that mouse
3127 button. However, if the item does not accept the button,
3128 QGraphicsScene will forward the mouse events to the first item
3129 beneath it that does.
3130
3131 \sa setAcceptedMouseButtons(), mousePressEvent()
3132*/
3133Qt::MouseButtons QGraphicsItem::acceptedMouseButtons() const
3134{
3135 return Qt::MouseButtons(d_ptr->acceptedMouseButtons);
3136}
3137
3138/*!
3139 Sets the mouse \a buttons that this item accepts mouse events for.
3140
3141 By default, all mouse buttons are accepted. If an item accepts a
3142 mouse button, it will become the mouse grabber item when a mouse
3143 press event is delivered for that button. However, if the item
3144 does not accept the mouse button, QGraphicsScene will forward the
3145 mouse events to the first item beneath it that does.
3146
3147 To disable mouse events for an item (i.e., make it transparent for mouse
3148 events), call setAcceptedMouseButtons(0).
3149
3150 \sa acceptedMouseButtons(), mousePressEvent()
3151*/
3152void QGraphicsItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
3153{
3154 if (Qt::MouseButtons(d_ptr->acceptedMouseButtons) != buttons) {
3155 if (buttons == 0 && d_ptr->scene && d_ptr->scene->mouseGrabberItem() == this
3156 && d_ptr->scene->d_func()->lastMouseGrabberItemHasImplicitMouseGrab) {
3157 ungrabMouse();
3158 }
3159 d_ptr->acceptedMouseButtons = quint32(buttons);
3160 }
3161}
3162
3163/*!
3164 \since 4.4
3165
3166 Returns \c true if an item accepts hover events
3167 (QGraphicsSceneHoverEvent); otherwise, returns \c false. By default,
3168 items do not accept hover events.
3169
3170 \sa setAcceptedMouseButtons()
3171*/
3172bool QGraphicsItem::acceptHoverEvents() const
3173{
3174 return d_ptr->acceptsHover;
3175}
3176
3177/*!
3178 \fn bool QGraphicsItem::acceptsHoverEvents() const
3179 \obsolete
3180
3181 Call acceptHoverEvents() instead.
3182*/
3183
3184/*!
3185 \since 4.4
3186
3187 If \a enabled is true, this item will accept hover events;
3188 otherwise, it will ignore them. By default, items do not accept
3189 hover events.
3190
3191 Hover events are delivered when there is no current mouse grabber
3192 item. They are sent when the mouse cursor enters an item, when it
3193 moves around inside the item, and when the cursor leaves an
3194 item. Hover events are commonly used to highlight an item when
3195 it's entered, and for tracking the mouse cursor as it hovers over
3196 the item (equivalent to QWidget::mouseTracking).
3197
3198 Parent items receive hover enter events before their children, and
3199 leave events after their children. The parent does not receive a
3200 hover leave event if the cursor enters a child, though; the parent
3201 stays "hovered" until the cursor leaves its area, including its
3202 children's areas.
3203
3204 If a parent item handles child events, it will receive hover move,
3205 drag move, and drop events as the cursor passes through its
3206 children, but it does not receive hover enter and hover leave, nor
3207 drag enter and drag leave events on behalf of its children.
3208
3209 A QGraphicsWidget with window decorations will accept hover events
3210 regardless of the value of acceptHoverEvents().
3211
3212 \sa acceptHoverEvents(), hoverEnterEvent(), hoverMoveEvent(),
3213 hoverLeaveEvent()
3214*/
3215void QGraphicsItem::setAcceptHoverEvents(bool enabled)
3216{
3217 if (d_ptr->acceptsHover == quint32(enabled))
3218 return;
3219 d_ptr->acceptsHover = quint32(enabled);
3220 if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) {
3221 d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false;
3222 d_ptr->scene->d_func()->enableMouseTrackingOnViews();
3223 }
3224}
3225
3226/*!
3227 \fn void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
3228 \obsolete
3229
3230 Use setAcceptHoverEvents(\a enabled) instead.
3231*/
3232
3233/*! \since 4.6
3234
3235 Returns \c true if an item accepts \l{QTouchEvent}{touch events};
3236 otherwise, returns \c false. By default, items do not accept touch events.
3237
3238 \sa setAcceptTouchEvents()
3239*/
3240bool QGraphicsItem::acceptTouchEvents() const
3241{
3242 return d_ptr->acceptTouchEvents;
3243}
3244
3245/*!
3246 \since 4.6
3247
3248 If \a enabled is true, this item will accept \l{QTouchEvent}{touch events};
3249 otherwise, it will ignore them. By default, items do not accept
3250 touch events.
3251*/
3252void QGraphicsItem::setAcceptTouchEvents(bool enabled)
3253{
3254 if (d_ptr->acceptTouchEvents == quint32(enabled))
3255 return;
3256 d_ptr->acceptTouchEvents = quint32(enabled);
3257 if (d_ptr->acceptTouchEvents && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreTouchEvents) {
3258 d_ptr->scene->d_func()->allItemsIgnoreTouchEvents = false;
3259 d_ptr->scene->d_func()->enableTouchEventsOnViews();
3260 }
3261}
3262
3263/*!
3264 \since 4.6
3265
3266 Returns \c true if this item filters child events (i.e., all events
3267 intended for any of its children are instead sent to this item);
3268 otherwise, false is returned.
3269
3270 The default value is false; child events are not filtered.
3271
3272 \sa setFiltersChildEvents()
3273*/
3274bool QGraphicsItem::filtersChildEvents() const
3275{
3276 return d_ptr->filtersDescendantEvents;
3277}
3278
3279/*!
3280 \since 4.6
3281
3282 If \a enabled is true, this item is set to filter all events for
3283 all its children (i.e., all events intented for any of its
3284 children are instead sent to this item); otherwise, if \a enabled
3285 is false, this item will only handle its own events. The default
3286 value is false.
3287
3288 \sa filtersChildEvents()
3289*/
3290void QGraphicsItem::setFiltersChildEvents(bool enabled)
3291{
3292 if (d_ptr->filtersDescendantEvents == enabled)
3293 return;
3294
3295 d_ptr->filtersDescendantEvents = enabled;
3296 d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
3297}
3298
3299/*!
3300 \obsolete
3301
3302 Returns \c true if this item handles child events (i.e., all events
3303 intended for any of its children are instead sent to this item);
3304 otherwise, false is returned.
3305
3306 This property is useful for item groups; it allows one item to
3307 handle events on behalf of its children, as opposed to its
3308 children handling their events individually.
3309
3310 The default is to return false; children handle their own events.
3311 The exception for this is if the item is a QGraphicsItemGroup, then
3312 it defaults to return true.
3313
3314 \sa setHandlesChildEvents()
3315*/
3316bool QGraphicsItem::handlesChildEvents() const
3317{
3318 return d_ptr->handlesChildEvents;
3319}
3320
3321/*!
3322 \obsolete
3323
3324 If \a enabled is true, this item is set to handle all events for
3325 all its children (i.e., all events intented for any of its
3326 children are instead sent to this item); otherwise, if \a enabled
3327 is false, this item will only handle its own events. The default
3328 value is false.
3329
3330 This property is useful for item groups; it allows one item to
3331 handle events on behalf of its children, as opposed to its
3332 children handling their events individually.
3333
3334 If a child item accepts hover events, its parent will receive
3335 hover move events as the cursor passes through the child, but it
3336 does not receive hover enter and hover leave events on behalf of
3337 its child.
3338
3339 \sa handlesChildEvents()
3340*/
3341void QGraphicsItem::setHandlesChildEvents(bool enabled)
3342{
3343 if (d_ptr->handlesChildEvents == enabled)
3344 return;
3345
3346 d_ptr->handlesChildEvents = enabled;
3347 d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
3348}
3349/*!
3350 \since 4.6
3351 Returns \c true if this item is active; otherwise returns \c false.
3352
3353 An item can only be active if the scene is active. An item is active
3354 if it is, or is a descendent of, an active panel. Items in non-active
3355 panels are not active.
3356
3357 Items that are not part of a panel follow scene activation when the
3358 scene has no active panel.
3359
3360 Only active items can gain input focus.
3361
3362 \sa QGraphicsScene::isActive(), QGraphicsScene::activePanel(), panel(), isPanel()
3363*/
3364bool QGraphicsItem::isActive() const
3365{
3366 if (!d_ptr->scene || !d_ptr->scene->isActive())
3367 return false;
3368 return panel() == d_ptr->scene->activePanel();
3369}
3370
3371/*!
3372 \since 4.6
3373
3374 If \a active is true, and the scene is active, this item's panel will be
3375 activated. Otherwise, the panel is deactivated.
3376
3377 If the item is not part of an active scene, \a active will decide what
3378 happens to the panel when the scene becomes active or the item is added to
3379 the scene. If true, the item's panel will be activated when the item is
3380 either added to the scene or the scene is activated. Otherwise, the item
3381 will stay inactive independent of the scene's activated state.
3382
3383 \sa isPanel(), QGraphicsScene::setActivePanel(), QGraphicsScene::isActive()
3384*/
3385void QGraphicsItem::setActive(bool active)
3386{
3387 d_ptr->explicitActivate = 1;
3388 d_ptr->wantsActive = active;
3389 if (d_ptr->scene) {
3390 if (active) {
3391 // Activate this item.
3392 d_ptr->scene->setActivePanel(this);
3393 } else {
3394 QGraphicsItem *activePanel = d_ptr->scene->activePanel();
3395 QGraphicsItem *thisPanel = panel();
3396 if (!activePanel || activePanel == thisPanel) {
3397 // Deactivate this item, and reactivate the parent panel,
3398 // or the last active panel (if any).
3399 QGraphicsItem *nextToActivate = 0;
3400 if (d_ptr->parent)
3401 nextToActivate = d_ptr->parent->panel();
3402 if (!nextToActivate)
3403 nextToActivate = d_ptr->scene->d_func()->lastActivePanel;
3404 if (nextToActivate == this || isAncestorOf(nextToActivate))
3405 nextToActivate = 0;
3406 d_ptr->scene->setActivePanel(nextToActivate);
3407 }
3408 }
3409 }
3410}
3411
3412/*!
3413 Returns \c true if this item is active, and it or its \l{focusProxy()}{focus
3414 proxy} has keyboard input focus; otherwise, returns \c false.
3415
3416 \sa focusItem(), setFocus(), QGraphicsScene::setFocusItem(), isActive()
3417*/
3418bool QGraphicsItem::hasFocus() const
3419{
3420 if (!d_ptr->scene || !d_ptr->scene->isActive())
3421 return false;
3422
3423 if (d_ptr->focusProxy)
3424 return d_ptr->focusProxy->hasFocus();
3425
3426 if (d_ptr->scene->d_func()->focusItem != this)
3427 return false;
3428
3429 return panel() == d_ptr->scene->d_func()->activePanel;
3430}
3431
3432/*!
3433 Gives keyboard input focus to this item. The \a focusReason argument will
3434 be passed into any \l{QFocusEvent}{focus event} generated by this function;
3435 it is used to give an explanation of what caused the item to get focus.
3436
3437 Only enabled items that set the ItemIsFocusable flag can accept keyboard
3438 focus.
3439
3440 If this item is not visible, not active, or not associated with a scene,
3441 it will not gain immediate input focus. However, it will be registered as
3442 the preferred focus item for its subtree of items, should it later become
3443 visible.
3444
3445 As a result of calling this function, this item will receive a
3446 \l{focusInEvent()}{focus in event} with \a focusReason. If another item
3447 already has focus, that item will first receive a \l{focusOutEvent()}
3448 {focus out event} indicating that it has lost input focus.
3449
3450 \sa clearFocus(), hasFocus(), focusItem(), focusProxy()
3451*/
3452void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
3453{
3454 d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromHide = */ false);
3455}
3456
3457/*!
3458 \internal
3459*/
3460void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide)
3461{
3462 // Disabled / unfocusable items cannot accept focus.
3463 if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable))
3464 return;
3465
3466 // Find focus proxy.
3467 QGraphicsItem *f = q_ptr;
3468 while (f->d_ptr->focusProxy)
3469 f = f->d_ptr->focusProxy;
3470
3471 // Return if it already has focus.
3472 if (scene && scene->focusItem() == f)
3473 return;
3474
3475 // Update focus scope item ptr.
3476 QGraphicsItem *p = parent;
3477 while (p) {
3478 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
3479 QGraphicsItem *oldFocusScopeItem = p->d_ptr->focusScopeItem;
3480 p->d_ptr->focusScopeItem = q_ptr;
3481 if (oldFocusScopeItem)
3482 oldFocusScopeItem->d_ptr->focusScopeItemChange(false);
3483 focusScopeItemChange(true);
3484 if (!p->focusItem() && !focusFromHide) {
3485 // Calling setFocus() on a child of a focus scope that does
3486 // not have focus changes only the focus scope pointer,
3487 // so that focus is restored the next time the scope gains
3488 // focus.
3489 return;
3490 }
3491 break;
3492 }
3493 p = p->d_ptr->parent;
3494 }
3495
3496 if (climb) {
3497 while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible())
3498 f = f->d_ptr->focusScopeItem;
3499 }
3500
3501 // Update the child focus chain.
3502 QGraphicsItem *commonAncestor = 0;
3503 if (scene && scene->focusItem() && scene->focusItem()->panel() == q_ptr->panel()) {
3504 commonAncestor = scene->focusItem()->commonAncestorItem(f);
3505 scene->focusItem()->d_ptr->clearSubFocus(scene->focusItem(), commonAncestor);
3506 }
3507
3508 f->d_ptr->setSubFocus(f, commonAncestor);
3509
3510 // Update the scene's focus item.
3511 if (scene) {
3512 QGraphicsItem *p = q_ptr->panel();
3513 if ((!p && scene->isActive()) || (p && p->isActive())) {
3514 // Visible items immediately gain focus from scene.
3515 scene->d_func()->setFocusItemHelper(f, focusReason);
3516 }
3517 }
3518}
3519
3520/*!
3521 Takes keyboard input focus from the item.
3522
3523 If it has focus, a \l{focusOutEvent()}{focus out event} is sent to this
3524 item to tell it that it is about to lose the focus.
3525
3526 Only items that set the ItemIsFocusable flag, or widgets that set an
3527 appropriate focus policy, can accept keyboard focus.
3528
3529 \sa setFocus(), hasFocus(), QGraphicsWidget::focusPolicy
3530*/
3531void QGraphicsItem::clearFocus()
3532{
3533 d_ptr->clearFocusHelper(/* giveFocusToParent = */ true,
3534 /* hiddenByParentPanel = */ false);
3535}
3536
3537/*!
3538 \internal
3539*/
3540void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent, bool hiddenByParentPanel)
3541{
3542 QGraphicsItem *subFocusItem = q_ptr;
3543 if (flags & QGraphicsItem::ItemIsFocusScope) {
3544 while (subFocusItem->d_ptr->focusScopeItem)
3545 subFocusItem = subFocusItem->d_ptr->focusScopeItem;
3546 }
3547
3548 if (giveFocusToParent) {
3549 // Pass focus to the closest parent focus scope
3550 if (!inDestructor) {
3551 QGraphicsItem *p = parent;
3552 while (p) {
3553 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
3554 if (p->d_ptr->focusScopeItem == q_ptr) {
3555 p->d_ptr->focusScopeItem = 0;
3556 if (!subFocusItem->hasFocus()) //if it has focus, focusScopeItemChange is called elsewhere
3557 focusScopeItemChange(false);
3558 }
3559 if (subFocusItem->hasFocus())
3560 p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
3561 /* focusFromHide = */ false);
3562 return;
3563 }
3564 p = p->d_ptr->parent;
3565 }
3566 }
3567 }
3568
3569 if (subFocusItem->hasFocus()) {
3570 // Invisible items with focus must explicitly clear subfocus.
3571 if (!hiddenByParentPanel)
3572 clearSubFocus(q_ptr);
3573
3574 // If this item has the scene's input focus, clear it.
3575 scene->setFocusItem(0);
3576 }
3577}
3578
3579/*!
3580 \since 4.6
3581
3582 Returns this item's focus proxy, or \nullptr if this item has no
3583 focus proxy.
3584
3585 \sa setFocusProxy(), setFocus(), hasFocus()
3586*/
3587QGraphicsItem *QGraphicsItem::focusProxy() const
3588{
3589 return d_ptr->focusProxy;
3590}
3591
3592/*!
3593 \since 4.6
3594
3595 Sets the item's focus proxy to \a item.
3596
3597 If an item has a focus proxy, the focus proxy will receive
3598 input focus when the item gains input focus. The item itself
3599 will still have focus (i.e., hasFocus() will return true),
3600 but only the focus proxy will receive the keyboard input.
3601
3602 A focus proxy can itself have a focus proxy, and so on. In
3603 such case, keyboard input will be handled by the outermost
3604 focus proxy.
3605
3606 The focus proxy \a item must belong to the same scene as
3607 this item.
3608
3609 \sa focusProxy(), setFocus(), hasFocus()
3610*/
3611void QGraphicsItem::setFocusProxy(QGraphicsItem *item)
3612{
3613 if (item == d_ptr->focusProxy)
3614 return;
3615 if (item == this) {
3616 qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
3617 return;
3618 }
3619 if (item) {
3620 if (item->d_ptr->scene != d_ptr->scene) {
3621 qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
3622 return;
3623 }
3624 for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) {
3625 if (f == this) {
3626 qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item);
3627 return;
3628 }
3629 }
3630 }
3631
3632 QGraphicsItem *lastFocusProxy = d_ptr->focusProxy;
3633 if (lastFocusProxy)
3634 lastFocusProxy->d_ptr->focusProxyRefs.removeOne(&d_ptr->focusProxy);
3635 d_ptr->focusProxy = item;
3636 if (item)
3637 item->d_ptr->focusProxyRefs << &d_ptr->focusProxy;
3638}
3639
3640/*!
3641 \since 4.6
3642
3643 If this item, a child or descendant of this item currently has input
3644 focus, this function will return a pointer to that item. If
3645 no descendant has input focus, \nullptr is returned.
3646
3647 \sa hasFocus(), setFocus(), QWidget::focusWidget()
3648*/
3649QGraphicsItem *QGraphicsItem::focusItem() const
3650{
3651 return d_ptr->subFocusItem;
3652}
3653
3654/*!
3655 \internal
3656
3657 Returns this item's focus scope item.
3658*/
3659QGraphicsItem *QGraphicsItem::focusScopeItem() const
3660{
3661 return d_ptr->focusScopeItem;
3662}
3663
3664/*!
3665 \since 4.4
3666 Grabs the mouse input.
3667
3668 This item will receive all mouse events for the scene until any of the
3669