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

source code of qtbase/src/widgets/graphicsview/qgraphicsitem.cpp