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