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