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