Changeset 561 for trunk/src/gui/graphicsview
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 37 edited
- 16 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/graphicsview/graphicsview.pri
r2 r561 1 1 # Qt graphicsview module 2 HEADERS += graphicsview/qgraphicsgridlayout.h \ 3 graphicsview/qgraphicsitem.h \ 4 graphicsview/qgraphicsitem_p.h \ 5 graphicsview/qgraphicsitemanimation.h \ 6 graphicsview/qgraphicslayout.h \ 7 graphicsview/qgraphicslayout_p.h \ 8 graphicsview/qgraphicslayoutitem.h \ 9 graphicsview/qgraphicslayoutitem_p.h \ 10 graphicsview/qgraphicslinearlayout.h \ 11 graphicsview/qgraphicsproxywidget.h \ 12 graphicsview/qgraphicsscene.h \ 13 graphicsview/qgraphicsscene_bsp_p.h \ 14 graphicsview/qgraphicsscene_p.h \ 15 graphicsview/qgraphicsscenebsptreeindex_p.h \ 16 graphicsview/qgraphicssceneevent.h \ 17 graphicsview/qgraphicssceneindex_p.h \ 18 graphicsview/qgraphicsscenelinearindex_p.h \ 19 graphicsview/qgraphicstransform.h \ 20 graphicsview/qgraphicstransform_p.h \ 21 graphicsview/qgraphicsview.h \ 22 graphicsview/qgraphicsview_p.h \ 23 graphicsview/qgraphicswidget.h \ 24 graphicsview/qgraphicswidget_p.h \ 25 graphicsview/qgridlayoutengine_p.h \ 26 graphicsview/qgraph_p.h \ 27 graphicsview/qsimplex_p.h \ 28 graphicsview/qgraphicsanchorlayout_p.h \ 29 graphicsview/qgraphicsanchorlayout.h 2 30 3 HEADERS += \ 4 graphicsview/qgraphicsitem.h \ 5 graphicsview/qgraphicsitem_p.h \ 6 graphicsview/qgraphicsitemanimation.h \ 7 graphicsview/qgraphicsscene.h \ 8 graphicsview/qgraphicsscene_p.h \ 9 graphicsview/qgraphicsscene_bsp_p.h \ 10 graphicsview/qgraphicssceneevent.h \ 11 graphicsview/qgraphicsview_p.h \ 12 graphicsview/qgraphicsview.h 13 14 SOURCES += \ 15 graphicsview/qgraphicsitem.cpp \ 16 graphicsview/qgraphicsitemanimation.cpp \ 17 graphicsview/qgraphicsscene.cpp \ 18 graphicsview/qgraphicsscene_bsp.cpp \ 19 graphicsview/qgraphicssceneevent.cpp \ 20 graphicsview/qgraphicsview.cpp 21 22 # Widgets on the canvas 23 24 HEADERS += \ 25 graphicsview/qgraphicslayout.h \ 26 graphicsview/qgraphicslayout_p.h \ 27 graphicsview/qgraphicslayoutitem.h \ 28 graphicsview/qgraphicslayoutitem_p.h \ 29 graphicsview/qgraphicslinearlayout.h \ 30 graphicsview/qgraphicswidget.h \ 31 graphicsview/qgraphicswidget_p.h \ 32 graphicsview/qgridlayoutengine_p.h \ 33 graphicsview/qgraphicsproxywidget.h \ 34 graphicsview/qgraphicsgridlayout.h 35 36 SOURCES += \ 37 graphicsview/qgraphicslayout.cpp \ 38 graphicsview/qgraphicslayout_p.cpp \ 39 graphicsview/qgraphicslayoutitem.cpp \ 40 graphicsview/qgraphicslinearlayout.cpp \ 41 graphicsview/qgraphicswidget.cpp \ 42 graphicsview/qgraphicswidget_p.cpp \ 43 graphicsview/qgridlayoutengine.cpp \ 44 graphicsview/qgraphicsproxywidget.cpp \ 45 graphicsview/qgraphicsgridlayout.cpp 46 31 SOURCES += graphicsview/qgraphicsgridlayout.cpp \ 32 graphicsview/qgraphicsitem.cpp \ 33 graphicsview/qgraphicsitemanimation.cpp \ 34 graphicsview/qgraphicslayout.cpp \ 35 graphicsview/qgraphicslayout_p.cpp \ 36 graphicsview/qgraphicslayoutitem.cpp \ 37 graphicsview/qgraphicslinearlayout.cpp \ 38 graphicsview/qgraphicsproxywidget.cpp \ 39 graphicsview/qgraphicsscene.cpp \ 40 graphicsview/qgraphicsscene_bsp.cpp \ 41 graphicsview/qgraphicsscenebsptreeindex.cpp \ 42 graphicsview/qgraphicssceneevent.cpp \ 43 graphicsview/qgraphicssceneindex.cpp \ 44 graphicsview/qgraphicsscenelinearindex.cpp \ 45 graphicsview/qgraphicstransform.cpp \ 46 graphicsview/qgraphicsview.cpp \ 47 graphicsview/qgraphicswidget.cpp \ 48 graphicsview/qgraphicswidget_p.cpp \ 49 graphicsview/qgridlayoutengine.cpp \ 50 graphicsview/qsimplex_p.cpp \ 51 graphicsview/qgraphicsanchorlayout_p.cpp \ 52 graphicsview/qgraphicsanchorlayout.cpp -
trunk/src/gui/graphicsview/qgraphicsgridlayout.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 widgets in Graphics View. 46 46 \since 4.4 47 \ingroup multimedia 47 48 48 \ingroup graphicsview-api 49 49 … … 64 64 removeAt() will remove an item from the layout, without 65 65 destroying it. 66 66 67 67 \sa QGraphicsLinearLayout, QGraphicsWidget 68 68 */ … … 90 90 91 91 QGridLayoutEngine engine; 92 #ifdef QT_DEBUG 92 #ifdef QT_DEBUG 93 93 void dump(int indent) const; 94 94 #endif … … 101 101 wid = new QWidget; 102 102 QGraphicsItem *item = parentItem(); 103 QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();103 QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style(); 104 104 return QLayoutStyleInfo(style, wid); 105 105 } … … 122 122 QGraphicsLayoutItem *item = itemAt(i); 123 123 // The following lines can be removed, but this removes the item 124 // from the layout more efficiently than the implementation of 124 // from the layout more efficiently than the implementation of 125 125 // ~QGraphicsLayoutItem. 126 126 removeAt(i); … … 142 142 Q_D(QGraphicsGridLayout); 143 143 if (row < 0 || column < 0) { 144 145 146 144 qWarning("QGraphicsGridLayout::addItem: invalid row/column: %d", 145 row < 0 ? row : column); 146 return; 147 147 } 148 148 if (columnSpan < 1 || rowSpan < 1) { 149 150 151 149 qWarning("QGraphicsGridLayout::addItem: invalid row span/column span: %d", 150 rowSpan < 1 ? rowSpan : columnSpan); 151 return; 152 152 } 153 153 if (!item) { 154 qWarning("QGraphicsGridLayout::addItem: cannot add null item"); 155 return; 154 qWarning("QGraphicsGridLayout::addItem: cannot add null item"); 155 return; 156 } 157 if (item == this) { 158 qWarning("QGraphicsGridLayout::addItem: cannot insert itself"); 159 return; 156 160 } 157 161 … … 648 652 649 653 QT_END_NAMESPACE 650 651 #endif //QT_NO_GRAPHICSVIEW 654 655 #endif //QT_NO_GRAPHICSVIEW -
trunk/src/gui/graphicsview/qgraphicsgridlayout.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/gui/graphicsview/qgraphicsitem.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 items in a QGraphicsScene. 46 46 \since 4.2 47 \ingroup multimedia 47 48 48 \ingroup graphicsview-api 49 49 … … 53 53 QGraphicsItem is part of \l{The Graphics View Framework} 54 54 55 \im ggraphicsview-items.png55 \image graphicsview-items.png 56 56 57 57 For convenience, Qt provides a set of standard graphics items for the most … … 92 92 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 0 93 93 94 The boundingRect() function has many different purposes. QGraphicsScene 95 bases its item index on boundingRect(), and QGraphicsView uses it both for 96 culling invisible items, and for determining the area that needs to be 97 recomposed when drawing overlapping items. In addition, QGraphicsItem's 98 collision detection mechanisms use boundingRect() to provide an efficient 99 cut-off. The fine grained collision algorithm in collidesWithItem() is based 100 on calling shape(), which returns an accurate outline of the item's shape 101 as a QPainterPath. 102 103 QGraphicsScene expects all items boundingRect() and shape() to remain 104 unchanged unless it is notified. If you want to change an item's geometry 105 in any way, you must first call prepareGeometryChange() to allow 106 QGraphicsScene to update its bookkeeping. 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. 107 109 108 110 Collision detection can be done in two ways: … … 110 112 \list 1 111 113 112 \o Reimplement shape() to return an accurate shape for your item, and rely 113 on the default implementation of collidesWithItem() to do shape-shape 114 intersection. This can be rather expensive if the shapes are complex. 115 116 \o Reimplement collidesWithItem() to provide your own custom item and shape 117 collision algorithm. 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. 118 121 119 122 \endlist … … 131 134 \img graphicsview-parentchild.png 132 135 133 QGraphicsItem supports affine transformations in addition to its base 134 position, pos(). To change the item's transformation, you can either pass 135 a transformation matrix to setTransform(), or call one of the convenience 136 functions rotate(), scale(), translate(), or shear(). Item transformations 137 accumulate from parent to child, so if both a parent and child item are 138 rotated 90 degrees, the child's total transformation will be 180 degrees. 139 Similarly, if the item's parent is scaled to 2x its original size, its 140 children will also be twice as large. An item's transformation does not 141 affect its own local geometry; all geometry functions (e.g., contains(), 142 update(), and all the mapping functions) still operate in local 143 coordinates. For convenience, QGraphicsItem provides the functions 144 sceneTransform(), which returns the item's total transformation matrix 145 (including its position and all parents' positions and transformations), 146 and scenePos(), which returns its position in scene coordinates. To reset 147 an item's matrix, call resetTransform(). 136 \section1 Transformation 137 138 QGraphicsItem supports projective transformations in addition to its base 139 position, pos(). There are several ways to change an item's transformation. 140 For simple transformations, you can call either of the convenience 141 functions setRotation() or setScale(), or you can pass any transformation 142 matrix to setTransform(). For advanced transformation control you also have 143 the option of setting several combined transformations by calling 144 setTransformations(). 145 146 Item transformations accumulate from parent to child, so if both a parent 147 and child item are rotated 90 degrees, the child's total transformation 148 will be 180 degrees. Similarly, if the item's parent is scaled to 2x its 149 original size, its children will also be twice as large. An item's 150 transformation does not affect its own local geometry; all geometry 151 functions (e.g., contains(), update(), and all the mapping functions) still 152 operate in local coordinates. For convenience, QGraphicsItem provides the 153 functions sceneTransform(), which returns the item's total transformation 154 matrix (including its position and all parents' positions and 155 transformations), and scenePos(), which returns its position in scene 156 coordinates. To reset an item's matrix, call resetTransform(). 157 158 Certain transformation operations produce a different outcome depending on 159 the order in which they are applied. For example, if you scale an 160 transform, and then rotate it, you may get a different result than if the 161 transform was rotated first. However, the order you set the transformation 162 properties on QGraphicsItem does not affect the resulting transformation; 163 QGraphicsItem always applies the properties in a fixed, defined order: 164 165 \list 166 \o The item's base transform is applied (transform()) 167 \o The item's transformations list is applied in order (transformations()) 168 \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint()) 169 \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint()) 170 \endlist 171 172 \section1 Painting 148 173 149 174 The paint() function is called by QGraphicsView to paint the item's … … 162 187 drawn before their children. 163 188 189 \section1 Sorting 190 191 All items are drawn in a defined, stable order, and this same order decides 192 which items will receive mouse input first when you click on the scene. 193 Normally you don't have to worry about sorting, as the items follow a 194 "natural order", following the logical structure of the scene. 195 196 An item's children are stacked on top of the parent, and sibling items are 197 stacked by insertion order (i.e., in the same order that they were either 198 added to the scene, or added to the same parent). If you add item A, and 199 then B, then B will be on top of A. If you then add C, the items' stacking 200 order will be A, then B, then C. 201 202 \image graphicsview-zorder.png 203 204 This example shows the stacking order of all limbs of the robot from the 205 \l{graphicsview/dragdroprobot}{Drag and Drop Robot} example. The torso is 206 the root item (all other items are children or descendants of the torso), 207 so it is drawn first. Next, the head is drawn, as it is the first item in 208 the torso's list of children. Then the upper left arm is drawn. As the 209 lower arm is a child of the upper arm, the lower arm is then drawn, 210 followed by the upper arm's next sibling, which is the upper right arm, and 211 so on. 212 213 For advanced users, there are ways to alter how your items are sorted: 214 215 \list 216 \o You can call setZValue() on an item to explicitly stack it on top of, or 217 under, other sibling items. The default Z value for an item is 0. Items 218 with the same Z value are stacked by insertion order. 219 220 \o You can call stackBefore() to reorder the list of children. This will 221 directly modify the insertion order. 222 223 \o You can set the ItemStacksBehindParent flag to stack a child item behind 224 its parent. 225 \endlist 226 227 The stacking order of two sibling items also counts for each item's 228 children and descendant items. So if one item is on top of another, then 229 all its children will also be on top of all the other item's children as 230 well. 231 232 \section1 Events 233 164 234 QGraphicsItem receives events from QGraphicsScene through the virtual 165 235 function sceneEvent(). This function distributes the most common events … … 172 242 hover enter, move and leave events 173 243 \o inputMethodEvent() handles input events, for accessibility support 174 \o keyPressEvent() and keyReleaseEvent handle key press and release events244 \o keyPressEvent() and keyReleaseEvent() handle key press and release events 175 245 \o mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and 176 246 mouseDoubleClickEvent() handles mouse press, move, release, click and … … 178 248 \endlist 179 249 180 You can filter events for any other item by installing event 181 filters. This functionaly is separate from from Qt's regular 182 event filters (see QObject::installEventFilter()), which only 183 work on subclasses of QObject. After installing your item as an 184 event filter for another item by calling 185 installSceneEventFilter(), the filtered events will be received 186 by the virtual function sceneEventFilter(). You can remove item 187 event filters by calling removeSceneEventFilter(). 250 You can filter events for any other item by installing event filters. This 251 functionality is separate from Qt's regular event filters (see 252 QObject::installEventFilter()), which only work on subclasses of QObject. After 253 installing your item as an event filter for another item by calling 254 installSceneEventFilter(), the filtered events will be received by the virtual 255 function sceneEventFilter(). You can remove item event filters by calling 256 removeSceneEventFilter(). 257 258 \section1 Custom Data 188 259 189 260 Sometimes it's useful to register custom data with an item, be it a custom … … 275 346 drop shadow effects and for decoration objects that follow the parent 276 347 item's geometry without drawing on top of it. 348 349 \value ItemUsesExtendedStyleOption The item makes use of either 350 \l{QStyleOptionGraphicsItem::}{exposedRect} or 351 \l{QStyleOptionGraphicsItem::}{matrix} in QStyleOptionGraphicsItem. By default, 352 the \l{QStyleOptionGraphicsItem::}{exposedRect} is initialized to the item's 353 boundingRect() and the \l{QStyleOptionGraphicsItem::}{matrix} is untransformed. 354 You can enable this flag for the style options to be set up with more 355 fine-grained values. 356 Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag 357 and always initialized to 1. Use 358 QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need a higher 359 value. 360 361 \value ItemHasNoContents The item does not paint anything (i.e., calling 362 paint() on the item has no effect). You should set this flag on items that 363 do not need to be painted to ensure that Graphics View avoids unnecessary 364 painting preparations. This flag was introduced in Qt 4.6. 365 366 \value ItemSendsGeometryChanges The item enables itemChange() 367 notifications for ItemPositionChange, ItemPositionHasChanged, 368 ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For 369 performance reasons, these notifications are disabled by default. You must 370 enable this flag to receive notifications for position and transform 371 changes. This flag was introduced in Qt 4.6. 372 373 \value ItemAcceptsInputMethod The item supports input methods typically 374 used for Asian languages. 375 This flag was introduced in Qt 4.6. 376 377 \value ItemNegativeZStacksBehindParent The item automatically stacks behind 378 it's parent if it's z-value is negative. This flag enables setZValue() to 379 toggle ItemStacksBehindParent. 380 381 \value ItemIsPanel The item is a panel. A panel provides activation and 382 contained focus handling. Only one panel can be active at a time (see 383 QGraphicsItem::isActive()). When no panel is active, QGraphicsScene 384 activates all non-panel items. Window items (i.e., 385 QGraphicsItem::isWindow() returns true) are panels. This flag was 386 introduced in Qt 4.6. 387 388 \omitvalue ItemIsFocusScope \omit Internal only (for now). \endomit 389 390 \value ItemSendsScenePositionChanges The item enables itemChange() 391 notifications for ItemScenePositionHasChanged. For performance reasons, 392 these notifications are disabled by default. You must enable this flag 393 to receive notifications for scene position changes. This flag was 394 introduced in Qt 4.6. 277 395 */ 278 396 … … 313 431 314 432 \value ItemPositionChange The item's position changes. This notification 315 is only sent when the item's local position changes, relative to its316 parent, has changed (i.e., as a result of calling setPos() or317 moveBy()). The value argument is the new position (i.e., a QPointF). You318 can call pos() to get the original position. Do not call setPos() or319 moveBy() in itemChange() as this notification is delivered; instead, you320 can return the new, adjusted position from itemChange(). After this321 notification, QGraphicsItem immediately sends the ItemPositionHasChanged322 notification if the position changed.433 is sent if the ItemSendsGeometryChanges flag is enabled, and when the 434 item's local position changes, relative to its parent (i.e., as a result 435 of calling setPos() or moveBy()). The value argument is the new position 436 (i.e., a QPointF). You can call pos() to get the original position. Do 437 not call setPos() or moveBy() in itemChange() as this notification is 438 delivered; instead, you can return the new, adjusted position from 439 itemChange(). After this notification, QGraphicsItem immediately sends the 440 ItemPositionHasChanged notification if the position changed. 323 441 324 442 \value ItemPositionHasChanged The item's position has changed. This 325 notification is only sent after the item's local position, relative to its 326 parent, has changed. The value argument is the new position (the same as 327 pos()), and QGraphicsItem ignores the return value for this notification 328 (i.e., a read-only notification). 443 notification is sent if the ItemSendsGeometryChanges flag is enabled, and 444 after the item's local position, relative to its parent, has changed. The 445 value argument is the new position (the same as pos()), and QGraphicsItem 446 ignores the return value for this notification (i.e., a read-only 447 notification). 329 448 330 449 \value ItemTransformChange The item's transformation matrix changes. This 331 notification is only sent when the item's local transformation matrix 332 changes (i.e., as a result of calling setTransform(), or one of the 333 convenience transformation functions, such as rotate()). The value 334 argument is the new matrix (i.e., a QTransform); to get the old matrix, 335 call transform(). Do not call setTransform() or any of the transformation 336 convenience functions in itemChange() as this notification is delivered; 337 instead, you can return the new matrix from itemChange(). 450 notification is send if the ItemSendsGeometryChanges flag is enabled, and 451 when the item's local transformation matrix changes (i.e., as a result of 452 calling setTransform(). The value argument is the new matrix (i.e., a 453 QTransform); to get the old matrix, call transform(). Do not call 454 setTransform() or set any of the transformation properties in itemChange() 455 as this notification is delivered; instead, you can return the new matrix 456 from itemChange(). This notification is not sent if you change the 457 transformation properties. 338 458 339 459 \value ItemTransformHasChanged The item's transformation matrix has 340 changed. This notification is only sent after the item's local 341 trasformation matrix has changed. The value argument is the new matrix 460 changed either because setTransform is called, or one of the 461 transformation properties is changed. This notification is sent if the 462 ItemSendsGeometryChanges flag is enabled, and after the item's local 463 transformation matrix has changed. The value argument is the new matrix 342 464 (same as transform()), and QGraphicsItem ignores the return value for this 343 465 notification (i.e., a read-only notification). 344 466 345 \value ItemSelectedChange The item's selected state changes. If the item 346 is presently selected, it will become unselected, and vice verca. The347 value argument is the new selected state (i.e., true or false). Do not348 call setSelected() in itemChange() as this notification is delivered();349 instead, youcan return the new selected state from itemChange().467 \value ItemSelectedChange The item's selected state changes. If the item is 468 presently selected, it will become unselected, and vice verca. The value 469 argument is the new selected state (i.e., true or false). Do not call 470 setSelected() in itemChange() as this notification is delivered; instead, you 471 can return the new selected state from itemChange(). 350 472 351 473 \value ItemSelectedHasChanged The item's selected state has changed. The … … 447 569 argument is the new opacity (i.e., a double). Do not call setOpacity() as 448 570 this notification is delivered. The return value is ignored. 571 572 \value ItemScenePositionHasChanged The item's scene position has changed. 573 This notification is sent if the ItemSendsScenePositionChanges flag is 574 enabled, and after the item's scene position has changed (i.e., the 575 position or transformation of the item itself or the position or 576 transformation of any ancestor has changed). The value argument is the 577 new scene position (the same as scenePos()), and QGraphicsItem ignores 578 the return value for this notification (i.e., a read-only notification). 449 579 */ 450 580 … … 492 622 */ 493 623 624 /*! 625 \enum QGraphicsItem::PanelModality 626 \since 4.6 627 628 This enum specifies the behavior of a modal panel. A modal panel 629 is one that blocks input to other panels. Note that items that 630 are children of a modal panel are not blocked. 631 632 The values are: 633 \value NonModal The panel is not modal and does not block input to other panels. 634 \value PanelModal The panel is modal to a single item hierarchy and blocks input to its parent pane, all grandparent panels, and all siblings of its parent and grandparent panels. 635 \value SceneModal The window is modal to the entire scene and blocks input to all panels. 636 637 \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel 638 */ 639 494 640 #include "qgraphicsitem.h" 495 641 … … 502 648 #include "qgraphicswidget.h" 503 649 #include "qgraphicsproxywidget.h" 650 #include "qgraphicsscenebsptreeindex_p.h" 504 651 #include <QtCore/qbitarray.h> 505 652 #include <QtCore/qdebug.h> … … 516 663 #include <QtGui/qstyleoption.h> 517 664 #include <QtGui/qevent.h> 665 #include <QtGui/qinputcontext.h> 666 #include <QtGui/qgraphicseffect.h> 518 667 519 668 #include <private/qgraphicsitem_p.h> … … 522 671 #include <private/qtextdocumentlayout_p.h> 523 672 #include <private/qtextengine_p.h> 673 #include <private/qwidget_p.h> 674 675 #ifdef Q_WS_X11 676 #include <private/qt_x11_p.h> 677 #include <private/qpixmap_x11_p.h> 678 #endif 679 680 #include <private/qgesturemanager_p.h> 524 681 525 682 #include <math.h> 526 683 527 684 QT_BEGIN_NAMESPACE 528 529 // QRectF::intersects() returns false always if either the source or target530 // rectangle's width or height are 0. This works around that problem.531 static inline void _q_adjustRect(QRectF *rect)532 {533 Q_ASSERT(rect);534 if (!rect->width())535 rect->adjust(-0.00001, 0, 0.00001, 0);536 if (!rect->height())537 rect->adjust(0, -0.00001, 0, 0.00001);538 }539 685 540 686 static inline void _q_adjustRect(QRect *rect) … … 556 702 }; 557 703 Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore) 558 559 /*!560 \internal561 562 Removes the first instance of \a child from \a children. This is a563 heuristic approach that assumes that it's common to remove items from the564 start or end of the list.565 */566 static void qt_graphicsitem_removeChild(QGraphicsItem *child, QList<QGraphicsItem *> *children)567 {568 const int n = children->size();569 for (int i = 0; i < (n + 1) / 2; ++i) {570 if (children->at(i) == child) {571 children->removeAt(i);572 return;573 }574 int j = n - i - 1;575 if (children->at(j) == child) {576 children->removeAt(j);577 return;578 }579 }580 }581 704 582 705 /*! … … 622 745 // disabled \a childFlag, or has been reparented. 623 746 switch (int(childFlag)) { 747 case -2: 748 flag = AncestorFiltersChildEvents; 749 enabled = q->filtersChildEvents(); 750 break; 624 751 case -1: 625 752 flag = AncestorHandlesChildEvents; … … 629 756 flag = AncestorClipsChildren; 630 757 enabled = flags & QGraphicsItem::ItemClipsChildrenToShape; 631 invalidateCachedClipPathRecursively(/*childrenOnly=*/true);632 758 break; 633 759 case QGraphicsItem::ItemIgnoresTransformations: … … 639 765 } 640 766 641 // Inherit the enabled-state from our parents. 642 if ((parent && ((parent->d_ptr->ancestorFlags & flag) 643 || (int(parent->d_ptr->flags & childFlag) == childFlag) 644 || (childFlag == -1 && parent->d_ptr->handlesChildEvents)))) { 645 enabled = true; 646 ancestorFlags |= flag; 767 if (parent) { 768 // Inherit the enabled-state from our parents. 769 if ((parent->d_ptr->ancestorFlags & flag) 770 || (int(parent->d_ptr->flags & childFlag) == childFlag) 771 || (childFlag == -1 && parent->d_ptr->handlesChildEvents) 772 || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)) { 773 enabled = true; 774 ancestorFlags |= flag; 775 } else { 776 ancestorFlags &= ~flag; 777 } 778 } else { 779 // Top-level root items don't have any ancestors, so there are no 780 // ancestor flags either. 781 ancestorFlags = 0; 647 782 } 648 649 // Top-level root items don't have any ancestors, so there are no650 // ancestor flags either.651 if (!parent)652 ancestorFlags = 0;653 783 } else { 654 784 // Don't set or propagate the ancestor flag if it's already correct. … … 663 793 664 794 // Don't process children if the item has the main flag set on itself. 665 if ((childFlag != -1 && int(flags & childFlag) == childFlag) || (int(childFlag) == -1 && handlesChildEvents)) 795 if ((childFlag != -1 && int(flags & childFlag) == childFlag) 796 || (int(childFlag) == -1 && handlesChildEvents) 797 || (int(childFlag) == -2 && filtersDescendantEvents)) 666 798 return; 667 799 } … … 755 887 \internal 756 888 757 Returns true if this item or any of its ancestors are untransformable. 758 */ 759 bool QGraphicsItemPrivate::itemIsUntransformable() const 760 { 761 return (flags & QGraphicsItem::ItemIgnoresTransformations) 762 || (ancestorFlags & AncestorIgnoresTransformations); 889 Combines this item's position and transform onto \a transform. 890 891 If you need to change this function (e.g., adding more transformation 892 modes / options), make sure to change all places marked with COMBINE. 893 */ 894 void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const 895 { 896 // COMBINE 897 if (viewTransform && itemIsUntransformable()) { 898 *x = q_ptr->deviceTransform(*viewTransform); 899 } else { 900 if (transformData) 901 *x *= transformData->computedFullTransform(); 902 if (!pos.isNull()) 903 *x *= QTransform::fromTranslate(pos.x(), pos.y()); 904 } 905 } 906 907 /*! 908 \internal 909 910 Combines this item's position and transform onto \a transform. 911 912 If you need to change this function (e.g., adding more transformation 913 modes / options), make sure to change QGraphicsItem::deviceTransform() as 914 well. 915 */ 916 void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const 917 { 918 // COMBINE 919 if (viewTransform && itemIsUntransformable()) { 920 *x = q_ptr->deviceTransform(*viewTransform); 921 } else { 922 x->translate(pos.x(), pos.y()); 923 if (transformData) 924 *x = transformData->computedFullTransform(x); 925 } 926 } 927 928 void QGraphicsItemPrivate::updateSceneTransformFromParent() 929 { 930 if (parent) { 931 Q_ASSERT(!parent->d_ptr->dirtySceneTransform); 932 if (parent->d_ptr->sceneTransformTranslateOnly) { 933 sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(), 934 parent->d_ptr->sceneTransform.dy() + pos.y()); 935 } else { 936 sceneTransform = parent->d_ptr->sceneTransform; 937 sceneTransform.translate(pos.x(), pos.y()); 938 } 939 if (transformData) { 940 sceneTransform = transformData->computedFullTransform(&sceneTransform); 941 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); 942 } else { 943 sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly; 944 } 945 } else if (!transformData) { 946 sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); 947 sceneTransformTranslateOnly = 1; 948 } else if (transformData->onlyTransform) { 949 sceneTransform = transformData->transform; 950 if (!pos.isNull()) 951 sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y()); 952 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); 953 } else if (pos.isNull()) { 954 sceneTransform = transformData->computedFullTransform(); 955 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); 956 } else { 957 sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); 958 sceneTransform = transformData->computedFullTransform(&sceneTransform); 959 sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); 960 } 961 dirtySceneTransform = 0; 763 962 } 764 963 … … 782 981 \internal 783 982 983 Make sure not to trigger any pure virtual function calls (e.g., 984 prepareGeometryChange) if the item is in its destructor, i.e. 985 inDestructor is 1. 986 */ 987 void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) 988 { 989 Q_Q(QGraphicsItem); 990 if (newParent == q) { 991 qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this); 992 return; 993 } 994 if (newParent == parent) 995 return; 996 997 const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange, 998 qVariantFromValue<QGraphicsItem *>(newParent))); 999 newParent = qVariantValue<QGraphicsItem *>(newParentVariant); 1000 if (newParent == parent) 1001 return; 1002 1003 if (scene) { 1004 // Deliver the change to the index 1005 scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); 1006 1007 // Disable scene pos notifications for old ancestors 1008 if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) 1009 scene->d_func()->setScenePosItemEnabled(q, false); 1010 } 1011 1012 if (subFocusItem && parent) { 1013 // Make sure none of the old parents point to this guy. 1014 subFocusItem->d_ptr->clearSubFocus(parent); 1015 } 1016 1017 // We anticipate geometry changes. If the item is deleted, it will be 1018 // removed from the index at a later stage, and the whole scene will be 1019 // updated. 1020 if (!inDestructor) 1021 q_ptr->prepareGeometryChange(); 1022 1023 const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(q)); 1024 if (parent) { 1025 // Remove from current parent 1026 parent->d_ptr->removeChild(q); 1027 parent->itemChange(QGraphicsItem::ItemChildRemovedChange, thisPointerVariant); 1028 } 1029 1030 // Update toplevelitem list. If this item is being deleted, its parent 1031 // will be 0 but we don't want to register/unregister it in the TLI list. 1032 if (scene && !inDestructor) { 1033 if (parent && !newParent) { 1034 scene->d_func()->registerTopLevelItem(q); 1035 } else if (!parent && newParent) { 1036 scene->d_func()->unregisterTopLevelItem(q); 1037 } 1038 } 1039 1040 // Ensure any last parent focus scope does not point to this item or any of 1041 // its descendents. 1042 QGraphicsItem *p = parent; 1043 QGraphicsItem *parentFocusScopeItem = 0; 1044 while (p) { 1045 if (p->flags() & QGraphicsItem::ItemIsFocusScope) { 1046 // If this item's focus scope's focus scope item points 1047 // to this item or a descendent, then clear it. 1048 QGraphicsItem *fsi = p->d_ptr->focusScopeItem; 1049 if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) { 1050 parentFocusScopeItem = fsi; 1051 p->d_ptr->focusScopeItem = 0; 1052 } 1053 break; 1054 } 1055 p = p->d_ptr->parent; 1056 } 1057 1058 // Update focus scope item ptr in new scope. 1059 QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; 1060 if (newFocusScopeItem && newParent) { 1061 if (subFocusItem) { 1062 // Find the subFocusItem's topmost focus scope. 1063 QGraphicsItem *ancestorScope = 0; 1064 QGraphicsItem *p = subFocusItem->d_ptr->parent; 1065 while (p) { 1066 if (p->flags() & QGraphicsItem::ItemIsFocusScope) 1067 ancestorScope = p; 1068 if (p->isPanel()) 1069 break; 1070 p = p->parentItem(); 1071 } 1072 if (ancestorScope) 1073 newFocusScopeItem = ancestorScope; 1074 } 1075 1076 QGraphicsItem *p = newParent; 1077 while (p) { 1078 if (p->flags() & QGraphicsItem::ItemIsFocusScope) { 1079 p->d_ptr->focusScopeItem = newFocusScopeItem; 1080 // Ensure the new item is no longer the subFocusItem. The 1081 // only way to set focus on a child of a focus scope is 1082 // by setting focus on the scope itself. 1083 if (subFocusItem && !p->focusItem()) 1084 subFocusItem->d_ptr->clearSubFocus(); 1085 break; 1086 } 1087 p = p->d_ptr->parent; 1088 } 1089 } 1090 1091 if ((parent = newParent)) { 1092 bool implicitUpdate = false; 1093 if (parent->d_func()->scene && parent->d_func()->scene != scene) { 1094 // Move this item to its new parent's scene 1095 parent->d_func()->scene->addItem(q); 1096 implicitUpdate = true; 1097 } else if (!parent->d_func()->scene && scene) { 1098 // Remove this item from its former scene 1099 scene->removeItem(q); 1100 } 1101 1102 parent->d_ptr->addChild(q); 1103 parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant); 1104 if (scene) { 1105 if (!implicitUpdate) 1106 scene->d_func()->markDirty(q_ptr); 1107 1108 // Re-enable scene pos notifications for new ancestors 1109 if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) 1110 scene->d_func()->setScenePosItemEnabled(q, true); 1111 } 1112 1113 // Inherit ancestor flags from the new parent. 1114 updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); 1115 updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); 1116 updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); 1117 updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); 1118 1119 // Update item visible / enabled. 1120 if (parent->isVisible() != visible) { 1121 if (!parent->isVisible() || !explicitlyHidden) 1122 setVisibleHelper(parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate); 1123 } 1124 if (parent->isEnabled() != enabled) { 1125 if (!parent->isEnabled() || !explicitlyDisabled) 1126 setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate); 1127 } 1128 1129 // Auto-activate if visible and the parent is active. 1130 if (q->isVisible() && parent->isActive()) 1131 q->setActive(true); 1132 } else { 1133 // Inherit ancestor flags from the new parent. 1134 updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); 1135 updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); 1136 updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); 1137 updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); 1138 1139 if (!inDestructor) { 1140 // Update item visible / enabled. 1141 if (!visible && !explicitlyHidden) 1142 setVisibleHelper(true, /* explicit = */ false); 1143 if (!enabled && !explicitlyDisabled) 1144 setEnabledHelper(true, /* explicit = */ false); 1145 1146 // If the item is being deleted, the whole scene will be updated. 1147 if (scene) 1148 scene->d_func()->markDirty(q_ptr); 1149 } 1150 } 1151 1152 // Resolve depth. 1153 invalidateDepthRecursively(); 1154 dirtySceneTransform = 1; 1155 1156 // Restore the sub focus chain. 1157 if (subFocusItem) { 1158 subFocusItem->d_ptr->setSubFocus(newParent); 1159 if (parent && parent->isActive()) 1160 subFocusItem->setFocus(); 1161 } 1162 1163 // Deliver post-change notification 1164 q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); 1165 1166 if (isObject) 1167 emit static_cast<QGraphicsObject *>(q)->parentChanged(); 1168 } 1169 1170 /*! 1171 \internal 1172 1173 Returns the bounding rect of this item's children (excluding itself). 1174 */ 1175 void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect) 1176 { 1177 for (int i = 0; i < children.size(); ++i) { 1178 QGraphicsItem *child = children.at(i); 1179 QGraphicsItemPrivate *childd = child->d_ptr.data(); 1180 bool hasPos = !childd->pos.isNull(); 1181 if (hasPos || childd->transformData) { 1182 // COMBINE 1183 QTransform matrix = childd->transformToParent(); 1184 if (x) 1185 matrix *= *x; 1186 *rect |= matrix.mapRect(child->boundingRect()); 1187 if (!childd->children.isEmpty()) 1188 childd->childrenBoundingRectHelper(&matrix, rect); 1189 } else { 1190 if (x) 1191 *rect |= x->mapRect(child->boundingRect()); 1192 else 1193 *rect |= child->boundingRect(); 1194 if (!childd->children.isEmpty()) 1195 childd->childrenBoundingRectHelper(x, rect); 1196 } 1197 } 1198 } 1199 1200 void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, 1201 const QRegion &exposedRegion, bool allItems) const 1202 { 1203 Q_ASSERT(option); 1204 Q_Q(const QGraphicsItem); 1205 1206 // Initialize standard QStyleOption values. 1207 const QRectF brect = q->boundingRect(); 1208 option->state = QStyle::State_None; 1209 option->rect = brect.toRect(); 1210 option->levelOfDetail = 1; 1211 option->exposedRect = brect; 1212 if (selected) 1213 option->state |= QStyle::State_Selected; 1214 if (enabled) 1215 option->state |= QStyle::State_Enabled; 1216 if (q->hasFocus()) 1217 option->state |= QStyle::State_HasFocus; 1218 if (scene) { 1219 if (scene->d_func()->hoverItems.contains(q_ptr)) 1220 option->state |= QStyle::State_MouseOver; 1221 if (q == scene->mouseGrabberItem()) 1222 option->state |= QStyle::State_Sunken; 1223 } 1224 1225 if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption)) 1226 return; 1227 1228 // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect). 1229 option->matrix = worldTransform.toAffine(); //### discards perspective 1230 1231 if (!allItems) { 1232 // Determine the item's exposed area 1233 option->exposedRect = QRectF(); 1234 const QTransform reverseMap = worldTransform.inverted(); 1235 const QVector<QRect> exposedRects(exposedRegion.rects()); 1236 for (int i = 0; i < exposedRects.size(); ++i) { 1237 option->exposedRect |= reverseMap.mapRect(QRectF(exposedRects.at(i))); 1238 if (option->exposedRect.contains(brect)) 1239 break; 1240 } 1241 option->exposedRect &= brect; 1242 } 1243 } 1244 1245 /*! 1246 \internal 1247 784 1248 Empty all cached pixmaps from the pixmap cache. 785 1249 */ … … 787 1251 { 788 1252 QPixmapCache::remove(key); 1253 key = QPixmapCache::Key(); 789 1254 QMutableMapIterator<QPaintDevice *, DeviceData> it(deviceData); 790 1255 while (it.hasNext()) { … … 799 1264 800 1265 /*! 801 Constructs a QGraphicsItem with the given \a parent. 1266 Constructs a QGraphicsItem with the given \a parent item. 1267 It does not modify the parent object returned by QObject::parent(). 802 1268 803 1269 If \a parent is 0, you can add the item to a scene by calling … … 851 1317 associated with a scene, the item will be removed from the scene before it 852 1318 is deleted. 1319 1320 \note It is more efficient to remove the item from the QGraphicsScene before 1321 destroying the item. 853 1322 */ 854 1323 QGraphicsItem::~QGraphicsItem() 855 1324 { 1325 if (d_ptr->isObject) 1326 QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true; 1327 d_ptr->inDestructor = 1; 1328 d_ptr->removeExtraItemCache(); 1329 856 1330 clearFocus(); 857 d_ptr->removeExtraItemCache(); 858 859 QVariant variant; 860 foreach (QGraphicsItem *child, d_ptr->children) { 861 if (QGraphicsItem *parent = child->parentItem()) { 862 qVariantSetValue<QGraphicsItem *>(variant, child); 863 parent->itemChange(ItemChildRemovedChange, variant); 1331 1332 // Update focus scope item ptr. 1333 QGraphicsItem *p = d_ptr->parent; 1334 while (p) { 1335 if (p->flags() & ItemIsFocusScope) { 1336 if (p->d_ptr->focusScopeItem == this) 1337 p->d_ptr->focusScopeItem = 0; 1338 break; 864 1339 } 865 delete child; 866 } 867 d_ptr->children.clear(); 868 869 if (QGraphicsItem *parent = parentItem()) { 870 qVariantSetValue<QGraphicsItem *>(variant, this); 871 parent->itemChange(ItemChildRemovedChange, variant); 872 qt_graphicsitem_removeChild(this, &parent->d_func()->children); 873 } 874 if (d_ptr->scene) 875 d_ptr->scene->d_func()->_q_removeItemLater(this); 876 877 delete d_ptr; 1340 p = p->d_ptr->parent; 1341 } 1342 1343 if (!d_ptr->children.isEmpty()) { 1344 while (!d_ptr->children.isEmpty()) 1345 delete d_ptr->children.first(); 1346 Q_ASSERT(d_ptr->children.isEmpty()); 1347 } 1348 1349 if (d_ptr->scene) { 1350 d_ptr->scene->d_func()->removeItemHelper(this); 1351 } else { 1352 d_ptr->resetFocusProxy(); 1353 d_ptr->setParentItemHelper(0); 1354 } 1355 1356 #ifndef QT_NO_GRAPHICSEFFECT 1357 delete d_ptr->graphicsEffect; 1358 #endif //QT_NO_GRAPHICSEFFECT 1359 if (d_ptr->transformData) { 1360 for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) { 1361 QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i); 1362 static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0; 1363 delete t; 1364 } 1365 } 1366 delete d_ptr->transformData; 878 1367 879 1368 qt_dataStore()->data.remove(this); … … 932 1421 parent, 0 is returned. 933 1422 934 \sa setParentItem(), child ren()1423 \sa setParentItem(), childItems() 935 1424 */ 936 1425 QGraphicsItem *QGraphicsItem::parentItem() const … … 955 1444 956 1445 /*! 1446 \since 4.6 1447 1448 Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item 1449 is not a QGraphicsObject. 1450 1451 \sa parentItem(), childItems() 1452 */ 1453 QGraphicsObject *QGraphicsItem::parentObject() const 1454 { 1455 QGraphicsItem *p = d_ptr->parent; 1456 return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : 0; 1457 } 1458 1459 /*! 957 1460 \since 4.4 958 1461 … … 996 1499 QGraphicsWidget *QGraphicsItem::window() const 997 1500 { 998 if (isWidget() && static_cast<const QGraphicsWidget *>(this)->isWindow()) 999 return static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)); 1000 if (QGraphicsWidget *parent = parentWidget()) 1001 return parent->window(); 1501 QGraphicsItem *p = panel(); 1502 if (p && p->isWindow()) 1503 return static_cast<QGraphicsWidget *>(p); 1002 1504 return 0; 1505 } 1506 1507 /*! 1508 \since 4.6 1509 1510 Returns the item's panel, or 0 if this item does not have a panel. If the 1511 item is a panel, it will return itself. Otherwise it will return the 1512 closest ancestor that is a panel. 1513 1514 \sa isPanel(), ItemIsPanel 1515 */ 1516 QGraphicsItem *QGraphicsItem::panel() const 1517 { 1518 if (d_ptr->flags & ItemIsPanel) 1519 return const_cast<QGraphicsItem *>(this); 1520 return d_ptr->parent ? d_ptr->parent->panel() : 0; 1521 } 1522 1523 /*! 1524 \since 4.6 1525 1526 Return the graphics item cast to a QGraphicsObject, if the class is actually a 1527 graphics object, 0 otherwise. 1528 */ 1529 QGraphicsObject *QGraphicsItem::toGraphicsObject() 1530 { 1531 return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : 0; 1532 } 1533 1534 /*! 1535 \since 4.6 1536 1537 Return the graphics item cast to a QGraphicsObject, if the class is actually a 1538 graphics object, 0 otherwise. 1539 */ 1540 const QGraphicsObject *QGraphicsItem::toGraphicsObject() const 1541 { 1542 return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0; 1003 1543 } 1004 1544 … … 1012 1552 item to the scene yourself. 1013 1553 1014 \sa parentItem(), children() 1554 Calling this function on an item that is an ancestor of \a parent have undefined behaviour. 1555 1556 \sa parentItem(), childItems() 1015 1557 */ 1016 1558 void QGraphicsItem::setParentItem(QGraphicsItem *parent) 1017 1559 { 1018 if (parent == this) { 1019 qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this); 1020 return; 1021 } 1022 if (parent == d_ptr->parent) 1023 return; 1024 const QVariant newParentVariant(itemChange(ItemParentChange, qVariantFromValue<QGraphicsItem *>(parent))); 1025 parent = qVariantValue<QGraphicsItem *>(newParentVariant); 1026 if (parent == d_ptr->parent) 1027 return; 1028 1029 if (QGraphicsWidget *w = d_ptr->isWidget ? static_cast<QGraphicsWidget *>(this) : parentWidget()) { 1030 // Update the child focus chain; when reparenting a widget that has a 1031 // focus child, ensure that that focus child clears its focus child 1032 // chain from our parents before it's reparented. 1033 if (QGraphicsWidget *focusChild = w->focusWidget()) 1034 focusChild->clearFocus(); 1035 } 1036 1037 // We anticipate geometry changes 1038 prepareGeometryChange(); 1039 1040 const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this)); 1041 if (d_ptr->parent) { 1042 // Remove from current parent 1043 qt_graphicsitem_removeChild(this, &d_ptr->parent->d_func()->children); 1044 d_ptr->parent->itemChange(ItemChildRemovedChange, thisPointerVariant); 1045 } 1046 1047 if ((d_ptr->parent = parent)) { 1048 bool implicitUpdate = false; 1049 if (parent->d_func()->scene && parent->d_func()->scene != d_ptr->scene) { 1050 // Move this item to its new parent's scene 1051 parent->d_func()->scene->addItem(this); 1052 implicitUpdate = true; 1053 } else if (!parent->d_func()->scene && d_ptr->scene) { 1054 // Remove this item from its former scene 1055 d_ptr->scene->removeItem(this); 1056 } 1057 1058 d_ptr->parent->d_func()->children << this; 1059 d_ptr->parent->itemChange(ItemChildAddedChange, thisPointerVariant); 1060 if (!implicitUpdate) 1061 d_ptr->updateHelper(QRectF(), false, true); 1062 1063 // Inherit ancestor flags from the new parent. 1064 d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); 1065 d_ptr->updateAncestorFlag(ItemClipsChildrenToShape); 1066 d_ptr->updateAncestorFlag(ItemIgnoresTransformations); 1067 1068 // Update item visible / enabled. 1069 if (d_ptr->parent->isVisible() != d_ptr->visible) { 1070 if (!d_ptr->parent->isVisible() || !d_ptr->explicitlyHidden) 1071 d_ptr->setVisibleHelper(d_ptr->parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate); 1072 } 1073 if (d_ptr->parent->isEnabled() != d_ptr->enabled) { 1074 if (!d_ptr->parent->isEnabled() || !d_ptr->explicitlyDisabled) 1075 d_ptr->setEnabledHelper(d_ptr->parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate); 1076 } 1077 1078 } else { 1079 // Inherit ancestor flags from the new parent. 1080 d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); 1081 d_ptr->updateAncestorFlag(ItemClipsChildrenToShape); 1082 d_ptr->updateAncestorFlag(ItemIgnoresTransformations); 1083 1084 // Update item visible / enabled. 1085 if (!d_ptr->visible && !d_ptr->explicitlyHidden) 1086 d_ptr->setVisibleHelper(true, /* explicit = */ false); 1087 if (!d_ptr->enabled && !d_ptr->explicitlyDisabled) 1088 d_ptr->setEnabledHelper(true, /* explicit = */ false); 1089 1090 d_ptr->updateHelper(QRectF(), false, true); 1091 } 1092 1093 if (d_ptr->scene) { 1094 // Invalidate any sort caching; arrival of a new item means we need to 1095 // resort. 1096 d_ptr->scene->d_func()->invalidateSortCache(); 1097 } 1098 1099 // Resolve opacity. 1100 d_ptr->updateEffectiveOpacity(); 1101 1102 // Resolve depth. 1103 d_ptr->resolveDepth(parent ? parent->d_ptr->depth : -1); 1104 1105 // Invalidate transform cache. 1106 d_ptr->invalidateSceneTransformCache(); 1107 1108 // Deliver post-change notification 1109 itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); 1560 d_ptr->setParentItemHelper(parent); 1110 1561 } 1111 1562 … … 1125 1576 \since 4.4 1126 1577 1127 Returns a list of this item's children. The items are returned in no 1128 particular order. 1129 1130 \sa setParentItem() 1578 Returns a list of this item's children. 1579 1580 The items are sorted by stacking order. This takes into account both the 1581 items' insertion order and their Z-values. 1582 1583 \sa setParentItem(), zValue(), {QGraphicsItem#Sorting}{Sorting} 1131 1584 */ 1132 1585 QList<QGraphicsItem *> QGraphicsItem::childItems() const 1133 1586 { 1587 const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren(); 1134 1588 return d_ptr->children; 1135 1589 } … … 1155 1609 { 1156 1610 return isWidget() && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window); 1611 } 1612 1613 /*! 1614 \since 4.6 1615 Returns true if the item is a panel; otherwise returns false. 1616 1617 \sa QGraphicsItem::panel(), ItemIsPanel 1618 */ 1619 bool QGraphicsItem::isPanel() const 1620 { 1621 return d_ptr->flags & ItemIsPanel; 1157 1622 } 1158 1623 … … 1212 1677 item is automatically unselected. 1213 1678 1214 By default, no flags are enabled. 1679 By default, no flags are enabled. (QGraphicsWidget enables the 1680 ItemSendsGeometryChanges flag by default in order to track position 1681 changes.) 1215 1682 1216 1683 \sa flags(), setFlag() … … 1218 1685 void QGraphicsItem::setFlags(GraphicsItemFlags flags) 1219 1686 { 1687 if (isWindow()) 1688 flags |= ItemIsPanel; 1689 1220 1690 // Notify change and check for adjustment. 1221 1691 if (quint32(d_ptr->flags) == quint32(flags)) … … 1224 1694 if (quint32(d_ptr->flags) == quint32(flags)) 1225 1695 return; 1696 if (d_ptr->scene) 1697 d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); 1226 1698 1227 1699 // Flags that alter the geometry of the item (or its children). 1228 int geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);1229 bool fullUpdate = ( flags& geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);1700 const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable); 1701 bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask); 1230 1702 if (fullUpdate) 1231 d_ptr-> fullUpdateHelper(false, true);1703 d_ptr->paintedViewBoundingRectsNeedRepaint = 1; 1232 1704 1233 1705 // Keep the old flags to compare the diff. … … 1236 1708 // Update flags. 1237 1709 d_ptr->flags = flags; 1238 1239 // Reresolve effective opacity if the opacity flags change.1240 static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren;1241 if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask))1242 d_ptr->updateEffectiveOpacity();1243 1710 1244 1711 if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) { … … 1260 1727 } 1261 1728 1262 if ((flags & ItemClipsToShape) != (oldFlags & ItemClipsToShape))1263 d_ptr->invalidateCachedClipPath();1264 1265 1729 if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) { 1266 1730 // Item children clipping changes. Propagate the ancestor flag to … … 1269 1733 } 1270 1734 1271 // ### Why updateHelper? 1272 d_ptr->updateHelper(QRectF(), false, true); 1735 if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) { 1736 // Ensure child item sorting is up to date when toggling this flag. 1737 if (d_ptr->parent) 1738 d_ptr->parent->d_ptr->needSortChildren = 1; 1739 else if (d_ptr->scene) 1740 d_ptr->scene->d_func()->needSortTopLevelItems = 1; 1741 } 1742 1743 if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) { 1744 // Update input method sensitivity in any views. 1745 if (d_ptr->scene) 1746 d_ptr->scene->d_func()->updateInputMethodSensitivityInViews(); 1747 } 1748 1749 if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) { 1750 // Update stack-behind. 1751 setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0)); 1752 } 1753 1754 if ((d_ptr->panelModality != NonModal) 1755 && d_ptr->scene 1756 && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) { 1757 // update the panel's modal state 1758 if (flags & ItemIsPanel) 1759 d_ptr->scene->d_func()->enterModal(this); 1760 else 1761 d_ptr->scene->d_func()->leaveModal(this); 1762 } 1763 1764 if (d_ptr->scene) { 1765 if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) { 1766 if (flags & ItemSendsScenePositionChanges) 1767 d_ptr->scene->d_func()->registerScenePosItem(this); 1768 else 1769 d_ptr->scene->d_func()->unregisterScenePosItem(this); 1770 } 1771 d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); 1772 } 1273 1773 1274 1774 // Notify change. … … 1333 1833 1334 1834 if (mode == ItemCoordinateCache) { 1335 if (cache->key.isEmpty()) {1336 // Generate new simple pixmap cache key.1337 QString tmp;1338 tmp.sprintf("qgv-%p", this);1339 cache->key = tmp;1340 }1341 1835 if (lastMode == mode && cache->fixedSize == logicalCacheSize) 1342 1836 noVisualChange = true; … … 1348 1842 } 1349 1843 1844 /*! 1845 \since 4.6 1846 1847 Returns the modality for this item. 1848 */ 1849 QGraphicsItem::PanelModality QGraphicsItem::panelModality() const 1850 { 1851 return d_ptr->panelModality; 1852 } 1853 1854 /*! 1855 \since 4.6 1856 1857 Sets the modality for this item to \a panelModality. 1858 1859 Changing the modality of a visible item takes effect immediately. 1860 */ 1861 void QGraphicsItem::setPanelModality(PanelModality panelModality) 1862 { 1863 if (d_ptr->panelModality == panelModality) 1864 return; 1865 1866 PanelModality previousModality = d_ptr->panelModality; 1867 bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible()); 1868 if (enterLeaveModal && panelModality == NonModal) 1869 d_ptr->scene->d_func()->leaveModal(this); 1870 d_ptr->panelModality = panelModality; 1871 if (enterLeaveModal && d_ptr->panelModality != NonModal) 1872 d_ptr->scene->d_func()->enterModal(this, previousModality); 1873 } 1874 1875 /*! 1876 \since 4.6 1877 1878 Returns true if this item is blocked by a modal panel, false otherwise. If \a blockingPanel is 1879 non-zero, \a blockingPanel will be set to the modal panel that is blocking this item. If this 1880 item is not blocked, \a blockingPanel will not be set by this function. 1881 1882 This function always returns false for items not in a scene. 1883 1884 \sa panelModality() setPanelModality() PanelModality 1885 */ 1886 bool QGraphicsItem::isBlockedByModalPanel(QGraphicsItem **blockingPanel) const 1887 { 1888 if (!d_ptr->scene) 1889 return false; 1890 1891 1892 QGraphicsItem *dummy = 0; 1893 if (!blockingPanel) 1894 blockingPanel = &dummy; 1895 1896 QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func(); 1897 if (scene_d->modalPanels.isEmpty()) 1898 return false; 1899 1900 // ### 1901 if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this) 1902 return false; 1903 1904 for (int i = 0; i < scene_d->modalPanels.count(); ++i) { 1905 QGraphicsItem *modalPanel = scene_d->modalPanels.at(i); 1906 if (modalPanel->panelModality() == QGraphicsItem::SceneModal) { 1907 // Scene modal panels block all non-descendents. 1908 if (modalPanel != this && !modalPanel->isAncestorOf(this)) { 1909 *blockingPanel = modalPanel; 1910 return true; 1911 } 1912 } else { 1913 // Window modal panels block ancestors and siblings/cousins. 1914 if (modalPanel != this 1915 && !modalPanel->isAncestorOf(this) 1916 && commonAncestorItem(modalPanel)) { 1917 *blockingPanel = modalPanel; 1918 return true; 1919 } 1920 } 1921 } 1922 return false; 1923 } 1924 1350 1925 #ifndef QT_NO_TOOLTIP 1351 1926 /*! … … 1416 1991 d_ptr->hasCursor = 1; 1417 1992 if (d_ptr->scene) { 1993 d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; 1418 1994 foreach (QGraphicsView *view, d_ptr->scene->views()) { 1995 view->viewport()->setMouseTracking(true); 1419 1996 // Note: Some of this logic is duplicated in QGraphicsView's mouse events. 1420 1997 if (view->underMouse()) { … … 1523 2100 return; 1524 2101 2102 // Don't show child if parent is not visible 2103 if (parent && newVisible && !parent->d_ptr->visible) 2104 return; 2105 1525 2106 // Modify the property. 1526 2107 const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, … … 1536 2117 if (c) 1537 2118 c->purge(); 1538 updateHelper(QRectF(), /* force = */ true); 2119 if (scene) 2120 scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true); 1539 2121 } 1540 2122 … … 1546 2128 if (scene->d_func()->keyboardGrabberItems.contains(q)) 1547 2129 q->ungrabKeyboard(); 2130 if (q->isPanel() && panelModality != QGraphicsItem::NonModal) 2131 scene->d_func()->leaveModal(q_ptr); 1548 2132 } 1549 2133 if (q_ptr->hasFocus() && scene) { 1550 // Hiding the closest non- windowancestor of the focus item2134 // Hiding the closest non-panel ancestor of the focus item 1551 2135 QGraphicsItem *focusItem = scene->focusItem(); 1552 2136 bool clear = true; 1553 if (isWidget && !focusItem->is Window()) {2137 if (isWidget && !focusItem->isPanel()) { 1554 2138 do { 1555 2139 if (focusItem == q_ptr) { … … 1557 2141 break; 1558 2142 } 1559 } while ((focusItem = focusItem->parentWidget()) && !focusItem->is Window());2143 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel()); 1560 2144 } 1561 2145 if (clear) … … 1565 2149 q_ptr->setSelected(false); 1566 2150 } else { 1567 if (isWidget && scene) { 1568 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); 1569 if (widget->windowType() == Qt::Popup) 1570 scene->d_func()->addPopup(widget); 2151 geometryChanged = 1; 2152 paintedViewBoundingRectsNeedRepaint = 1; 2153 if (scene) { 2154 if (isWidget) { 2155 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); 2156 if (widget->windowType() == Qt::Popup) 2157 scene->d_func()->addPopup(widget); 2158 } 2159 if (q->isPanel() && panelModality != QGraphicsItem::NonModal) { 2160 scene->d_func()->enterModal(q_ptr); 2161 } 1571 2162 } 1572 2163 } … … 1579 2170 } 1580 2171 2172 // Update activation 2173 if (scene && q->isPanel()) { 2174 if (newVisible) { 2175 if (parent && parent->isActive()) 2176 q->setActive(true); 2177 } else { 2178 if (q->isActive()) 2179 scene->setActivePanel(parent); 2180 } 2181 } 2182 1581 2183 // Enable subfocus 1582 if (newVisible && isWidget) { 1583 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); 1584 QGraphicsWidget *fw = widget->focusWidget(); 1585 if (fw && fw != scene->focusItem()) 1586 scene->setFocusItem(fw); 2184 if (scene && newVisible) { 2185 QGraphicsItem *p = parent; 2186 bool done = false; 2187 while (p) { 2188 if (p->flags() & QGraphicsItem::ItemIsFocusScope) { 2189 QGraphicsItem *fsi = p->d_ptr->focusScopeItem; 2190 if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) { 2191 done = true; 2192 while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible()) 2193 fsi = fsi->d_ptr->focusScopeItem; 2194 scene->setFocusItem(fsi); 2195 } 2196 break; 2197 } 2198 p = p->d_ptr->parent; 2199 } 2200 if (!done) { 2201 QGraphicsItem *fi = subFocusItem; 2202 if (fi && fi != scene->focusItem()) { 2203 scene->setFocusItem(fi); 2204 } 2205 } 1587 2206 } 1588 2207 1589 2208 // Deliver post-change notification. 1590 2209 q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant); 2210 2211 if (isObject) 2212 emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged(); 1591 2213 } 1592 2214 … … 1674 2296 q_ptr->ungrabMouse(); 1675 2297 if (q_ptr->hasFocus()) { 1676 // Disabling the closest non- windowancestor of the focus item2298 // Disabling the closest non-panel ancestor of the focus item 1677 2299 // causes focus to pop to the next item, otherwise it's cleared. 1678 2300 QGraphicsItem *focusItem = scene->focusItem(); 1679 2301 bool clear = true; 1680 if (isWidget && !focusItem->is Window() && q_ptr->isAncestorOf(focusItem)) {2302 if (isWidget && !focusItem->isPanel() && q_ptr->isAncestorOf(focusItem)) { 1681 2303 do { 1682 2304 if (focusItem == q_ptr) { … … 1684 2306 break; 1685 2307 } 1686 } while ((focusItem = focusItem->parentWidget()) && !focusItem->is Window());2308 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel()); 1687 2309 } 1688 2310 if (clear) … … 1700 2322 // Schedule redraw. 1701 2323 if (update) 1702 updateHelper();2324 q_ptr->update(); 1703 2325 1704 2326 foreach (QGraphicsItem *child, children) { … … 1709 2331 // Deliver post-change notification. 1710 2332 q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant); 2333 2334 if (isObject) 2335 emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged(); 1711 2336 } 1712 2337 … … 1801 2426 d_ptr->selected = newSelected; 1802 2427 1803 d_ptr->updateHelper(); 1804 2428 update(); 1805 2429 if (d_ptr->scene) { 1806 2430 QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func(); … … 1839 2463 qreal QGraphicsItem::opacity() const 1840 2464 { 1841 if (d_ptr->hasOpacity) { 1842 QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity); 1843 if (!o.isNull()) 1844 return o.toDouble(); 1845 } 1846 return qreal(1.0); 2465 return d_ptr->opacity; 1847 2466 } 1848 2467 … … 1860 2479 qreal QGraphicsItem::effectiveOpacity() const 1861 2480 { 1862 if (!d_ptr->hasEffectiveOpacity) 1863 return qreal(1.0); 1864 1865 QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity); 1866 return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble()); 2481 return d_ptr->effectiveOpacity(); 1867 2482 } 1868 2483 … … 1892 2507 { 1893 2508 // Notify change. 1894 const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity))); 1895 qreal newOpacity = newOpacityVariant.toDouble(); 1896 1897 // Normalize. 1898 newOpacity = qBound<qreal>(0.0, newOpacity, 1.0); 2509 const QVariant newOpacityVariant(itemChange(ItemOpacityChange, opacity)); 2510 2511 // Normalized opacity 2512 qreal newOpacity = qBound(qreal(0), newOpacityVariant.toReal(), qreal(1)); 1899 2513 1900 2514 // No change? Done. 1901 if ( qFuzzyCompare(newOpacity, this->opacity()))2515 if (newOpacity == d_ptr->opacity) 1902 2516 return; 1903 2517 1904 // Assign local opacity. 1905 if (qFuzzyCompare(newOpacity, qreal(1.0))) { 1906 // Opaque, unset opacity. 1907 d_ptr->hasOpacity = 0; 1908 d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity); 1909 } else { 1910 d_ptr->hasOpacity = 1; 1911 d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity)); 1912 } 1913 1914 // Resolve effective opacity. 1915 if (QGraphicsItem *p = d_ptr->parent) 1916 d_ptr->resolveEffectiveOpacity(p->effectiveOpacity()); 1917 else 1918 d_ptr->resolveEffectiveOpacity(1.0); 2518 d_ptr->opacity = newOpacity; 1919 2519 1920 2520 // Notify change. 1921 itemChange(ItemOpacityHasChanged, newOpacity );2521 itemChange(ItemOpacityHasChanged, newOpacityVariant); 1922 2522 1923 2523 // Update. 1924 d_ptr->fullUpdateHelper(); 2524 if (d_ptr->scene) { 2525 #ifndef QT_NO_GRAPHICSEFFECT 2526 d_ptr->invalidateGraphicsEffectsRecursively(); 2527 #endif //QT_NO_GRAPHICSEFFECT 2528 d_ptr->scene->d_func()->markDirty(this, QRectF(), 2529 /*invalidateChildren=*/true, 2530 /*force=*/false, 2531 /*ignoreOpacity=*/true); 2532 } 2533 2534 if (d_ptr->isObject) 2535 emit static_cast<QGraphicsObject *>(this)->opacityChanged(); 2536 } 2537 2538 /*! 2539 Returns a pointer to this item's effect if it has one; otherwise 0. 2540 2541 \since 4.6 2542 */ 2543 #ifndef QT_NO_GRAPHICSEFFECT 2544 QGraphicsEffect *QGraphicsItem::graphicsEffect() const 2545 { 2546 return d_ptr->graphicsEffect; 2547 } 2548 2549 /*! 2550 Sets \a effect as the item's effect. If there already is an effect installed 2551 on this item, QGraphicsItem will delete the existing effect before installing 2552 the new \a effect. 2553 2554 If \a effect is the installed on a different item, setGraphicsEffect() will remove 2555 the effect from the item and install it on this item. 2556 2557 QGraphicsItem takes ownership of \a effect. 2558 2559 \note This function will apply the effect on itself and all its children. 2560 2561 \since 4.6 2562 */ 2563 void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) 2564 { 2565 if (d_ptr->graphicsEffect == effect) 2566 return; 2567 2568 if (d_ptr->graphicsEffect) { 2569 delete d_ptr->graphicsEffect; 2570 d_ptr->graphicsEffect = 0; 2571 } 2572 2573 if (effect) { 2574 // Set new effect. 2575 QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this); 2576 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced); 2577 d_ptr->graphicsEffect = effect; 2578 effect->d_func()->setGraphicsEffectSource(source); 2579 prepareGeometryChange(); 2580 } 2581 } 2582 #endif //QT_NO_GRAPHICSEFFECT 2583 2584 /*! 2585 \internal 2586 \since 4.6 2587 Returns the effective bounding rect of the given item space rect. 2588 If the item has no effect, the rect is returned unmodified. 2589 If the item has an effect, the effective rect can be extend beyond the 2590 item's bounding rect, depending on the effect. 2591 2592 \sa boundingRect() 2593 */ 2594 QRectF QGraphicsItemPrivate::effectiveBoundingRect(const QRectF &rect) const 2595 { 2596 #ifndef QT_NO_GRAPHICSEFFECT 2597 Q_Q(const QGraphicsItem); 2598 QGraphicsEffect *effect = graphicsEffect; 2599 if (scene && effect && effect->isEnabled()) { 2600 QRectF sceneRect = q->mapRectToScene(rect); 2601 QRectF sceneEffectRect; 2602 foreach (QGraphicsView *view, scene->views()) { 2603 QRectF deviceRect = view->d_func()->mapRectFromScene(sceneRect); 2604 QRect deviceEffectRect = effect->boundingRectFor(deviceRect).toAlignedRect(); 2605 sceneEffectRect |= view->d_func()->mapRectToScene(deviceEffectRect); 2606 } 2607 return q->mapRectFromScene(sceneEffectRect); 2608 } 2609 #endif //QT_NO_GRAPHICSEFFECT 2610 return rect; 2611 } 2612 2613 /*! 2614 \internal 2615 \since 4.6 2616 Returns the effective bounding rect of the item. 2617 If the item has no effect, this is the same as the item's bounding rect. 2618 If the item has an effect, the effective rect can be larger than the item's 2619 bouding rect, depending on the effect. 2620 2621 \sa boundingRect() 2622 */ 2623 QRectF QGraphicsItemPrivate::effectiveBoundingRect() const 2624 { 2625 #ifndef QT_NO_GRAPHICSEFFECT 2626 Q_Q(const QGraphicsItem); 2627 QRectF brect = effectiveBoundingRect(q_ptr->boundingRect()); 2628 if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) 2629 return brect; 2630 2631 const QGraphicsItem *effectParent = parent; 2632 while (effectParent) { 2633 QGraphicsEffect *effect = effectParent->d_ptr->graphicsEffect; 2634 if (scene && effect && effect->isEnabled()) { 2635 const QRectF brectInParentSpace = q->mapRectToItem(effectParent, brect); 2636 const QRectF effectRectInParentSpace = effectParent->d_ptr->effectiveBoundingRect(brectInParentSpace); 2637 brect = effectParent->mapRectToItem(q, effectRectInParentSpace); 2638 } 2639 if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) 2640 return brect; 2641 effectParent = effectParent->d_ptr->parent; 2642 } 2643 2644 return brect; 2645 #else //QT_NO_GRAPHICSEFFECT 2646 return q_ptr->boundingRect(); 2647 #endif //QT_NO_GRAPHICSEFFECT 2648 2649 } 2650 2651 /*! 2652 \internal 2653 \since 4.6 2654 Returns the effective bounding rect of this item in scene coordinates, 2655 by combining sceneTransform() with boundingRect(), taking into account 2656 the effect that the item might have. 2657 2658 If the item has no effect, this is the same as sceneBoundingRect(). 2659 2660 \sa effectiveBoundingRect(), sceneBoundingRect() 2661 */ 2662 QRectF QGraphicsItemPrivate::sceneEffectiveBoundingRect() const 2663 { 2664 // Find translate-only offset 2665 // COMBINE 2666 QPointF offset; 2667 const QGraphicsItem *parentItem = q_ptr; 2668 const QGraphicsItemPrivate *itemd; 2669 do { 2670 itemd = parentItem->d_ptr.data(); 2671 if (itemd->transformData) 2672 break; 2673 offset += itemd->pos; 2674 } while ((parentItem = itemd->parent)); 2675 2676 QRectF br = effectiveBoundingRect(); 2677 br.translate(offset); 2678 return !parentItem ? br : parentItem->sceneTransform().mapRect(br); 1925 2679 } 1926 2680 … … 2035 2789 children's areas. 2036 2790 2037 If a parent item handles child events (setHandlesChildEvents()), it will2038 receive hover move, drag move, and drop events as the cursor passes2039 through its children, but it does not receive hover enter and hover leave,2040 nordrag enter and drag leave events on behalf of its children.2791 If a parent item handles child events, it will receive hover move, 2792 drag move, and drop events as the cursor passes through its 2793 children, but it does not receive hover enter and hover leave, nor 2794 drag enter and drag leave events on behalf of its children. 2041 2795 2042 2796 A QGraphicsWidget with window decorations will accept hover events … … 2048 2802 void QGraphicsItem::setAcceptHoverEvents(bool enabled) 2049 2803 { 2804 if (d_ptr->acceptsHover == quint32(enabled)) 2805 return; 2050 2806 d_ptr->acceptsHover = quint32(enabled); 2807 if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) { 2808 d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false; 2809 d_ptr->scene->d_func()->enableMouseTrackingOnViews(); 2810 } 2051 2811 } 2052 2812 … … 2058 2818 void QGraphicsItem::setAcceptsHoverEvents(bool enabled) 2059 2819 { 2060 d_ptr->acceptsHover = quint32(enabled); 2061 } 2062 2063 /*! 2820 setAcceptHoverEvents(enabled); 2821 } 2822 2823 /*! \since 4.6 2824 2825 Returns true if an item accepts \l{QTouchEvent}{touch events}; 2826 otherwise, returns false. By default, items do not accept touch events. 2827 2828 \sa setAcceptTouchEvents() 2829 */ 2830 bool QGraphicsItem::acceptTouchEvents() const 2831 { 2832 return d_ptr->acceptTouchEvents; 2833 } 2834 2835 /*! 2836 \since 4.6 2837 2838 If \a enabled is true, this item will accept \l{QTouchEvent}{touch events}; 2839 otherwise, it will ignore them. By default, items do not accept 2840 touch events. 2841 */ 2842 void QGraphicsItem::setAcceptTouchEvents(bool enabled) 2843 { 2844 if (d_ptr->acceptTouchEvents == quint32(enabled)) 2845 return; 2846 d_ptr->acceptTouchEvents = quint32(enabled); 2847 if (d_ptr->acceptTouchEvents && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreTouchEvents) { 2848 d_ptr->scene->d_func()->allItemsIgnoreTouchEvents = false; 2849 d_ptr->scene->d_func()->enableTouchEventsOnViews(); 2850 } 2851 } 2852 2853 /*! 2854 \since 4.6 2855 2856 Returns true if this item filters child events (i.e., all events 2857 intended for any of its children are instead sent to this item); 2858 otherwise, false is returned. 2859 2860 The default value is false; child events are not filtered. 2861 2862 \sa setFiltersChildEvents() 2863 */ 2864 bool QGraphicsItem::filtersChildEvents() const 2865 { 2866 return d_ptr->filtersDescendantEvents; 2867 } 2868 2869 /*! 2870 \since 4.6 2871 2872 If \a enabled is true, this item is set to filter all events for 2873 all its children (i.e., all events intented for any of its 2874 children are instead sent to this item); otherwise, if \a enabled 2875 is false, this item will only handle its own events. The default 2876 value is false. 2877 2878 \sa filtersChildEvents() 2879 */ 2880 void QGraphicsItem::setFiltersChildEvents(bool enabled) 2881 { 2882 if (d_ptr->filtersDescendantEvents == enabled) 2883 return; 2884 2885 d_ptr->filtersDescendantEvents = enabled; 2886 d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); 2887 } 2888 2889 /*! 2890 \obsolete 2891 2064 2892 Returns true if this item handles child events (i.e., all events 2065 2893 intended for any of its children are instead sent to this item); … … 2082 2910 2083 2911 /*! 2912 \obsolete 2913 2084 2914 If \a enabled is true, this item is set to handle all events for 2085 2915 all its children (i.e., all events intented for any of its … … 2107 2937 d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); 2108 2938 } 2109 2110 /*! 2111 Returns true if this item has keyboard input focus; otherwise, returns 2112 false. 2113 2114 \sa QGraphicsScene::focusItem(), setFocus(), QGraphicsScene::setFocusItem() 2939 /*! 2940 \since 4.6 2941 Returns true if this item is active; otherwise returns false. 2942 2943 An item can only be active if the scene is active. An item is active 2944 if it is, or is a descendent of, an active panel. Items in non-active 2945 panels are not active. 2946 2947 Items that are not part of a panel follow scene activation when the 2948 scene has no active panel. 2949 2950 Only active items can gain input focus. 2951 2952 \sa QGraphicsScene::isActive(), QGraphicsScene::activePanel(), panel(), isPanel() 2953 */ 2954 bool QGraphicsItem::isActive() const 2955 { 2956 if (!d_ptr->scene || !d_ptr->scene->isActive()) 2957 return false; 2958 return panel() == d_ptr->scene->activePanel(); 2959 } 2960 2961 /*! 2962 \since 4.6 2963 2964 If \a active is true, and the scene is active, this item's panel will be 2965 activated. Otherwise, the panel is deactivated. 2966 2967 If the item is not part of an active scene, \a active will decide what 2968 happens to the panel when the scene becomes active or the item is added to 2969 the scene. If true, the item's panel will be activated when the item is 2970 either added to the scene or the scene is activated. Otherwise, the item 2971 will stay inactive independent of the scene's activated state. 2972 2973 \sa isPanel(), QGraphicsScene::setActivePanel(), QGraphicsScene::isActive() 2974 */ 2975 void QGraphicsItem::setActive(bool active) 2976 { 2977 d_ptr->explicitActivate = 1; 2978 d_ptr->wantsActive = active; 2979 if (d_ptr->scene) { 2980 if (active) { 2981 // Activate this item. 2982 d_ptr->scene->setActivePanel(this); 2983 } else { 2984 // Deactivate this item, and reactivate the last active item 2985 // (if any). 2986 QGraphicsItem *lastActive = d_ptr->scene->d_func()->lastActivePanel; 2987 d_ptr->scene->setActivePanel(lastActive != this ? lastActive : 0); 2988 } 2989 } 2990 } 2991 2992 /*! 2993 Returns true if this item is active, and it or its \l{focusProxy()}{focus 2994 proxy} has keyboard input focus; otherwise, returns false. 2995 2996 \sa focusItem(), setFocus(), QGraphicsScene::setFocusItem(), isActive() 2115 2997 */ 2116 2998 bool QGraphicsItem::hasFocus() const 2117 2999 { 2118 return (d_ptr->scene && d_ptr->scene->focusItem() == this); 3000 if (d_ptr->focusProxy) 3001 return d_ptr->focusProxy->hasFocus(); 3002 return isActive() && (d_ptr->scene && d_ptr->scene->focusItem() == this); 2119 3003 } 2120 3004 2121 3005 /*! 2122 3006 Gives keyboard input focus to this item. The \a focusReason argument will 2123 be passed into any focus event generated by this function; it is used to 2124 give an explanation of what caused the item to get focus. 2125 2126 Only items that set the ItemIsFocusable flag can accept keyboard focus. 2127 2128 If this item is not visible (i.e., isVisible() returns false), not 2129 enabled, not associated with a scene, or if it already has input focus, 2130 this function will do nothing. 2131 2132 As a result of calling this function, this item will receive a focus in 2133 event with \a focusReason. If another item already has focus, that item 2134 will first receive a focus out event indicating that it has lost input 3007 be passed into any \l{QFocusEvent}{focus event} generated by this function; 3008 it is used to give an explanation of what caused the item to get focus. 3009 3010 Only enabled items that set the ItemIsFocusable flag can accept keyboard 2135 3011 focus. 2136 3012 2137 \sa clearFocus(), hasFocus() 3013 If this item is not visible, not active, or not associated with a scene, 3014 it will not gain immediate input focus. However, it will be registered as 3015 the preferred focus item for its subtree of items, should it later become 3016 visible. 3017 3018 As a result of calling this function, this item will receive a 3019 \l{focusInEvent()}{focus in event} with \a focusReason. If another item 3020 already has focus, that item will first receive a \l{focusOutEvent()} 3021 {focus out event} indicating that it has lost input focus. 3022 3023 \sa clearFocus(), hasFocus(), focusItem(), focusProxy() 2138 3024 */ 2139 3025 void QGraphicsItem::setFocus(Qt::FocusReason focusReason) 2140 3026 { 2141 if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable)) 3027 d_ptr->setFocusHelper(focusReason, /* climb = */ true); 3028 } 3029 3030 /*! 3031 \internal 3032 */ 3033 void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb) 3034 { 3035 // Disabled / unfocusable items cannot accept focus. 3036 if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable)) 2142 3037 return; 2143 if (isVisible()) { 2144 // Visible items immediately gain focus from scene. 2145 d_ptr->scene->setFocusItem(this, focusReason); 2146 } else if (d_ptr->isWidget) { 2147 // Just set up subfocus. 2148 static_cast<QGraphicsWidget *>(this)->d_func()->setFocusWidget(); 3038 3039 // Find focus proxy. 3040 QGraphicsItem *f = q_ptr; 3041 while (f->d_ptr->focusProxy) 3042 f = f->d_ptr->focusProxy; 3043 3044 // Return if it already has focus. 3045 if (scene && scene->focusItem() == f) 3046 return; 3047 3048 // Update focus scope item ptr. 3049 QGraphicsItem *p = parent; 3050 while (p) { 3051 if (p->flags() & QGraphicsItem::ItemIsFocusScope) { 3052 p->d_ptr->focusScopeItem = q_ptr; 3053 if (!p->focusItem()) { 3054 // If you call setFocus on a child of a focus scope that 3055 // doesn't currently have a focus item, then stop. 3056 return; 3057 } 3058 break; 3059 } 3060 p = p->d_ptr->parent; 3061 } 3062 3063 if (climb) { 3064 while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible()) 3065 f = f->d_ptr->focusScopeItem; 3066 } 3067 3068 // Update the child focus chain. 3069 f->d_ptr->setSubFocus(); 3070 3071 // Update the scene's focus item. 3072 if (scene) { 3073 QGraphicsItem *p = q_ptr->panel(); 3074 if ((!p && scene->isActive()) || (p && p->isActive())) { 3075 // Visible items immediately gain focus from scene. 3076 scene->d_func()->setFocusItemHelper(f, focusReason); 3077 } 2149 3078 } 2150 3079 } … … 2153 3082 Takes keyboard input focus from the item. 2154 3083 2155 If it has focus, a focus out event is sent to this item to tell it that it2156 i s about to lose the focus.3084 If it has focus, a \l{focusOutEvent()}{focus out event} is sent to this 3085 item to tell it that it is about to lose the focus. 2157 3086 2158 3087 Only items that set the ItemIsFocusable flag, or widgets that set an 2159 3088 appropriate focus policy, can accept keyboard focus. 2160 3089 2161 \sa setFocus(), QGraphicsWidget::focusPolicy3090 \sa setFocus(), hasFocus(), QGraphicsWidget::focusPolicy 2162 3091 */ 2163 3092 void QGraphicsItem::clearFocus() 2164 3093 { 2165 if (!d_ptr->scene) 2166 return; 2167 if (d_ptr->isWidget) { 2168 // Invisible widget items with focus must explicitly clear subfocus. 2169 static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget(); 2170 } 2171 if (d_ptr->scene->focusItem() == this) { 3094 // Pass focus to the closest parent focus scope. 3095 if (!d_ptr->inDestructor) { 3096 QGraphicsItem *p = d_ptr->parent; 3097 while (p) { 3098 if (p->flags() & ItemIsFocusScope) { 3099 p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false); 3100 return; 3101 } 3102 p = p->d_ptr->parent; 3103 } 3104 } 3105 3106 // Invisible items with focus must explicitly clear subfocus. 3107 d_ptr->clearSubFocus(this); 3108 3109 if (hasFocus()) { 2172 3110 // If this item has the scene's input focus, clear it. 2173 3111 d_ptr->scene->setFocusItem(0); 2174 3112 } 3113 } 3114 3115 /*! 3116 \since 4.6 3117 3118 Returns this item's focus proxy, or 0 if this item has no 3119 focus proxy. 3120 3121 \sa setFocusProxy(), setFocus(), hasFocus() 3122 */ 3123 QGraphicsItem *QGraphicsItem::focusProxy() const 3124 { 3125 return d_ptr->focusProxy; 3126 } 3127 3128 /*! 3129 \since 4.6 3130 3131 Sets the item's focus proxy to \a item. 3132 3133 If an item has a focus proxy, the focus proxy will receive 3134 input focus when the item gains input focus. The item itself 3135 will still have focus (i.e., hasFocus() will return true), 3136 but only the focus proxy will receive the keyboard input. 3137 3138 A focus proxy can itself have a focus proxy, and so on. In 3139 such case, keyboard input will be handled by the outermost 3140 focus proxy. 3141 3142 The focus proxy \a item must belong to the same scene as 3143 this item. 3144 3145 \sa focusProxy(), setFocus(), hasFocus() 3146 */ 3147 void QGraphicsItem::setFocusProxy(QGraphicsItem *item) 3148 { 3149 if (item == d_ptr->focusProxy) 3150 return; 3151 if (item == this) { 3152 qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy"); 3153 return; 3154 } 3155 if (item) { 3156 if (item->d_ptr->scene != d_ptr->scene) { 3157 qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene"); 3158 return; 3159 } 3160 for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) { 3161 if (f == this) { 3162 qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item); 3163 return; 3164 } 3165 } 3166 } 3167 3168 QGraphicsItem *lastFocusProxy = d_ptr->focusProxy; 3169 if (lastFocusProxy) 3170 lastFocusProxy->d_ptr->focusProxyRefs.removeOne(&d_ptr->focusProxy); 3171 d_ptr->focusProxy = item; 3172 if (item) 3173 item->d_ptr->focusProxyRefs << &d_ptr->focusProxy; 3174 } 3175 3176 /*! 3177 \since 4.6 3178 3179 If this item, a child or descendant of this item currently has input 3180 focus, this function will return a pointer to that item. If 3181 no descendant has input focus, 0 is returned. 3182 3183 \sa hasFocus(), setFocus(), QWidget::focusWidget() 3184 */ 3185 QGraphicsItem *QGraphicsItem::focusItem() const 3186 { 3187 return d_ptr->subFocusItem; 3188 } 3189 3190 /*! 3191 \internal 3192 3193 Returns this item's focus scope item. 3194 */ 3195 QGraphicsItem *QGraphicsItem::focusScopeItem() const 3196 { 3197 return d_ptr->focusScopeItem; 2175 3198 } 2176 3199 … … 2310 3333 item's position in scene coordinates, regardless of its parent. 2311 3334 2312 \sa x(), y(), setPos(), matrix(), {The Graphics View Coordinate System}3335 \sa x(), y(), setPos(), transform(), {The Graphics View Coordinate System} 2313 3336 */ 2314 3337 QPointF QGraphicsItem::pos() const … … 2326 3349 2327 3350 /*! 3351 \since 4.6 3352 3353 Set's the \a x coordinate of the item's position. Equivalent to 3354 calling setPos(x, y()). 3355 3356 \sa x(), setPos() 3357 */ 3358 void QGraphicsItem::setX(qreal x) 3359 { 3360 if (d_ptr->inDestructor) 3361 return; 3362 3363 d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y())); 3364 } 3365 3366 /*! 2328 3367 \fn QGraphicsItem::y() const 2329 3368 … … 2332 3371 \sa x() 2333 3372 */ 3373 3374 /*! 3375 \since 4.6 3376 3377 Set's the \a y coordinate of the item's position. Equivalent to 3378 calling setPos(x(), y). 3379 3380 \sa x(), setPos() 3381 */ 3382 void QGraphicsItem::setY(qreal y) 3383 { 3384 if (d_ptr->inDestructor) 3385 return; 3386 3387 d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y)); 3388 } 2334 3389 2335 3390 /*! … … 2347 3402 \internal 2348 3403 2349 Sets the position \a pos and notifies the change. If \a update is true, 2350 the item is also updated; otherwise it is not updated before and after the 2351 change. 3404 Sets the position \a pos. 2352 3405 */ 2353 3406 void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) 2354 3407 { 2355 3408 Q_Q(QGraphicsItem); 2356 if (this->pos == pos)2357 return;2358 2359 // Notify the item that the position is changing.2360 const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos));2361 QPointF newPos = newPosVariant.toPointF();2362 if (newPos == this->pos)2363 return;2364 2365 // Update and repositition.2366 3409 inSetPosHelper = 1; 2367 updateCachedClipPathFromSetPosHelper(newPos); 2368 if (scene) { 2369 fullUpdateHelper(true); 3410 if (scene) 2370 3411 q->prepareGeometryChange(); 2371 } 2372 this->pos = newPos; 2373 invalidateSceneTransformCache(); 2374 2375 // Send post-notification. 2376 q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); 3412 QPointF oldPos = this->pos; 3413 this->pos = pos; 3414 dirtySceneTransform = 1; 2377 3415 inSetPosHelper = 0; 3416 if (isObject) { 3417 if (pos.x() != oldPos.x()) 3418 emit static_cast<QGraphicsObject *>(q_ptr)->xChanged(); 3419 if (pos.y() != oldPos.y()) 3420 emit static_cast<QGraphicsObject *>(q_ptr)->yChanged(); 3421 } 3422 } 3423 3424 /*! 3425 \internal 3426 3427 Sets the transform \a transform. 3428 */ 3429 void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform) 3430 { 3431 q_ptr->prepareGeometryChange(); 3432 transformData->transform = transform; 3433 dirtySceneTransform = 1; 2378 3434 } 2379 3435 … … 2390 3446 void QGraphicsItem::setPos(const QPointF &pos) 2391 3447 { 2392 d_ptr->setPosHelper(pos); 3448 if (d_ptr->pos == pos) 3449 return; 3450 3451 if (d_ptr->inDestructor) 3452 return; 3453 3454 // Update and repositition. 3455 if (!(d_ptr->flags & ItemSendsGeometryChanges)) { 3456 d_ptr->setPosHelper(pos); 3457 return; 3458 } 3459 3460 // Notify the item that the position is changing. 3461 const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos))); 3462 QPointF newPos = newPosVariant.toPointF(); 3463 if (newPos == d_ptr->pos) 3464 return; 3465 3466 // Update and repositition. 3467 d_ptr->setPosHelper(newPos); 3468 3469 // Send post-notification. 3470 itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); 3471 d_ptr->sendScenePosChange(); 2393 3472 } 2394 3473 … … 2463 3542 \since 4.3 2464 3543 2465 Returns this item's transformation matrix. If no matrix has been set, the 2466 identity matrix is returned. 3544 Returns this item's transformation matrix. 3545 3546 The transformation matrix is combined with the item's rotation(), scale() 3547 and transformations() into a combined transformations for the item. 3548 3549 The default transformation matrix is an identity matrix. 2467 3550 2468 3551 \sa setTransform(), sceneTransform() … … 2470 3553 QTransform QGraphicsItem::transform() const 2471 3554 { 2472 if (!d_ptr-> hasTransform)3555 if (!d_ptr->transformData) 2473 3556 return QTransform(); 2474 return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)); 2475 } 3557 return d_ptr->transformData->transform; 3558 } 3559 3560 /*! 3561 \since 4.6 3562 3563 Returns the clockwise rotation, in degrees, around the Z axis. The default 3564 value is 0 (i.e., the item is not rotated). 3565 3566 The rotation is combined with the item's scale(), transform() and 3567 transformations() to map the item's coordinate system to the parent item. 3568 3569 \sa setRotation(), transformOriginPoint(), {Transformations} 3570 */ 3571 qreal QGraphicsItem::rotation() const 3572 { 3573 if (!d_ptr->transformData) 3574 return 0; 3575 return d_ptr->transformData->rotation; 3576 } 3577 3578 /*! 3579 \since 4.6 3580 3581 Sets the clockwise rotation \a angle, in degrees, around the Z axis. The 3582 default value is 0 (i.e., the item is not rotated). Assigning a negative 3583 value will rotate the item counter-clockwise. Normally the rotation angle 3584 is in the range (-360, 360), but it's also possible to assign values 3585 outside of this range (e.g., a rotation of 370 degrees is the same as a 3586 rotation of 10 degrees). 3587 3588 The item is rotated around its transform origin point, which by default 3589 is (0, 0). You can select a different transformation origin by calling 3590 setTransformOriginPoint(). 3591 3592 The rotation is combined with the item's scale(), transform() and 3593 transformations() to map the item's coordinate system to the parent item. 3594 3595 \sa rotation(), setTransformOriginPoint(), {Transformations} 3596 */ 3597 void QGraphicsItem::setRotation(qreal angle) 3598 { 3599 prepareGeometryChange(); 3600 if (!d_ptr->transformData) 3601 d_ptr->transformData = new QGraphicsItemPrivate::TransformData; 3602 d_ptr->transformData->rotation = angle; 3603 d_ptr->transformData->onlyTransform = false; 3604 d_ptr->dirtySceneTransform = 1; 3605 3606 if (d_ptr->isObject) 3607 emit static_cast<QGraphicsObject *>(this)->rotationChanged(); 3608 } 3609 3610 /*! 3611 \since 4.6 3612 3613 Returns the scale factor of the item. The default scale factor is 1.0 3614 (i.e., the item is not scaled). 3615 3616 The scale is combined with the item's rotation(), transform() and 3617 transformations() to map the item's coordinate system to the parent item. 3618 3619 \sa setScale(), rotation(), {Transformations} 3620 */ 3621 qreal QGraphicsItem::scale() const 3622 { 3623 if (!d_ptr->transformData) 3624 return 1.; 3625 return d_ptr->transformData->scale; 3626 } 3627 3628 /*! 3629 \since 4.6 3630 3631 Sets the scale \a factor of the item. The default scale factor is 1.0 3632 (i.e., the item is not scaled). A scale factor of 0.0 will collapse the 3633 item to a single point. If you provide a negative scale factor, the 3634 item will be flipped and mirrored (i.e., rotated 180 degrees). 3635 3636 The item is scaled around its transform origin point, which by default 3637 is (0, 0). You can select a different transformation origin by calling 3638 setTransformOriginPoint(). 3639 3640 The scale is combined with the item's rotation(), transform() and 3641 transformations() to map the item's coordinate system to the parent item. 3642 3643 \sa scale(), setTransformOriginPoint(), {Transformations} 3644 */ 3645 void QGraphicsItem::setScale(qreal factor) 3646 { 3647 prepareGeometryChange(); 3648 if (!d_ptr->transformData) 3649 d_ptr->transformData = new QGraphicsItemPrivate::TransformData; 3650 d_ptr->transformData->scale = factor; 3651 d_ptr->transformData->onlyTransform = false; 3652 d_ptr->dirtySceneTransform = 1; 3653 3654 if (d_ptr->isObject) 3655 emit static_cast<QGraphicsObject *>(this)->scaleChanged(); 3656 } 3657 3658 3659 /*! 3660 \since 4.6 3661 3662 Returns a list of graphics transforms that currently apply to this item. 3663 3664 QGraphicsTransform is for applying and controlling a chain of individual 3665 transformation operations on an item. It's particularily useful in 3666 animations, where each transform operation needs to be interpolated 3667 independently, or differently. 3668 3669 The transformations are combined with the item's rotation(), scale() and 3670 transform() to map the item's coordinate system to the parent item. 3671 3672 \sa scale(), rotation(), transformOriginPoint(), {Transformations} 3673 */ 3674 QList<QGraphicsTransform *> QGraphicsItem::transformations() const 3675 { 3676 if (!d_ptr->transformData) 3677 return QList<QGraphicsTransform *>(); 3678 return d_ptr->transformData->graphicsTransforms; 3679 } 3680 3681 /*! 3682 \since 4.6 3683 3684 Sets a list of graphics \a transformations (QGraphicsTransform) that 3685 currently apply to this item. 3686 3687 If all you want is to rotate or scale an item, you should call setRotation() 3688 or setScale() instead. If you want to set an arbitrary transformation on 3689 an item, you can call setTransform(). 3690 3691 QGraphicsTransform is for applying and controlling a chain of individual 3692 transformation operations on an item. It's particularily useful in 3693 animations, where each transform operation needs to be interpolated 3694 independently, or differently. 3695 3696 The transformations are combined with the item's rotation(), scale() and 3697 transform() to map the item's coordinate system to the parent item. 3698 3699 \sa scale(), setTransformOriginPoint(), {Transformations} 3700 */ 3701 void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transformations) 3702 { 3703 prepareGeometryChange(); 3704 if (!d_ptr->transformData) 3705 d_ptr->transformData = new QGraphicsItemPrivate::TransformData; 3706 d_ptr->transformData->graphicsTransforms = transformations; 3707 for (int i = 0; i < transformations.size(); ++i) 3708 transformations.at(i)->d_func()->setItem(this); 3709 d_ptr->transformData->onlyTransform = false; 3710 d_ptr->dirtySceneTransform = 1; 3711 } 3712 3713 /*! 3714 \internal 3715 */ 3716 void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t) 3717 { 3718 if (!transformData) 3719 transformData = new QGraphicsItemPrivate::TransformData; 3720 if (!transformData->graphicsTransforms.contains(t)) 3721 transformData->graphicsTransforms.append(t); 3722 3723 Q_Q(QGraphicsItem); 3724 t->d_func()->setItem(q); 3725 transformData->onlyTransform = false; 3726 dirtySceneTransform = 1; 3727 } 3728 3729 /*! 3730 \since 4.6 3731 3732 Returns the origin point for the transformation in item coordinates. 3733 3734 The default is QPointF(0,0). 3735 3736 \sa setTransformOriginPoint(), {Transformations} 3737 */ 3738 QPointF QGraphicsItem::transformOriginPoint() const 3739 { 3740 if (!d_ptr->transformData) 3741 return QPointF(0,0); 3742 return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin); 3743 } 3744 3745 /*! 3746 \since 4.6 3747 3748 Sets the \a origin point for the transformation in item coordinates. 3749 3750 \sa transformOriginPoint(), {Transformations} 3751 */ 3752 void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) 3753 { 3754 prepareGeometryChange(); 3755 if (!d_ptr->transformData) 3756 d_ptr->transformData = new QGraphicsItemPrivate::TransformData; 3757 d_ptr->transformData->xOrigin = origin.x(); 3758 d_ptr->transformData->yOrigin = origin.y(); 3759 d_ptr->transformData->onlyTransform = false; 3760 d_ptr->dirtySceneTransform = 1; 3761 } 3762 3763 /*! 3764 \fn void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y) 3765 3766 \since 4.6 3767 \overload 3768 3769 Sets the origin point for the transformation in item coordinates. 3770 This is equivalent to calling setTransformOriginPoint(QPointF(\a x, \a y)). 3771 3772 \sa setTransformOriginPoint(), {Transformations} 3773 */ 3774 2476 3775 2477 3776 /*! … … 2484 3783 QMatrix QGraphicsItem::sceneMatrix() const 2485 3784 { 2486 return sceneTransform().toAffine(); 3785 d_ptr->ensureSceneTransform(); 3786 return d_ptr->sceneTransform.toAffine(); 2487 3787 } 2488 3788 … … 2501 3801 2502 3802 Unlike transform(), which returns only an item's local transformation, this 2503 function includes the item's (and any parents') position .2504 2505 \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System} 3803 function includes the item's (and any parents') position, and all the transfomation properties. 3804 3805 \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations} 2506 3806 */ 2507 3807 QTransform QGraphicsItem::sceneTransform() const 2508 3808 { 2509 // Check if there's any entry in the transform cache. 2510 QGraphicsScenePrivate *sd = d_ptr->scene ? d_ptr->scene->d_func() : 0; 2511 int index = d_ptr->sceneTransformIndex; 2512 if (sd && index != -1 && sd->validTransforms.testBit(index)) 2513 return sd->sceneTransformCache[index]; 2514 2515 // Calculate local transform. 2516 QTransform m; 2517 if (d_ptr->hasTransform) { 2518 m = transform(); 2519 if (!d_ptr->pos.isNull()) 2520 m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()); 2521 } else if (!d_ptr->pos.isNull()) { 2522 m = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y()); 2523 } 2524 2525 // Combine with parent and add to cache. 2526 if (d_ptr->parent) { 2527 m *= d_ptr->parent->sceneTransform(); 2528 // Don't cache toplevels 2529 if (sd) { 2530 if (index == -1) { 2531 if (!sd->freeSceneTransformSlots.isEmpty()) { 2532 index = sd->freeSceneTransformSlots.last(); 2533 sd->freeSceneTransformSlots.pop_back(); 2534 } else { 2535 index = sd->sceneTransformCache.size(); 2536 } 2537 d_ptr->sceneTransformIndex = index; 2538 if (index >= sd->validTransforms.size()) { 2539 sd->validTransforms.resize(index + 1); 2540 sd->sceneTransformCache.resize(index + 1); 2541 } 2542 } 2543 sd->validTransforms.setBit(index, 1); 2544 sd->sceneTransformCache[index] = m; 2545 } 2546 } 2547 return m; 3809 d_ptr->ensureSceneTransform(); 3810 return d_ptr->sceneTransform; 2548 3811 } 2549 3812 … … 2573 3836 QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const 2574 3837 { 3838 // Ensure we return the standard transform if we're not untransformable. 3839 if (!d_ptr->itemIsUntransformable()) { 3840 d_ptr->ensureSceneTransform(); 3841 return d_ptr->sceneTransform * viewportTransform; 3842 } 3843 2575 3844 // Find the topmost item that ignores view transformations. 2576 3845 const QGraphicsItem *untransformedAncestor = this; … … 2590 3859 2591 3860 // First translate the base untransformable item. 2592 QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0)); 2593 QTransform matrix; 2594 matrix.translate(mappedPoint.x(), mappedPoint.y()); 2595 matrix = untransformedAncestor->transform() * matrix; 3861 untransformedAncestor->d_ptr->ensureSceneTransform(); 3862 QPointF mappedPoint = (untransformedAncestor->d_ptr->sceneTransform * viewportTransform).map(QPointF(0, 0)); 3863 3864 // COMBINE 3865 QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y()); 3866 if (untransformedAncestor->d_ptr->transformData) 3867 matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform(&matrix); 2596 3868 2597 3869 // Then transform and translate all children. 2598 3870 for (int i = 0; i < parents.size(); ++i) { 2599 3871 const QGraphicsItem *parent = parents.at(i); 2600 QPointF pos = parent->pos(); 2601 QTransform moveMatrix; 2602 moveMatrix.translate(pos.x(), pos.y()); 2603 matrix = (parent->transform() * moveMatrix) * matrix; 3872 parent->d_ptr->combineTransformFromParent(&matrix); 2604 3873 } 2605 3874 … … 2644 3913 if (ok) 2645 3914 *ok = true; 2646 const QPointF &itemPos = d_ptr->pos; 2647 if (itemPos.isNull()) 2648 return d_ptr->hasTransform ? transform() : QTransform(); 2649 if (d_ptr->hasTransform) 2650 return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y()); 2651 return QTransform::fromTranslate(itemPos.x(), itemPos.y()); 3915 QTransform x; 3916 d_ptr->combineTransformFromParent(&x); 3917 return x; 2652 3918 } 2653 3919 … … 2655 3921 if (otherParent == this) { 2656 3922 const QPointF &otherPos = other->d_ptr->pos; 2657 if (other->d_ptr->hasTransform) { 2658 QTransform otherToParent = other->transform(); 2659 if (!otherPos.isNull()) 2660 otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y()); 3923 if (other->d_ptr->transformData) { 3924 QTransform otherToParent; 3925 other->d_ptr->combineTransformFromParent(&otherToParent); 2661 3926 return otherToParent.inverted(ok); 2662 } else {2663 if (ok)2664 *ok = true;2665 return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());2666 3927 } 3928 if (ok) 3929 *ok = true; 3930 return QTransform::fromTranslate(-otherPos.x(), -otherPos.y()); 2667 3931 } 2668 3932 2669 3933 // Siblings 2670 3934 if (parent == otherParent) { 2671 bool hasTr = d_ptr->hasTransform; 2672 bool otherHasTr = other->d_ptr->hasTransform; 3935 // COMBINE 2673 3936 const QPointF &itemPos = d_ptr->pos; 2674 3937 const QPointF &otherPos = other->d_ptr->pos; 2675 2676 if (!hasTr && !otherHasTr) { 3938 if (!d_ptr->transformData && !other->d_ptr->transformData) { 2677 3939 QPointF delta = itemPos - otherPos; 2678 3940 if (ok) … … 2681 3943 } 2682 3944 2683 QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y()); 2684 if (hasTr) 2685 itemToParent = itemPos.isNull() ? transform() : transform() * itemToParent; 2686 2687 QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y()); 2688 if (otherHasTr) 2689 otherToParent = otherPos.isNull() ? other->transform() : other->transform() * otherToParent; 2690 3945 QTransform itemToParent; 3946 d_ptr->combineTransformFromParent(&itemToParent); 3947 QTransform otherToParent; 3948 other->d_ptr->combineTransformFromParent(&otherToParent); 2691 3949 return itemToParent * otherToParent.inverted(ok); 2692 3950 } … … 2695 3953 // ancestor, then the only way is to combine their scene transforms. 2696 3954 const QGraphicsItem *commonAncestor = commonAncestorItem(other); 2697 if (!commonAncestor) 2698 return sceneTransform() * other->sceneTransform().inverted(ok); 3955 if (!commonAncestor) { 3956 d_ptr->ensureSceneTransform(); 3957 other->d_ptr->ensureSceneTransform(); 3958 return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok); 3959 } 2699 3960 2700 3961 // If the two items are cousins (in sibling branches), map both to the … … 2703 3964 if (cousins) { 2704 3965 bool good = false; 2705 QTransform thisToScene; 2706 QTransform otherToScene; 2707 thisToScene = itemTransform(commonAncestor, &good); 3966 QTransform thisToScene = itemTransform(commonAncestor, &good); 3967 QTransform otherToScene(Qt::Uninitialized); 2708 3968 if (good) 2709 3969 otherToScene = other->itemTransform(commonAncestor, &good); … … 2724 3984 const QGraphicsItem *p = child; 2725 3985 do { 2726 const QGraphicsItemPrivate *pd = p->d_ptr; 2727 if (pd->hasTransform) 2728 x *= p->transform(); 2729 if (!pd->pos.isNull()) 2730 x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y()); 3986 p->d_ptr.data()->combineTransformToParent(&x); 2731 3987 } while ((p = p->d_ptr->parent) && p != root); 2732 3988 if (parentOfOther) … … 2746 4002 Use setTransform() instead. 2747 4003 2748 \sa transform(), rotate(), scale(), shear(), translate(),{The Graphics View Coordinate System}4004 \sa transform(), {The Graphics View Coordinate System} 2749 4005 */ 2750 4006 void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) 2751 4007 { 2752 QTransform oldTransform = this->transform(); 2753 QTransform newTransform; 2754 if (!combine) 2755 newTransform = QTransform(matrix); 2756 else 2757 newTransform = QTransform(matrix) * oldTransform; 2758 if (oldTransform == newTransform) 4008 if (!d_ptr->transformData) 4009 d_ptr->transformData = new QGraphicsItemPrivate::TransformData; 4010 4011 QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix)); 4012 if (d_ptr->transformData->transform == newTransform) 2759 4013 return; 2760 4014 2761 // Notify the item that the matrix is changing. 2762 QVariant newTransformVariant(itemChange(ItemMatrixChange, 2763 qVariantFromValue<QMatrix>(newTransform.toAffine()))); 2764 newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant)); 2765 if (oldTransform == newTransform) 4015 // Update and set the new transformation. 4016 if (!(d_ptr->flags & ItemSendsGeometryChanges)) { 4017 d_ptr->setTransformHelper(newTransform); 2766 4018 return; 4019 } 4020 4021 // Notify the item that the transformation matrix is changing. 4022 const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine()); 4023 newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); 4024 if (d_ptr->transformData->transform == newTransform) 4025 return; 2767 4026 2768 4027 // Update and set the new transformation. 2769 d_ptr->fullUpdateHelper(true, true); 2770 prepareGeometryChange(); 2771 d_ptr->hasTransform = !newTransform.isIdentity(); 2772 d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); 2773 d_ptr->invalidateSceneTransformCache(); 4028 d_ptr->setTransformHelper(newTransform); 2774 4029 2775 4030 // Send post-notification. 2776 // NB! We have to change the value from QMatrix to QTransform. 2777 qVariantSetValue<QTransform>(newTransformVariant, newTransform); 2778 itemChange(ItemTransformHasChanged, newTransformVariant); 4031 itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform)); 2779 4032 } 2780 4033 … … 2794 4047 from scene coordinates to item coordinates. 2795 4048 2796 \sa transform(), rotate(), scale(), shear(), translate(), {The Graphics View Coordinate System} 4049 The transformation matrix is combined with the item's rotation(), scale() 4050 and transformations() into a combined transformation that maps the item's 4051 coordinate system to its parent. 4052 4053 \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations} 2797 4054 */ 2798 4055 void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) 2799 4056 { 2800 QTransform oldTransform = this->transform(); 2801 QTransform newTransform; 2802 if (!combine) 2803 newTransform = matrix; 2804 else 2805 newTransform = matrix * oldTransform; 2806 if (oldTransform == newTransform) 4057 if (!d_ptr->transformData) 4058 d_ptr->transformData = new QGraphicsItemPrivate::TransformData; 4059 4060 QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix); 4061 if (d_ptr->transformData->transform == newTransform) 2807 4062 return; 4063 4064 // Update and set the new transformation. 4065 if (!(d_ptr->flags & ItemSendsGeometryChanges)) { 4066 d_ptr->setTransformHelper(newTransform); 4067 return; 4068 } 2808 4069 2809 4070 // Notify the item that the transformation matrix is changing. … … 2811 4072 qVariantFromValue<QTransform>(newTransform))); 2812 4073 newTransform = qVariantValue<QTransform>(newTransformVariant); 2813 if ( oldTransform == newTransform)4074 if (d_ptr->transformData->transform == newTransform) 2814 4075 return; 2815 4076 2816 4077 // Update and set the new transformation. 2817 d_ptr->fullUpdateHelper(true, true); 2818 prepareGeometryChange(); 2819 d_ptr->hasTransform = !newTransform.isIdentity(); 2820 d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform); 2821 d_ptr->invalidateSceneTransformCache(); 4078 d_ptr->setTransformHelper(newTransform); 2822 4079 2823 4080 // Send post-notification. 2824 4081 itemChange(ItemTransformHasChanged, newTransformVariant); 4082 d_ptr->sendScenePosChange(); 2825 4083 } 2826 4084 … … 2838 4096 \since 4.3 2839 4097 2840 Resets this item's transformation matrix to the identity matrix. This is 2841 equivalent to calling \c setTransform(QTransform()). 4098 Resets this item's transformation matrix to the identity matrix or 4099 all the transformation properties to their default values. 4100 This is equivalent to calling \c setTransform(QTransform()). 2842 4101 2843 4102 \sa setTransform(), transform() … … 2849 4108 2850 4109 /*! 4110 \obsolete 4111 4112 Use 4113 4114 \code 4115 setRotation(rotation() + angle); 4116 \endcode 4117 4118 instead. 4119 2851 4120 Rotates the current item transformation \a angle degrees clockwise around 2852 4121 its origin. To translate around an arbitrary point (x, y), you need to … … 2865 4134 2866 4135 /*! 4136 \obsolete 4137 4138 Use 4139 4140 \code 4141 setTransform(QTransform::fromScale(sx, sy), true); 4142 \endcode 4143 4144 instead. 4145 2867 4146 Scales the current item transformation by (\a sx, \a sy) around its 2868 4147 origin. To scale from an arbitrary point (x, y), you need to combine … … 2873 4152 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7 2874 4153 2875 \sa setTransform(), transform() , rotate(), shear(), translate()4154 \sa setTransform(), transform() 2876 4155 */ 2877 4156 void QGraphicsItem::scale(qreal sx, qreal sy) … … 2881 4160 2882 4161 /*! 4162 \obsolete 4163 4164 Use 4165 4166 \code 4167 setTransform(QTransform().shear(sh, sv), true); 4168 \endcode 4169 4170 instead. 4171 2883 4172 Shears the current item transformation by (\a sh, \a sv). 2884 4173 2885 \sa setTransform(), transform() , rotate(), scale(), translate()4174 \sa setTransform(), transform() 2886 4175 */ 2887 4176 void QGraphicsItem::shear(qreal sh, qreal sv) … … 2891 4180 2892 4181 /*! 4182 \obsolete 4183 4184 Use setPos() or setTransformOriginPoint() instead. For identical 4185 behavior, use 4186 4187 \code 4188 setTransform(QTransform::fromTranslate(dx, dy), true); 4189 \endcode 4190 2893 4191 Translates the current item transformation by (\a dx, \a dy). 2894 4192 … … 2897 4195 which is conceptually separate from its position. 2898 4196 2899 \sa setTransform(), transform() , rotate(), scale(), shear()4197 \sa setTransform(), transform() 2900 4198 */ 2901 4199 void QGraphicsItem::translate(qreal dx, qreal dy) … … 2927 4225 2928 4226 /*! 2929 Returns the Z-value , or the elevation, of the item. The Z-value decides2930 the stacking order ofsibling (neighboring) items.4227 Returns the Z-value of the item. The Z-value affects the stacking order of 4228 sibling (neighboring) items. 2931 4229 2932 4230 The default Z-value is 0. 2933 4231 2934 \sa setZValue() 4232 \sa setZValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent 2935 4233 */ 2936 4234 qreal QGraphicsItem::zValue() const … … 2940 4238 2941 4239 /*! 2942 Sets the Z-value, or the elevation, of the item, to \a z. The elevation 2943 decides the stacking order of sibling (neighboring) items. An item of high 2944 Z-value will be drawn on top of an item with a lower Z-value if they 2945 share the same parent item. In addition, children of an item will always be drawn 2946 on top of the parent, regardless of the child's Z-value. Sibling items 2947 that share the same Z-value will be drawn in an undefined order, although 2948 the order will stay the same for as long as the items live. 2949 2950 \img graphicsview-zorder.png 2951 2952 Children of different parents are stacked according to the Z-value of 2953 each item's ancestor item which is an immediate child of the two 2954 items' closest common ancestor. For example, a robot item might 2955 define a torso item as the parent of a head item, two arm items, 2956 and two upper-leg items. The upper-leg items would each be parents 2957 of one lower-leg item, and each lower-leg item would be parents of 2958 one foot item. The stacking order of the feet is the same as the 2959 stacking order of each foot's ancestor that is an immediate child 2960 of the two feet's common ancestor (i.e., the torso item); so the 2961 feet are stacked in the same order as the upper-leg items, 2962 regardless of each foot's Z-value. 4240 Sets the Z-value of the item to \a z. The Z value decides the stacking 4241 order of sibling (neighboring) items. A sibling item of high Z value will 4242 always be drawn on top of another sibling item with a lower Z value. 4243 4244 If you restore the Z value, the item's insertion order will decide its 4245 stacking order. 2963 4246 2964 4247 The Z-value does not affect the item's size in any way. … … 2966 4249 The default Z-value is 0. 2967 4250 2968 \sa zValue() 4251 \sa zValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent 2969 4252 */ 2970 4253 void QGraphicsItem::setZValue(qreal z) 2971 4254 { 2972 const QVariant newZVariant(itemChange(ItemZValueChange, double(z)));2973 qreal newZ = qreal(newZVariant.toDouble());4255 const QVariant newZVariant(itemChange(ItemZValueChange, z)); 4256 qreal newZ = newZVariant.toReal(); 2974 4257 if (newZ == d_ptr->z) 2975 4258 return; 2976 d_ptr->z = z;2977 d_ptr->fullUpdateHelper();2978 4259 2979 4260 if (d_ptr->scene) { 2980 // Invalidate any sort caching; arrival of a new item means we need to 2981 // resort. 2982 d_ptr->scene->d_func()->invalidateSortCache(); 2983 } 4261 // Z Value has changed, we have to notify the index. 4262 d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant); 4263 } 4264 4265 d_ptr->z = newZ; 4266 if (d_ptr->parent) 4267 d_ptr->parent->d_ptr->needSortChildren = 1; 4268 else if (d_ptr->scene) 4269 d_ptr->scene->d_func()->needSortTopLevelItems = 1; 4270 4271 if (d_ptr->scene) 4272 d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); 2984 4273 2985 4274 itemChange(ItemZValueHasChanged, newZVariant); 4275 4276 if (d_ptr->flags & ItemNegativeZStacksBehindParent) 4277 setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0)); 4278 4279 if (d_ptr->isObject) 4280 emit static_cast<QGraphicsObject *>(this)->zChanged(); 4281 } 4282 4283 /*! 4284 \internal 4285 4286 Ensures that the list of children is sorted by insertion order, and that 4287 the siblingIndexes are packed (no gaps), and start at 0. 4288 4289 ### This function is almost identical to 4290 QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes(). 4291 */ 4292 void QGraphicsItemPrivate::ensureSequentialSiblingIndex() 4293 { 4294 if (!sequentialOrdering) { 4295 qSort(children.begin(), children.end(), insertionOrder); 4296 sequentialOrdering = 1; 4297 needSortChildren = 1; 4298 } 4299 if (holesInSiblingIndex) { 4300 holesInSiblingIndex = 0; 4301 for (int i = 0; i < children.size(); ++i) 4302 children[i]->d_ptr->siblingIndex = i; 4303 } 4304 } 4305 4306 /*! 4307 \internal 4308 */ 4309 inline void QGraphicsItemPrivate::sendScenePosChange() 4310 { 4311 Q_Q(QGraphicsItem); 4312 if (scene) { 4313 if (flags & QGraphicsItem::ItemSendsScenePositionChanges) 4314 q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos()); 4315 if (scenePosDescendants) { 4316 foreach (QGraphicsItem *item, scene->d_func()->scenePosItems) { 4317 if (q->isAncestorOf(item)) 4318 item->itemChange(QGraphicsItem::ItemScenePositionHasChanged, item->scenePos()); 4319 } 4320 } 4321 } 4322 } 4323 4324 /*! 4325 \since 4.6 4326 4327 Stacks this item before \a sibling, which must be a sibling item (i.e., the 4328 two items must share the same parent item, or must both be toplevel items). 4329 The \a sibling must have the same Z value as this item, otherwise calling 4330 this function will have no effect. 4331 4332 By default, all sibling items are stacked by insertion order (i.e., the 4333 first item you add is drawn before the next item you add). If two items' Z 4334 values are different, then the item with the highest Z value is drawn on 4335 top. When the Z values are the same, the insertion order will decide the 4336 stacking order. 4337 4338 \sa setZValue(), ItemStacksBehindParent, {QGraphicsItem#Sorting}{Sorting} 4339 */ 4340 void QGraphicsItem::stackBefore(const QGraphicsItem *sibling) 4341 { 4342 if (sibling == this) 4343 return; 4344 if (!sibling || d_ptr->parent != sibling->parentItem()) { 4345 qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); 4346 return; 4347 } 4348 QList<QGraphicsItem *> *siblings = d_ptr->parent 4349 ? &d_ptr->parent->d_ptr->children 4350 : (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : 0); 4351 if (!siblings) { 4352 qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); 4353 return; 4354 } 4355 4356 // First, make sure that the sibling indexes have no holes. This also 4357 // marks the children list for sorting. 4358 if (d_ptr->parent) 4359 d_ptr->parent->d_ptr->ensureSequentialSiblingIndex(); 4360 else 4361 d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes(); 4362 4363 // Only move items with the same Z value, and that need moving. 4364 int siblingIndex = sibling->d_ptr->siblingIndex; 4365 int myIndex = d_ptr->siblingIndex; 4366 if (myIndex >= siblingIndex) { 4367 siblings->move(myIndex, siblingIndex); 4368 // Fixup the insertion ordering. 4369 for (int i = 0; i < siblings->size(); ++i) { 4370 int &index = siblings->at(i)->d_ptr->siblingIndex; 4371 if (i != siblingIndex && index >= siblingIndex && index <= myIndex) 4372 ++index; 4373 } 4374 d_ptr->siblingIndex = siblingIndex; 4375 for (int i = 0; i < siblings->size(); ++i) { 4376 int &index = siblings->at(i)->d_ptr->siblingIndex; 4377 if (i != siblingIndex && index >= siblingIndex && index <= myIndex) 4378 siblings->at(i)->d_ptr->siblingOrderChange(); 4379 } 4380 d_ptr->siblingOrderChange(); 4381 } 2986 4382 } 2987 4383 … … 3005 4401 QRectF QGraphicsItem::childrenBoundingRect() const 3006 4402 { 3007 QRectF childRect; 3008 foreach (QGraphicsItem *child, children()) { 3009 QPointF childPos = child->pos(); 3010 QTransform matrix = child->transform(); 3011 if (!childPos.isNull()) 3012 matrix *= QTransform::fromTranslate(childPos.x(), childPos.y()); 3013 childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect()); 3014 } 3015 return childRect; 4403 if (!d_ptr->dirtyChildrenBoundingRect) 4404 return d_ptr->childrenBoundingRect; 4405 4406 d_ptr->childrenBoundingRect = QRectF(); 4407 d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect); 4408 d_ptr->dirtyChildrenBoundingRect = 0; 4409 return d_ptr->childrenBoundingRect; 3016 4410 } 3017 4411 … … 3026 4420 Although the item's shape can be arbitrary, the bounding rect is 3027 4421 always rectangular, and it is unaffected by the items' 3028 transformation (scale(), rotate(), etc.).4422 transformation. 3029 4423 3030 4424 If you want to change the item's bounding rectangle, you must first call … … 3058 4452 { 3059 4453 // Find translate-only offset 4454 // COMBINE 3060 4455 QPointF offset; 3061 4456 const QGraphicsItem *parentItem = this; 3062 4457 const QGraphicsItemPrivate *itemd; 3063 4458 do { 3064 itemd = parentItem->d_ptr ;3065 if (itemd-> hasTransform)4459 itemd = parentItem->d_ptr.data(); 4460 if (itemd->transformData) 3066 4461 break; 3067 4462 offset += itemd->pos; … … 3070 4465 QRectF br = boundingRect(); 3071 4466 br.translate(offset); 3072 return !parentItem ? br : parentItem->sceneTransform().mapRect(br); 4467 if (!parentItem) 4468 return br; 4469 if (parentItem->d_ptr->hasTranslateOnlySceneTransform()) { 4470 br.translate(parentItem->d_ptr->sceneTransform.dx(), parentItem->d_ptr->sceneTransform.dy()); 4471 return br; 4472 } 4473 return parentItem->d_ptr->sceneTransform.mapRect(br); 3073 4474 } 3074 4475 … … 3142 4543 { 3143 4544 Q_D(const QGraphicsItem); 3144 if (!d->dirtyClipPath) 3145 return d->emptyClipPath ? QPainterPath() : d->cachedClipPath; 3146 3147 if (!isClipped()) { 3148 d_ptr->setCachedClipPath(QPainterPath()); 3149 return d->cachedClipPath; 3150 } 4545 if (!isClipped()) 4546 return QPainterPath(); 3151 4547 3152 4548 const QRectF thisBoundingRect(boundingRect()); 3153 if (thisBoundingRect.isEmpty()) { 3154 if (d_ptr->flags & ItemClipsChildrenToShape) 3155 d_ptr->setEmptyCachedClipPathRecursively(); 3156 else 3157 d_ptr->setEmptyCachedClipPath(); 4549 if (thisBoundingRect.isEmpty()) 3158 4550 return QPainterPath(); 3159 }3160 4551 3161 4552 QPainterPath clip; … … 3168 4559 3169 4560 // Intersect any in-between clips starting at the top and moving downwards. 3170 bool foundValidClipPath = false;3171 4561 while ((parent = parent->d_ptr->parent)) { 3172 4562 if (parent->d_ptr->flags & ItemClipsChildrenToShape) { 3173 4563 // Map clip to the current parent and intersect with its shape/clipPath 3174 4564 clip = lastParent->itemTransform(parent).map(clip); 3175 if ((foundValidClipPath = !parent->d_ptr->dirtyClipPath && parent->isClipped())) { 3176 if (parent->d_ptr->emptyClipPath) { 3177 if (d_ptr->flags & ItemClipsChildrenToShape) 3178 d_ptr->setEmptyCachedClipPathRecursively(); 3179 else 3180 d_ptr->setEmptyCachedClipPath(); 3181 return QPainterPath(); 3182 } 3183 clip = clip.intersected(parent->d_ptr->cachedClipPath); 3184 if (!(parent->d_ptr->flags & ItemClipsToShape)) 3185 clip = clip.intersected(parent->shape()); 3186 } else { 3187 clip = clip.intersected(parent->shape()); 3188 } 3189 3190 if (clip.isEmpty()) { 3191 if (d_ptr->flags & ItemClipsChildrenToShape) 3192 d_ptr->setEmptyCachedClipPathRecursively(); 3193 else 3194 d_ptr->setEmptyCachedClipPath(); 4565 clip = clip.intersected(parent->shape()); 4566 if (clip.isEmpty()) 3195 4567 return clip; 3196 }3197 4568 lastParent = parent; 3198 4569 } 3199 4570 3200 if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) 3201 || foundValidClipPath) { 4571 if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) 3202 4572 break; 3203 }3204 4573 } 3205 4574 … … 3214 4583 clip = clip.intersected(shape()); 3215 4584 3216 d_ptr->setCachedClipPath(clip);3217 4585 return clip; 3218 4586 } … … 3236 4604 3237 4605 /*! 3238 Returns true if this item collides with \a other; otherwise returns false. 3239 The ways items collide is determined by \a mode. The default value for \a 3240 mode is Qt::IntersectsItemShape; \a other collides with this item if it 3241 either intersects, contains, or is contained by this item's shape. 4606 4607 Returns true if this item collides with \a other; otherwise 4608 returns false. 4609 4610 The \a mode is applied to \a other, and the resulting shape or 4611 bounding rectangle is then compared to this item's shape. The 4612 default value for \a mode is Qt::IntersectsItemShape; \a other 4613 collides with this item if it either intersects, contains, or is 4614 contained by this item's shape (see Qt::ItemSelectionMode for 4615 details). 3242 4616 3243 4617 The default implementation is based on shape intersection, and it calls … … 3294 4668 intersects, contains, or is contained by this item's shape. 3295 4669 4670 Note that this function checks whether the item's shape or 4671 bounding rectangle (depending on \a mode) is contained within \a 4672 path, and not whether \a path is contained within the items shape 4673 or bounding rectangle. 4674 3296 4675 \sa collidesWithItem(), contains(), shape() 3297 4676 */ … … 3334 4713 Returns a list of all items that collide with this item. 3335 4714 3336 The way collisions are detected is determined by \a mode. The default 3337 value for \a mode is Qt::IntersectsItemShape; All items whose shape 3338 intersects or is contained by this item's shape are returned. 3339 3340 \sa QGraphicsScene::collidingItems(), collidesWithItem() 4715 The way collisions are detected is determined by applying \a mode 4716 to items that are compared to this item, i.e., each item's shape 4717 or bounding rectangle is checked against this item's shape. The 4718 default value for \a mode is Qt::IntersectsItemShape. 4719 4720 \sa collidesWithItem() 3341 4721 */ 3342 4722 QList<QGraphicsItem *> QGraphicsItem::collidingItems(Qt::ItemSelectionMode mode) const … … 3433 4813 if (!item) 3434 4814 return false; 3435 return QGraphicsScenePrivate::closestItemFirst_withoutCache(item, this)4815 return qt_closestItemFirst(item, this) 3436 4816 && qt_QGraphicsItem_isObscured(this, item, boundingRect()); 3437 4817 } … … 3518 4898 3519 4899 // Transform QRegion back to device space 3520 QTransform unscale; 3521 unscale.scale(1 / granularity, 1 / granularity); 4900 QTransform unscale = QTransform::fromScale(1 / granularity, 1 / granularity); 3522 4901 QRegion r; 3523 4902 QBitmap colorMask = QBitmap::fromImage(mask.createMaskFromColor(0)); … … 3615 4994 All painting is done in local coordinates. 3616 4995 3617 \sa setCacheMode(), QPen::width(), {Item Coordinates} 4996 \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption 3618 4997 */ 3619 4998 … … 3622 5001 Returns true if we can discard an update request; otherwise false. 3623 5002 */ 3624 bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, 3625 bool ignoreVisibleBit, 3626 bool ignoreDirtyBit) const 5003 bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreVisibleBit, bool ignoreDirtyBit, 5004 bool ignoreOpacity) const 3627 5005 { 3628 5006 // No scene, or if the scene is updating everything, means we have nothing 3629 5007 // to do. The only exception is if the scene tracks the growing scene rect. 3630 return (!visible && !ignoreVisibleBit) 3631 || (dirty && !ignoreDirtyBit) 3632 || !scene 3633 || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect) 3634 || (!ignoreClipping && (childrenClippedToShape() && isClippedAway())) 3635 || (childrenCombineOpacity() && isFullyTransparent()); 5008 return !scene 5009 || (!visible && !ignoreVisibleBit && !this->ignoreVisible) 5010 || (!ignoreDirtyBit && fullUpdatePending) 5011 || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); 3636 5012 } 3637 5013 3638 5014 /*! 3639 5015 \internal 3640 3641 Asks the scene to mark this item's scene rect as dirty, requesting a 3642 redraw. This does not invalidate any cache. 3643 3644 The \a force argument is for the update call in setVisible(), which is the 3645 only case where the item's background should be marked as dirty even when 3646 the item isn't visible. 3647 */ 3648 void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool maybeDirtyClipPath) 3649 { 3650 // No scene, or if the scene is updating everything, means we have nothing 3651 // to do. The only exception is if the scene tracks the growing scene rect. 3652 if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force)) 5016 */ 5017 int QGraphicsItemPrivate::depth() const 5018 { 5019 if (itemDepth == -1) 5020 const_cast<QGraphicsItemPrivate *>(this)->resolveDepth(); 5021 5022 return itemDepth; 5023 } 5024 5025 /*! 5026 \internal 5027 */ 5028 #ifndef QT_NO_GRAPHICSEFFECT 5029 void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() 5030 { 5031 QGraphicsItemPrivate *itemPrivate = this; 5032 do { 5033 if (itemPrivate->graphicsEffect) { 5034 itemPrivate->notifyInvalidated = 1; 5035 5036 if (!itemPrivate->updateDueToGraphicsEffect) 5037 static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache(); 5038 } 5039 } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); 5040 } 5041 #endif //QT_NO_GRAPHICSEFFECT 5042 5043 /*! 5044 \internal 5045 */ 5046 void QGraphicsItemPrivate::invalidateDepthRecursively() 5047 { 5048 if (itemDepth == -1) 3653 5049 return; 3654 5050 3655 i f (rect.isNull())3656 dirty = 1;3657 scene->itemUpdated(q_ptr, rect);5051 itemDepth = -1; 5052 for (int i = 0; i < children.size(); ++i) 5053 children.at(i)->d_ptr->invalidateDepthRecursively(); 3658 5054 } 3659 5055 … … 3661 5057 \internal 3662 5058 3663 Propagates updates to \a item and all its children. 3664 */ 3665 void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath) 3666 { 3667 if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, 3668 /*ignoreVisibleBit=*/false, 3669 /*ignoreDirtyBit=*/true)) { 3670 return; 3671 } 3672 3673 if (!childrenOnly && !dirty) { 3674 // Effectively the same as updateHelper(QRectF(), false, maybeDirtyClipPath). 3675 dirty = 1; 3676 scene->itemUpdated(q_ptr, QRectF()); 3677 } 3678 3679 if (dirtyChildren || childrenClippedToShape()) { 3680 // Unnecessary to update children as well. 3681 return; 3682 } 3683 3684 if (ancestorFlags & AncestorClipsChildren) { 3685 Q_Q(QGraphicsItem); 3686 // Check if we can avoid updating all children. 3687 QGraphicsItem *p = parent; 3688 QRectF br = q->boundingRect(); 3689 while (p) { 3690 if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) { 3691 bool ok; 3692 QTransform x = q->itemTransform(p, &ok); 3693 if (!ok) 3694 break; 3695 if (x.mapRect(br).contains(p->boundingRect())) 3696 return; 3697 } 3698 p = p->d_ptr->parent; 3699 if (!p || !(p->d_ptr->ancestorFlags & AncestorClipsChildren)) 3700 break; 3701 // ### check one level only 3702 break; 3703 } 3704 } 3705 foreach (QGraphicsItem *child, children) 3706 child->d_ptr->fullUpdateHelper(false, maybeDirtyClipPath); 3707 dirtyChildren = 1; 3708 } 3709 3710 static inline bool qt_allChildrenCombineOpacity(QGraphicsItem *parent) 3711 { 3712 Q_ASSERT(parent); 3713 if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) 3714 return false; 3715 3716 const QList<QGraphicsItem *> children(parent->childItems()); 3717 for (int i = 0; i < children.size(); ++i) { 3718 if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity) 3719 return false; 3720 } 3721 return true; 3722 } 3723 3724 void QGraphicsItemPrivate::updateEffectiveOpacity() 3725 { 3726 Q_Q(QGraphicsItem); 3727 if (parent) { 3728 resolveEffectiveOpacity(parent->effectiveOpacity()); 3729 parent->d_ptr->allChildrenCombineOpacity = qt_allChildrenCombineOpacity(parent); 3730 } else { 3731 resolveEffectiveOpacity(1.0); 3732 } 3733 allChildrenCombineOpacity = qt_allChildrenCombineOpacity(q); 5059 Resolves the stacking depth of this object and all its ancestors. 5060 */ 5061 void QGraphicsItemPrivate::resolveDepth() 5062 { 5063 if (!parent) 5064 itemDepth = 0; 5065 else { 5066 if (parent->d_ptr->itemDepth == -1) 5067 parent->d_ptr->resolveDepth(); 5068 itemDepth = parent->d_ptr->itemDepth + 1; 5069 } 3734 5070 } 3735 5071 … … 3737 5073 \internal 3738 5074 3739 Resolves and propagates this item's effective opacity to its children. 3740 */ 3741 void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity) 3742 { 3743 Q_Q(QGraphicsItem); 3744 QGraphicsItem::GraphicsItemFlags myFlags = q->flags(); 3745 QGraphicsItem::GraphicsItemFlags parentFlags = parent ? parent->flags() : QGraphicsItem::GraphicsItemFlags(0); 3746 3747 // My local opacity is always part of my effective opacity. 3748 qreal myEffectiveOpacity = q->opacity(); 3749 3750 // If I have a parent, and I don't ignore my parent's opacity, and my 3751 // parent propagates to me, then combine my local opacity with my parent's 3752 // effective opacity into my effective opacity. 3753 if (parent 3754 && !(myFlags & QGraphicsItem::ItemIgnoresParentOpacity) 3755 && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { 3756 myEffectiveOpacity *= parentEffectiveOpacity; 3757 } 3758 3759 // Set this item's resolved opacity. 3760 if (qFuzzyCompare(myEffectiveOpacity, qreal(1.0))) { 3761 // Opaque, unset effective opacity. 3762 hasEffectiveOpacity = 0; 3763 unsetExtra(ExtraEffectiveOpacity); 3764 } else { 3765 hasEffectiveOpacity = 1; 3766 setExtra(ExtraEffectiveOpacity, myEffectiveOpacity); 3767 } 3768 3769 // Resolve children always. 3770 for (int i = 0; i < children.size(); ++i) 3771 children.at(i)->d_ptr->resolveEffectiveOpacity(myEffectiveOpacity); 5075 ### This function is almost identical to 5076 QGraphicsScenePrivate::registerTopLevelItem(). 5077 */ 5078 void QGraphicsItemPrivate::addChild(QGraphicsItem *child) 5079 { 5080 // Remove all holes from the sibling index list. Now the max index 5081 // number is equal to the size of the children list. 5082 ensureSequentialSiblingIndex(); 5083 needSortChildren = 1; // ### maybe 0 5084 child->d_ptr->siblingIndex = children.size(); 5085 children.append(child); 3772 5086 } 3773 5087 … … 3775 5089 \internal 3776 5090 3777 Resolves the stacking depth of this object and all its children. 3778 */ 3779 void QGraphicsItemPrivate::resolveDepth(int parentDepth) 3780 { 3781 depth = parentDepth + 1; 3782 for (int i = 0; i < children.size(); ++i) 3783 children.at(i)->d_ptr->resolveDepth(depth); 5091 ### This function is almost identical to 5092 QGraphicsScenePrivate::unregisterTopLevelItem(). 5093 */ 5094 void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) 5095 { 5096 // When removing elements in the middle of the children list, 5097 // there will be a "gap" in the list of sibling indexes (0,1,3,4). 5098 if (!holesInSiblingIndex) 5099 holesInSiblingIndex = child->d_ptr->siblingIndex != children.size() - 1; 5100 if (sequentialOrdering && !holesInSiblingIndex) 5101 children.removeAt(child->d_ptr->siblingIndex); 5102 else 5103 children.removeOne(child); 5104 // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because 5105 // the child is not guaranteed to be at the index after the list is sorted. 5106 // (see ensureSortedChildren()). 5107 child->d_ptr->siblingIndex = -1; 3784 5108 } 3785 5109 … … 3787 5111 \internal 3788 5112 */ 3789 void QGraphicsItemPrivate::invalidateSceneTransformCache() 3790 { 3791 if (!scene || (parent && sceneTransformIndex == -1)) 3792 return; 3793 if (sceneTransformIndex != -1) 3794 scene->d_func()->validTransforms.setBit(sceneTransformIndex, 0); 3795 for (int i = 0; i < children.size(); ++i) 3796 children.at(i)->d_ptr->invalidateSceneTransformCache(); 3797 } 3798 5113 QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const 5114 { 5115 return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); 5116 } 5117 5118 /*! 5119 \internal 5120 */ 3799 5121 QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const 3800 5122 { … … 3808 5130 } 3809 5131 5132 /*! 5133 \internal 5134 */ 3810 5135 void QGraphicsItemPrivate::removeExtraItemCache() 3811 5136 { … … 3818 5143 } 3819 5144 3820 void QGraphicsItemPrivate::setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect) 3821 { 3822 setEmptyCachedClipPath(); 3823 3824 const bool checkRect = !emptyIfOutsideThisRect.isNull() 3825 && !(flags & QGraphicsItem::ItemClipsChildrenToShape); 3826 for (int i = 0; i < children.size(); ++i) { 3827 if (!checkRect) { 3828 children.at(i)->d_ptr->setEmptyCachedClipPathRecursively(); 3829 continue; 5145 // Traverses all the ancestors up to the top-level and updates the pointer to 5146 // always point to the top-most item that has a dirty scene transform. 5147 // It then backtracks to the top-most dirty item and start calculating the 5148 // scene transform by combining the item's transform (+pos) with the parent's 5149 // cached scene transform (which we at this point know for sure is valid). 5150 void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem) 5151 { 5152 Q_ASSERT(topMostDirtyItem); 5153 5154 if (dirtySceneTransform) 5155 *topMostDirtyItem = q_ptr; 5156 5157 if (parent) 5158 parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem); 5159 5160 if (*topMostDirtyItem == q_ptr) { 5161 if (!dirtySceneTransform) 5162 return; // OK, neither my ancestors nor I have dirty scene transforms. 5163 *topMostDirtyItem = 0; 5164 } else if (*topMostDirtyItem) { 5165 return; // Continue backtrack. 5166 } 5167 5168 // This item and all its descendants have dirty scene transforms. 5169 // We're about to validate this item's scene transform, so we have to 5170 // invalidate all the children; otherwise there's no way for the descendants 5171 // to detect that the ancestor has changed. 5172 invalidateChildrenSceneTransform(); 5173 5174 // COMBINE my transform with the parent's scene transform. 5175 updateSceneTransformFromParent(); 5176 Q_ASSERT(!dirtySceneTransform); 5177 } 5178 5179 /*! 5180 \internal 5181 */ 5182 void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem) 5183 { 5184 // Update focus child chain. Stop at panels, or if this item 5185 // is hidden, stop at the first item with a visible parent. 5186 QGraphicsItem *parent = rootItem ? rootItem : q_ptr; 5187 do { 5188 // Clear any existing ancestor's subFocusItem. 5189 if (parent != q_ptr && parent->d_ptr->subFocusItem) { 5190 if (parent->d_ptr->subFocusItem == q_ptr) 5191 break; 5192 parent->d_ptr->subFocusItem->d_ptr->clearSubFocus(); 3830 5193 } 3831 3832 QGraphicsItem *child = children.at(i); 3833 const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect); 3834 if (rect.intersects(child->boundingRect())) 3835 child->d_ptr->invalidateCachedClipPathRecursively(false, rect); 3836 else 3837 child->d_ptr->setEmptyCachedClipPathRecursively(rect); 3838 } 3839 } 3840 3841 void QGraphicsItemPrivate::invalidateCachedClipPathRecursively(bool childrenOnly, const QRectF &emptyIfOutsideThisRect) 3842 { 3843 if (!childrenOnly) 3844 invalidateCachedClipPath(); 3845 3846 const bool checkRect = !emptyIfOutsideThisRect.isNull(); 3847 for (int i = 0; i < children.size(); ++i) { 3848 if (!checkRect) { 3849 children.at(i)->d_ptr->invalidateCachedClipPathRecursively(false); 3850 continue; 3851 } 3852 3853 QGraphicsItem *child = children.at(i); 3854 const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect); 3855 if (rect.intersects(child->boundingRect())) 3856 child->d_ptr->invalidateCachedClipPathRecursively(false, rect); 3857 else 3858 child->d_ptr->setEmptyCachedClipPathRecursively(rect); 3859 } 3860 } 3861 3862 void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &newPos) 3863 { 3864 Q_ASSERT(inSetPosHelper); 3865 3866 if (!(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) 3867 return; // Not clipped by any ancestor. 3868 3869 // Find closest clip ancestor and transform. 3870 Q_Q(QGraphicsItem); 3871 QTransform thisToParentTransform = hasTransform 3872 ? q->transform() * QTransform::fromTranslate(newPos.x(), newPos.y()) 3873 : QTransform::fromTranslate(newPos.x(), newPos.y()); 3874 QGraphicsItem *clipParent = parent; 3875 while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) { 3876 if (clipParent->d_ptr->hasTransform) 3877 thisToParentTransform *= clipParent->transform(); 3878 if (!clipParent->d_ptr->pos.isNull()) { 3879 thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(), 3880 clipParent->d_ptr->pos.y()); 3881 } 3882 clipParent = clipParent->d_ptr->parent; 3883 } 3884 3885 // thisToParentTransform is now the same as q->itemTransform(clipParent), except 3886 // that the new position (which is not yet set on the item) is taken into account. 3887 Q_ASSERT(clipParent); 3888 Q_ASSERT(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); 3889 3890 // From here everything is calculated in clip parent's coordinates. 3891 const QRectF parentBoundingRect(clipParent->boundingRect()); 3892 const QRectF thisBoundingRect(thisToParentTransform.mapRect(q->boundingRect())); 3893 3894 if (!parentBoundingRect.intersects(thisBoundingRect)) { 3895 // Item is moved outside the clip parent's bounding rect, 3896 // i.e. it is fully clipped and the clip path is empty. 3897 if (flags & QGraphicsItem::ItemClipsChildrenToShape) 3898 setEmptyCachedClipPathRecursively(); 3899 else 3900 setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentBoundingRect)); 3901 return; 3902 } 3903 3904 const QPainterPath parentClip(clipParent->isClipped() ? clipParent->clipPath() : clipParent->shape()); 3905 if (parentClip.contains(thisBoundingRect)) 3906 return; // Item is inside the clip parent's shape. No update required. 3907 3908 const QRectF parentClipRect(parentClip.controlPointRect()); 3909 if (!parentClipRect.intersects(thisBoundingRect)) { 3910 // Item is moved outside the clip parent's shape, 3911 // i.e. it is fully clipped and the clip path is empty. 3912 if (flags & QGraphicsItem::ItemClipsChildrenToShape) 3913 setEmptyCachedClipPathRecursively(); 3914 else 3915 setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentClipRect)); 3916 } else { 3917 // Item is partially inside the clip parent's shape, 3918 // i.e. the cached clip path must be invalidated. 3919 invalidateCachedClipPathRecursively(false, thisToParentTransform.inverted().mapRect(parentClipRect)); 3920 } 5194 parent->d_ptr->subFocusItem = q_ptr; 5195 parent->d_ptr->subFocusItemChange(); 5196 } while (!parent->isPanel() && (parent = parent->d_ptr->parent) && (visible || !parent->d_ptr->visible)); 5197 5198 if (scene && !scene->isActive()) 5199 scene->d_func()->lastFocusItem = subFocusItem; 5200 } 5201 5202 /*! 5203 \internal 5204 */ 5205 void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem) 5206 { 5207 // Reset sub focus chain. 5208 QGraphicsItem *parent = rootItem ? rootItem : q_ptr; 5209 do { 5210 if (parent->d_ptr->subFocusItem != q_ptr) 5211 break; 5212 parent->d_ptr->subFocusItem = 0; 5213 parent->d_ptr->subFocusItemChange(); 5214 } while (!parent->isPanel() && (parent = parent->d_ptr->parent)); 5215 } 5216 5217 /*! 5218 \internal 5219 5220 Sets the focusProxy pointer to 0 for all items that have this item as their 5221 focusProxy. ### Qt 5: Use QPointer instead. 5222 */ 5223 void QGraphicsItemPrivate::resetFocusProxy() 5224 { 5225 for (int i = 0; i < focusProxyRefs.size(); ++i) 5226 *focusProxyRefs.at(i) = 0; 5227 focusProxyRefs.clear(); 5228 } 5229 5230 /*! 5231 \internal 5232 5233 Subclasses can reimplement this function to be notified when subFocusItem 5234 changes. 5235 */ 5236 void QGraphicsItemPrivate::subFocusItemChange() 5237 { 5238 } 5239 5240 /*! 5241 \internal 5242 5243 Subclasses can reimplement this function to be notified when its 5244 siblingIndex order is changed. 5245 */ 5246 void QGraphicsItemPrivate::siblingOrderChange() 5247 { 3921 5248 } 3922 5249 … … 3954 5281 return; 3955 5282 5283 // Make sure we notify effects about invalidated source. 5284 #ifndef QT_NO_GRAPHICSEFFECT 5285 d_ptr->invalidateGraphicsEffectsRecursively(); 5286 #endif //QT_NO_GRAPHICSEFFECT 5287 3956 5288 if (CacheMode(d_ptr->cacheMode) != NoCache) { 5289 // Invalidate cache. 3957 5290 QGraphicsItemCache *cache = d_ptr->extraItemCache(); 3958 if (d_ptr->discardUpdateRequest(/* ignoreVisibleBit = */ false, 3959 /* ignoreClipping = */ false, 3960 /* ignoreDirtyBit = */ true)) { 3961 return; 3962 } 3963 3964 // Invalidate cache. 3965 if (rect.isNull()) { 3966 cache->allExposed = true; 3967 cache->exposed.clear(); 3968 } else { 3969 cache->exposed.append(rect); 5291 if (!cache->allExposed) { 5292 if (rect.isNull()) { 5293 cache->allExposed = true; 5294 cache->exposed.clear(); 5295 } else { 5296 cache->exposed.append(rect); 5297 } 3970 5298 } 3971 5299 // Only invalidate cache; item is already dirty. 3972 if (d_ptr-> dirty)5300 if (d_ptr->fullUpdatePending) 3973 5301 return; 3974 } else if (d_ptr->discardUpdateRequest()) { 5302 } 5303 5304 if (d_ptr->discardUpdateRequest()) 3975 5305 return; 3976 } 3977 3978 // Effectively the same as updateHelper(rect); 3979 if (rect.isNull()) 3980 d_ptr->dirty = 1; 3981 d_ptr->scene->itemUpdated(this, rect); 3982 } 3983 5306 5307 if (d_ptr->scene) 5308 d_ptr->scene->d_func()->markDirty(this, rect); 5309 } 3984 5310 3985 5311 /*! … … 4010 5336 return; 4011 5337 if (d->cacheMode != NoCache) { 4012 // ### This is very slow, and can be done much better. If the cache is 4013 // local and matches the below criteria for rotation and scaling, we 4014 // can easily scroll. And if the cache is in device coordinates, we 4015 // can scroll both the viewport and the cache. 4016 update(rect); 5338 QGraphicsItemCache *c; 5339 bool scrollCache = qFuzzyIsNull(dx - int(dx)) && qFuzzyIsNull(dy - int(dy)) 5340 && (c = (QGraphicsItemCache *)qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraCacheData))) 5341 && (d->cacheMode == ItemCoordinateCache && !c->fixedSize.isValid()); 5342 if (scrollCache) { 5343 QPixmap pix; 5344 if (QPixmapCache::find(c->key, &pix)) { 5345 // Adjust with 2 pixel margin. Notice the loss of precision 5346 // when converting to QRect. 5347 int adjust = 2; 5348 QRectF br = boundingRect().adjusted(-adjust, -adjust, adjust, adjust); 5349 QRect irect = rect.toRect().translated(-br.x(), -br.y()); 5350 5351 pix.scroll(dx, dy, irect); 5352 5353 QPixmapCache::replace(c->key, pix); 5354 5355 // Translate the existing expose. 5356 foreach (QRectF exposedRect, c->exposed) 5357 c->exposed += exposedRect.translated(dx, dy) & rect; 5358 5359 // Calculate exposure. 5360 QRegion exposed; 5361 QRect r = rect.toRect(); 5362 exposed += r; 5363 exposed -= r.translated(dx, dy); 5364 foreach (QRect rect, exposed.rects()) 5365 update(rect); 5366 d->scene->d_func()->markDirty(this); 5367 } else { 5368 update(rect); 5369 } 5370 } else { 5371 // ### This is very slow, and can be done much better. If the cache is 5372 // local and matches the below criteria for rotation and scaling, we 5373 // can easily scroll. And if the cache is in device coordinates, we 5374 // can scroll both the viewport and the cache. 5375 update(rect); 5376 } 4017 5377 return; 4018 5378 } … … 4033 5393 static const QLineF right(0, 0, 1, 0); 4034 5394 4035 QTransform deviceTr; 4036 if (d->itemIsUntransformable()) { 4037 deviceTr = deviceTransform(view->viewportTransform()); 4038 } else { 4039 deviceTr = sceneTransform() * view->viewportTransform(); 4040 } 4041 5395 QTransform deviceTr = deviceTransform(view->viewportTransform()); 4042 5396 QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect(); 4043 5397 QLineF v1 = deviceTr.map(right); … … 4171 5525 QPointF QGraphicsItem::mapToParent(const QPointF &point) const 4172 5526 { 4173 return d_ptr->pos + (d_ptr->hasTransform ? transform().map(point) : point); 5527 // COMBINE 5528 if (!d_ptr->transformData) 5529 return point + d_ptr->pos; 5530 return d_ptr->transformToParent().map(point); 4174 5531 } 4175 5532 … … 4191 5548 QPointF QGraphicsItem::mapToScene(const QPointF &point) const 4192 5549 { 4193 return sceneTransform().map(point); 5550 if (d_ptr->hasTranslateOnlySceneTransform()) 5551 return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy()); 5552 return d_ptr->sceneTransform.map(point); 4194 5553 } 4195 5554 … … 4236 5595 QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const 4237 5596 { 4238 QPolygonF p = !d_ptr->hasTransform ? rect : transform().map(rect); 4239 p.translate(d_ptr->pos); 4240 return p; 5597 // COMBINE 5598 if (!d_ptr->transformData) 5599 return rect.translated(d_ptr->pos); 5600 return d_ptr->transformToParent().map(rect); 4241 5601 } 4242 5602 … … 4257 5617 QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const 4258 5618 { 4259 return sceneTransform().map(rect); 5619 if (d_ptr->hasTranslateOnlySceneTransform()) 5620 return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); 5621 return d_ptr->sceneTransform.map(rect); 4260 5622 } 4261 5623 … … 4305 5667 QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const 4306 5668 { 4307 QRectF r = !d_ptr->hasTransform ? rect : transform().mapRect(rect); 4308 return r.translated(d_ptr->pos); 5669 // COMBINE 5670 if (!d_ptr->transformData) 5671 return rect.translated(d_ptr->pos); 5672 return d_ptr->transformToParent().mapRect(rect); 4309 5673 } 4310 5674 … … 4328 5692 QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const 4329 5693 { 4330 return sceneTransform().mapRect(rect); 5694 if (d_ptr->hasTranslateOnlySceneTransform()) 5695 return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); 5696 return d_ptr->sceneTransform.mapRect(rect); 4331 5697 } 4332 5698 … … 4377 5743 QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const 4378 5744 { 4379 QRectF r = rect.translated(-d_ptr->pos); 4380 return d_ptr->hasTransform ? transform().inverted().mapRect(r) : r; 5745 // COMBINE 5746 if (!d_ptr->transformData) 5747 return rect.translated(-d_ptr->pos); 5748 return d_ptr->transformToParent().inverted().mapRect(rect); 4381 5749 } 4382 5750 … … 4400 5768 QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const 4401 5769 { 4402 return sceneTransform().inverted().mapRect(rect); 5770 if (d_ptr->hasTranslateOnlySceneTransform()) 5771 return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); 5772 return d_ptr->sceneTransform.inverted().mapRect(rect); 4403 5773 } 4404 5774 … … 4437 5807 QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const 4438 5808 { 4439 QPolygonF p = !d_ptr->hasTransform ? polygon : transform().map(polygon); 4440 p.translate(d_ptr->pos); 4441 return p; 5809 // COMBINE 5810 if (!d_ptr->transformData) 5811 return polygon.translated(d_ptr->pos); 5812 return d_ptr->transformToParent().map(polygon); 4442 5813 } 4443 5814 … … 4451 5822 QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const 4452 5823 { 4453 return sceneTransform().map(polygon); 5824 if (d_ptr->hasTranslateOnlySceneTransform()) 5825 return polygon.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); 5826 return d_ptr->sceneTransform.map(polygon); 4454 5827 } 4455 5828 … … 4481 5854 QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const 4482 5855 { 4483 QTransform x = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());4484 if ( d_ptr->hasTransform)4485 x = transform() * x;4486 return x.map(path);5856 // COMBINE 5857 if (!d_ptr->transformData) 5858 return path.translated(d_ptr->pos); 5859 return d_ptr->transformToParent().map(path); 4487 5860 } 4488 5861 … … 4496 5869 QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const 4497 5870 { 4498 return sceneTransform().map(path); 5871 if (d_ptr->hasTranslateOnlySceneTransform()) 5872 return path.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); 5873 return d_ptr->sceneTransform.map(path); 4499 5874 } 4500 5875 … … 4533 5908 QPointF QGraphicsItem::mapFromParent(const QPointF &point) const 4534 5909 { 4535 if (d_ptr->hasTransform) 4536 return transform().inverted().map(point - d_ptr->pos); 5910 // COMBINE 5911 if (d_ptr->transformData) 5912 return d_ptr->transformToParent().inverted().map(point); 4537 5913 return point - d_ptr->pos; 4538 5914 } … … 4556 5932 QPointF QGraphicsItem::mapFromScene(const QPointF &point) const 4557 5933 { 4558 return sceneTransform().inverted().map(point); 5934 if (d_ptr->hasTranslateOnlySceneTransform()) 5935 return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy()); 5936 return d_ptr->sceneTransform.inverted().map(point); 4559 5937 } 4560 5938 … … 4601 5979 QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const 4602 5980 { 4603 QRectF r = rect.translated(-d_ptr->pos); 4604 return d_ptr->hasTransform ? transform().inverted().map(r) : r; 5981 // COMBINE 5982 if (!d_ptr->transformData) 5983 return rect.translated(-d_ptr->pos); 5984 return d_ptr->transformToParent().inverted().map(rect); 4605 5985 } 4606 5986 … … 4622 6002 QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const 4623 6003 { 4624 return sceneTransform().inverted().map(rect); 6004 if (d_ptr->hasTranslateOnlySceneTransform()) 6005 return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); 6006 return d_ptr->sceneTransform.inverted().map(rect); 4625 6007 } 4626 6008 … … 4657 6039 QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const 4658 6040 { 4659 QPolygonF p = polygon; 4660 p.translate(-d_ptr->pos); 4661 return d_ptr->hasTransform ? transform().inverted().map(p) : p; 6041 // COMBINE 6042 if (!d_ptr->transformData) 6043 return polygon.translated(-d_ptr->pos); 6044 return d_ptr->transformToParent().inverted().map(polygon); 4662 6045 } 4663 6046 … … 4671 6054 QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const 4672 6055 { 4673 return sceneTransform().inverted().map(polygon); 6056 if (d_ptr->hasTranslateOnlySceneTransform()) 6057 return polygon.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); 6058 return d_ptr->sceneTransform.inverted().map(polygon); 4674 6059 } 4675 6060 … … 4699 6084 QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const 4700 6085 { 4701 if (d_ptr->parent) 4702 return d_ptr->parent->itemTransform(this).map(path); 4703 return mapFromScene(path); 6086 // COMBINE 6087 if (!d_ptr->transformData) 6088 return path.translated(-d_ptr->pos); 6089 return d_ptr->transformToParent().inverted().map(path); 4704 6090 } 4705 6091 … … 4713 6099 QPainterPath QGraphicsItem::mapFromScene(const QPainterPath &path) const 4714 6100 { 4715 return sceneTransform().inverted().map(path); 6101 if (d_ptr->hasTranslateOnlySceneTransform()) 6102 return path.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); 6103 return d_ptr->sceneTransform.inverted().map(path); 4716 6104 } 4717 6105 … … 4725 6113 { 4726 6114 if (!child || child == this) 6115 return false; 6116 if (child->d_ptr->depth() < d_ptr->depth()) 4727 6117 return false; 4728 6118 const QGraphicsItem *ancestor = child; … … 4750 6140 const QGraphicsItem *thisw = this; 4751 6141 const QGraphicsItem *otherw = other; 4752 int thisDepth = d_ptr->depth ;4753 int otherDepth = other->d_ptr->depth ;6142 int thisDepth = d_ptr->depth(); 6143 int otherDepth = other->d_ptr->depth(); 4754 6144 while (thisDepth > otherDepth) { 4755 6145 thisw = thisw->d_ptr->parent; … … 5050 6440 inputMethodEvent(static_cast<QInputMethodEvent *>(event)); 5051 6441 break; 6442 case QEvent::WindowActivate: 6443 case QEvent::WindowDeactivate: 6444 // Propagate panel activation. 6445 if (d_ptr->scene) { 6446 for (int i = 0; i < d_ptr->children.size(); ++i) { 6447 QGraphicsItem *child = d_ptr->children.at(i); 6448 if (child->isVisible() && !child->isPanel()) { 6449 if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents)) 6450 d_ptr->scene->sendEvent(child, event); 6451 } 6452 } 6453 } 6454 break; 5052 6455 default: 5053 6456 return false; … … 5189 6592 ensureVisible(). 5190 6593 5191 \sa focusOutEvent(), sceneEvent() 6594 \sa focusOutEvent(), sceneEvent(), setFocus() 5192 6595 */ 5193 6596 void QGraphicsItem::focusInEvent(QFocusEvent *event) 5194 6597 { 5195 6598 Q_UNUSED(event); 6599 update(); 5196 6600 } 5197 6601 … … 5200 6604 focus out events for this item. The default implementation does nothing. 5201 6605 5202 \sa focusInEvent(), sceneEvent() 6606 \sa focusInEvent(), sceneEvent(), setFocus() 5203 6607 */ 5204 6608 void QGraphicsItem::focusOutEvent(QFocusEvent *event) 5205 6609 { 5206 6610 Q_UNUSED(event); 6611 update(); 5207 6612 } 5208 6613 … … 5219 6624 { 5220 6625 Q_UNUSED(event); 5221 d_ptr->updateHelper();6626 update(); 5222 6627 } 5223 6628 … … 5247 6652 { 5248 6653 Q_UNUSED(event); 5249 d_ptr->updateHelper();6654 update(); 5250 6655 } 5251 6656 … … 5337 6742 // Qt::Popup closes when you click outside. 5338 6743 QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this); 5339 if ( w->windowFlags() &Qt::Popup) {6744 if ((w->windowFlags() & Qt::Popup) == Qt::Popup) { 5340 6745 event->accept(); 5341 6746 if (!w->rect().contains(event->pos())) … … 5584 6989 property is queried. 5585 6990 5586 \sa inputMethodEvent() 6991 \sa inputMethodEvent(), QInputMethodEvent, QInputContext 5587 6992 */ 5588 6993 QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const … … 5600 7005 5601 7006 /*! 7007 Returns the current input method hints of this item. 7008 7009 Input method hints are only relevant for input items. 7010 The hints are used by the input method to indicate how it should operate. 7011 For example, if the Qt::ImhNumbersOnly flag is set, the input method may change 7012 its visual components to reflect that only numbers can be entered. 7013 7014 The effect may vary between input method implementations. 7015 7016 \since 4.6 7017 7018 \sa setInputMethodHints(), inputMethodQuery(), QInputContext 7019 */ 7020 Qt::InputMethodHints QGraphicsItem::inputMethodHints() const 7021 { 7022 Q_D(const QGraphicsItem); 7023 return d->imHints; 7024 } 7025 7026 /*! 7027 Sets the current input method hints of this item to \a hints. 7028 7029 \since 4.6 7030 7031 \sa inputMethodHints(), inputMethodQuery(), QInputContext 7032 */ 7033 void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints) 7034 { 7035 Q_D(QGraphicsItem); 7036 d->imHints = hints; 7037 } 7038 7039 /*! 5602 7040 This virtual function is called by QGraphicsItem to notify custom items 5603 7041 that some part of the item's state changes. By reimplementing this … … 5676 7114 } 5677 7115 if (d_ptr->scene) 5678 d_ptr->scene->d_func()->addToIndex(this); 5679 d_ptr->updateHelper(); 7116 d_ptr->scene->d_func()->index->addItem(this); 5680 7117 } 5681 7118 … … 5693 7130 return; 5694 7131 } 5695 d_ptr->updateHelper();5696 7132 if (d_ptr->scene) 5697 d_ptr->scene->d_func()-> removeFromIndex(this);7133 d_ptr->scene->d_func()->index->removeItem(this); 5698 7134 } 5699 7135 … … 5713 7149 void QGraphicsItem::prepareGeometryChange() 5714 7150 { 7151 if (d_ptr->inDestructor) 7152 return; 5715 7153 if (d_ptr->scene) { 5716 d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); 7154 d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true; 7155 d_ptr->geometryChanged = 1; 7156 d_ptr->paintedViewBoundingRectsNeedRepaint = 1; 7157 d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper; 7158 5717 7159 QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); 5718 scenePrivate->removeFromIndex(this); 5719 } 5720 5721 if (d_ptr->inSetPosHelper) 5722 return; 5723 5724 if (d_ptr->flags & ItemClipsChildrenToShape) 5725 d_ptr->invalidateCachedClipPathRecursively(); 5726 else 5727 d_ptr->invalidateCachedClipPath(); 7160 scenePrivate->index->prepareBoundingRectChange(this); 7161 scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true); 7162 7163 // For compatibility reasons, we have to update the item's old geometry 7164 // if someone is connected to the changed signal or the scene has no views. 7165 // Note that this has to be done *after* markDirty to ensure that 7166 // _q_processDirtyItems is called before _q_emitUpdated. 7167 if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex) 7168 || scenePrivate->views.isEmpty()) { 7169 if (d_ptr->hasTranslateOnlySceneTransform()) { 7170 d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(), 7171 d_ptr->sceneTransform.dy())); 7172 } else { 7173 d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect())); 7174 } 7175 } 7176 } 7177 7178 QGraphicsItem *parent = this; 7179 while ((parent = parent->d_ptr->parent)) { 7180 QGraphicsItemPrivate *parentp = parent->d_ptr.data(); 7181 parentp->dirtyChildrenBoundingRect = 1; 7182 // ### Only do this if the parent's effect applies to the entire subtree. 7183 parentp->notifyBoundingRectChanged = 1; 7184 #ifndef QT_NO_GRAPHICSEFFECT 7185 if (parentp->scene && parentp->graphicsEffect) { 7186 parentp->notifyInvalidated = 1; 7187 static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()->source->d_func())->invalidateCache(); 7188 } 7189 #endif 7190 } 5728 7191 } 5729 7192 … … 5740 7203 { 5741 7204 const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1)); 5742 if (qFuzzy Compare(qMax(murect.width(), murect.height()) + 1, 1))7205 if (qFuzzyIsNull(qMax(murect.width(), murect.height()))) 5743 7206 return; 5744 7207 … … 5790 7253 5791 7254 /*! 7255 \class QGraphicsObject 7256 \brief The QGraphicsObject class provides a base class for all graphics items that 7257 require signals, slots and properties. 7258 \since 4.6 7259 \ingroup graphicsview-api 7260 7261 The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms. 7262 It maps many of QGraphicsItem's basic setters and getters to properties and adds notification 7263 signals for many of them. 7264 7265 \section1 Parents and Children 7266 7267 Each graphics object can be constructed with a parent item. This ensures that the 7268 item will be destroyed when its parent item is destroyed. Although QGraphicsObject 7269 inherits from both QObject and QGraphicsItem, you should use the functions provided 7270 by QGraphicsItem, \e not QObject, to manage the relationships between parent and 7271 child items. 7272 7273 The relationships between items can be explored using the parentItem() and childItems() 7274 functions. In the hierarchy of items in a scene, the parentObject() and parentWidget() 7275 functions are the equivalent of the QWidget::parent() and QWidget::parentWidget() 7276 functions for QWidget subclasses. 7277 7278 \sa QGraphicsWidget 7279 */ 7280 7281 /*! 7282 Constructs a QGraphicsObject with \a parent. 7283 */ 7284 QGraphicsObject::QGraphicsObject(QGraphicsItem *parent) 7285 : QGraphicsItem(parent) 7286 { 7287 QGraphicsItem::d_ptr->isObject = true; 7288 } 7289 7290 /*! 7291 \internal 7292 */ 7293 QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene) 7294 : QGraphicsItem(dd, parent, scene) 7295 { 7296 QGraphicsItem::d_ptr->isObject = true; 7297 } 7298 7299 /*! 7300 Subscribes the graphics object to the given \a gesture with specific \a flags. 7301 7302 \sa ungrabGesture(), QGestureEvent 7303 */ 7304 void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags) 7305 { 7306 QGraphicsItemPrivate * const d = QGraphicsItem::d_func(); 7307 d->gestureContext.insert(gesture, flags); 7308 (void)QGestureManager::instance(); // create a gesture manager 7309 } 7310 7311 /*! 7312 Unsubscribes the graphics object from the given \a gesture. 7313 7314 \sa grabGesture(), QGestureEvent 7315 */ 7316 void QGraphicsObject::ungrabGesture(Qt::GestureType gesture) 7317 { 7318 QGraphicsItemPrivate * const d = QGraphicsItem::d_func(); 7319 if (d->gestureContext.remove(gesture)) { 7320 QGestureManager *manager = QGestureManager::instance(); 7321 manager->cleanupCachedGestures(this, gesture); 7322 } 7323 } 7324 7325 /*! 7326 \property QGraphicsObject::parent 7327 \brief the parent of the item 7328 7329 \note The item's parent is set independently of the parent object returned 7330 by QObject::parent(). 7331 7332 \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject() 7333 */ 7334 7335 /*! 7336 \property QGraphicsObject::opacity 7337 \brief the opacity of the item 7338 7339 \sa QGraphicsItem::setOpacity(), QGraphicsItem::opacity() 7340 */ 7341 7342 /*! 7343 \fn QGraphicsObject::opacityChanged() 7344 7345 This signal gets emitted whenever the opacity of the item changes 7346 7347 \sa QGraphicsItem::opacity() 7348 */ 7349 7350 /*! 7351 \fn QGraphicsObject::parentChanged() 7352 7353 This signal gets emitted whenever the parent of the item changes 7354 */ 7355 7356 /*! 7357 \property QGraphicsObject::pos 7358 \brief the position of the item 7359 7360 Describes the items position. 7361 7362 \sa QGraphicsItem::setPos(), QGraphicsItem::pos() 7363 */ 7364 7365 /*! 7366 \property QGraphicsObject::x 7367 \brief the x position of the item 7368 7369 Describes the items x position. 7370 7371 \sa QGraphicsItem::setX(), setPos(), xChanged() 7372 */ 7373 7374 /*! 7375 \fn QGraphicsObject::xChanged() 7376 7377 This signal gets emitted whenever the x position of the item changes 7378 7379 \sa pos() 7380 */ 7381 7382 /*! 7383 \property QGraphicsObject::y 7384 \brief the y position of the item 7385 7386 Describes the items y position. 7387 7388 \sa QGraphicsItem::setY(), setPos(), yChanged() 7389 */ 7390 7391 /*! 7392 \fn QGraphicsObject::yChanged() 7393 7394 This signal gets emitted whenever the y position of the item changes. 7395 7396 \sa pos() 7397 */ 7398 7399 /*! 7400 \property QGraphicsObject::z 7401 \brief the z value of the item 7402 7403 Describes the items z value. 7404 7405 \sa QGraphicsItem::setZValue(), zValue(), zChanged() 7406 */ 7407 7408 /*! 7409 \fn QGraphicsObject::zChanged() 7410 7411 This signal gets emitted whenever the z value of the item changes. 7412 7413 \sa pos() 7414 */ 7415 7416 /*! 7417 \property QGraphicsObject::rotation 7418 This property holds the rotation of the item in degrees. 7419 7420 This specifies how many degrees to rotate the item around its transformOrigin. 7421 The default rotation is 0 degrees (i.e. not rotated at all). 7422 */ 7423 7424 /*! 7425 \fn QGraphicsObject::rotationChanged() 7426 7427 This signal gets emitted whenever the roation of the item changes. 7428 */ 7429 7430 /*! 7431 \property QGraphicsObject::scale 7432 This property holds the scale of the item. 7433 7434 A scale of less than 1 means the item will be displayed smaller than 7435 normal, and a scale of greater than 1 means the item will be 7436 displayed larger than normal. A negative scale means the item will 7437 be mirrored. 7438 7439 By default, items are displayed at a scale of 1 (i.e. at their 7440 normal size). 7441 7442 Scaling is from the item's transformOrigin. 7443 */ 7444 7445 /*! 7446 \fn void QGraphicsObject::scaleChanged() 7447 7448 This signal is emitted when the scale of the item changes. 7449 */ 7450 7451 7452 /*! 7453 \property QGraphicsObject::enabled 7454 \brief whether the item is enabled or not 7455 7456 This property is declared in QGraphicsItem. 7457 7458 By default, this property is true. 7459 7460 \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled() 7461 \sa QGraphicsObject::enabledChanged() 7462 */ 7463 7464 /*! 7465 \fn void QGraphicsObject::enabledChanged() 7466 7467 This signal gets emitted whenever the item get's enabled or disabled. 7468 7469 \sa isEnabled() 7470 */ 7471 7472 /*! 7473 \property QGraphicsObject::visible 7474 \brief whether the item is visible or not 7475 7476 This property is declared in QGraphicsItem. 7477 7478 By default, this property is true. 7479 7480 \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), visibleChanged() 7481 */ 7482 7483 /*! 7484 \fn QGraphicsObject::visibleChanged() 7485 7486 This signal gets emitted whenever the visibility of the item changes 7487 7488 \sa visible 7489 */ 7490 7491 /*! 7492 \fn const QObjectList &QGraphicsObject::children() const 7493 \internal 7494 7495 This function returns the same value as QObject::children(). It's 7496 provided to differentiate between the obsolete member 7497 QGraphicsItem::children() and QObject::children(). QGraphicsItem now 7498 provides childItems() instead. 7499 */ 7500 7501 /*! 7502 \property QGraphicsObject::transformOriginPoint 7503 \brief the transformation origin 7504 7505 This property sets a specific point in the items coordiante system as the 7506 origin for scale and rotation. 7507 7508 \sa scale, rotation, QGraphicsItem::transformOriginPoint() 7509 */ 7510 7511 7512 /*! 5792 7513 \class QAbstractGraphicsShapeItem 5793 7514 \brief The QAbstractGraphicsShapeItem class provides a common base for 5794 7515 all path items. 5795 7516 \since 4.2 5796 \ingroup multimedia7517 \ingroup graphicsview-api 5797 7518 5798 7519 This class does not fully implement an item by itself; in particular, it … … 5929 7650 can add to a QGraphicsScene. 5930 7651 \since 4.2 5931 \ingroup multimedia5932 7652 \ingroup graphicsview-api 5933 7653 … … 6132 7852 can add to a QGraphicsScene. 6133 7853 \since 4.2 6134 \ingroup multimedia6135 7854 \ingroup graphicsview-api 6136 7855 … … 6377 8096 can add to a QGraphicsScene. 6378 8097 \since 4.2 6379 \ingroup multimedia6380 8098 \ingroup graphicsview-api 6381 8099 … … 6694 8412 can add to a QGraphicsScene. 6695 8413 \since 4.2 6696 \ingroup multimedia6697 8414 \ingroup graphicsview-api 6698 8415 … … 6928 8645 QGraphicsScene. 6929 8646 \since 4.2 6930 \ingroup multimedia6931 8647 \ingroup graphicsview-api 6932 8648 … … 7190 8906 a QGraphicsScene. 7191 8907 \since 4.2 7192 \ingroup multimedia7193 8908 \ingroup graphicsview-api 7194 8909 … … 7379 9094 Q_D(QGraphicsPixmapItem); 7380 9095 if (mode != d->transformationMode) { 7381 d_ptr->updateHelper();7382 9096 d->transformationMode = mode; 7383 9097 update(); … … 7427 9141 { 7428 9142 Q_D(const QGraphicsPixmapItem); 7429 qreal pw = 1.0;7430 9143 if (d->pixmap.isNull()) 7431 9144 return QRectF(); 7432 return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); 9145 if (d->flags & ItemIsSelectable) { 9146 qreal pw = 1.0; 9147 return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); 9148 } else { 9149 return QRectF(d->offset, d->pixmap.size()); 9150 } 7433 9151 } 7434 9152 … … 7467 9185 (d->transformationMode == Qt::SmoothTransformation)); 7468 9186 7469 QRectF exposed = option->exposedRect.adjusted(-1, -1, 1, 1); 7470 exposed &= QRectF(d->offset.x(), d->offset.y(), d->pixmap.width(), d->pixmap.height()); 7471 painter->drawPixmap(exposed, d->pixmap, exposed.translated(-d->offset)); 9187 painter->drawPixmap(d->offset, d->pixmap); 7472 9188 7473 9189 if (option->state & QStyle::State_Selected) … … 7557 9273 a QGraphicsScene to display formatted text. 7558 9274 \since 4.2 7559 \ingroup multimedia7560 9275 \ingroup graphicsview-api 7561 9276 … … 7592 9307 public: 7593 9308 QGraphicsTextItemPrivate() 7594 : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false) 9309 : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false), clickCausedFocus(0) 7595 9310 { } 7596 9311 … … 7613 9328 bool tabChangesFocus; 7614 9329 9330 uint clickCausedFocus : 1; 9331 7615 9332 QGraphicsTextItem *qq; 7616 9333 }; 9334 7617 9335 7618 9336 /*! … … 7628 9346 #endif 7629 9347 ) 7630 : QGraphics Item(parent, scene), dd(new QGraphicsTextItemPrivate)9348 : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate) 7631 9349 { 7632 9350 dd->qq = this; … … 7635 9353 setAcceptDrops(true); 7636 9354 setAcceptHoverEvents(true); 9355 setFlags(ItemUsesExtendedStyleOption); 7637 9356 } 7638 9357 … … 7649 9368 #endif 7650 9369 ) 7651 : QGraphics Item(parent, scene), dd(new QGraphicsTextItemPrivate)9370 : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate) 7652 9371 { 7653 9372 dd->qq = this; 7654 9373 setAcceptDrops(true); 7655 9374 setAcceptHoverEvents(true); 9375 setFlag(ItemUsesExtendedStyleOption); 7656 9376 } 7657 9377 … … 7743 9463 QTextControl *c = dd->textControl(); 7744 9464 QPalette pal = c->palette(); 9465 QColor old = pal.color(QPalette::Text); 7745 9466 pal.setColor(QPalette::Text, col); 7746 9467 c->setPalette(pal); 9468 if (old != col) 9469 update(); 7747 9470 } 7748 9471 … … 7915 9638 } 7916 9639 } 7917 return QGraphicsItem::sceneEvent(event); 9640 bool result = QGraphicsItem::sceneEvent(event); 9641 9642 // Ensure input context is updated. 9643 switch (event->type()) { 9644 case QEvent::ContextMenu: 9645 case QEvent::FocusIn: 9646 case QEvent::FocusOut: 9647 case QEvent::GraphicsSceneDragEnter: 9648 case QEvent::GraphicsSceneDragLeave: 9649 case QEvent::GraphicsSceneDragMove: 9650 case QEvent::GraphicsSceneDrop: 9651 case QEvent::GraphicsSceneHoverEnter: 9652 case QEvent::GraphicsSceneHoverLeave: 9653 case QEvent::GraphicsSceneHoverMove: 9654 case QEvent::GraphicsSceneMouseDoubleClick: 9655 case QEvent::GraphicsSceneMousePress: 9656 case QEvent::GraphicsSceneMouseMove: 9657 case QEvent::GraphicsSceneMouseRelease: 9658 case QEvent::KeyPress: 9659 case QEvent::KeyRelease: 9660 // Reset the focus widget's input context, regardless 9661 // of how this item gained or lost focus. 9662 if (QWidget *fw = qApp->focusWidget()) { 9663 #ifndef QT_NO_IM 9664 if (QInputContext *qic = fw->inputContext()) { 9665 if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) 9666 qic->reset(); 9667 else 9668 qic->update(); 9669 } 9670 #endif //QT_NO_IM 9671 } 9672 break; 9673 default: 9674 break; 9675 } 9676 9677 return result; 7918 9678 } 7919 9679 … … 7924 9684 { 7925 9685 if ((QGraphicsItem::d_ptr->flags & (ItemIsSelectable | ItemIsMovable)) 7926 7927 7928 7929 9686 && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) { 9687 // User left-pressed on edge of selectable/movable item, use 9688 // base impl. 9689 dd->useDefaultImpl = true; 7930 9690 } else if (event->buttons() == event->button() 7931 7932 7933 9691 && dd->control->textInteractionFlags() == Qt::NoTextInteraction) { 9692 // User pressed first button on non-interactive item. 9693 dd->useDefaultImpl = true; 7934 9694 } 7935 9695 if (dd->useDefaultImpl) { 7936 9696 QGraphicsItem::mousePressEvent(event); 7937 7938 9697 if (!event->isAccepted()) 9698 dd->useDefaultImpl = false; 7939 9699 return; 7940 9700 } 9701 7941 9702 dd->sendControlEvent(event); 7942 9703 } … … 7951 9712 return; 7952 9713 } 9714 7953 9715 dd->sendControlEvent(event); 7954 9716 } … … 7961 9723 if (dd->useDefaultImpl) { 7962 9724 QGraphicsItem::mouseReleaseEvent(event); 7963 7964 7965 9725 if (dd->control->textInteractionFlags() == Qt::NoTextInteraction 9726 && !event->buttons()) { 9727 // User released last button on non-interactive item. 7966 9728 dd->useDefaultImpl = false; 7967 7968 9729 } else if ((event->buttons() & Qt::LeftButton) == 0) { 9730 // User released the left button on an interactive item. 7969 9731 dd->useDefaultImpl = false; 7970 9732 } 7971 9733 return; 7972 9734 } 9735 9736 QWidget *widget = event->widget(); 9737 if (widget && (dd->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos())) { 9738 qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus); 9739 } 9740 dd->clickCausedFocus = 0; 7973 9741 dd->sendControlEvent(event); 7974 9742 } … … 8022 9790 { 8023 9791 dd->sendControlEvent(event); 9792 if (event->reason() == Qt::MouseFocusReason) { 9793 dd->clickCausedFocus = 1; 9794 } 8024 9795 update(); 8025 9796 } … … 8258 10029 input. 8259 10030 8260 The default for a QGraphicsTextItem is Qt::NoTextInteraction. Setting a8261 value different to Qt::NoTextInteraction will also set the ItemIsFocusable8262 QGraphicsItem flag.10031 The default for a QGraphicsTextItem is Qt::NoTextInteraction. This function 10032 also affects the ItemIsFocusable QGraphicsItem flag by setting it if \a flags 10033 is different from Qt::NoTextInteraction and clearing it otherwise. 8263 10034 8264 10035 By default, the text is read-only. To transform the item into an editor, … … 8268 10039 { 8269 10040 if (flags == Qt::NoTextInteraction) 8270 setFlags(this->flags() & ~ QGraphicsItem::ItemIsFocusable);10041 setFlags(this->flags() & ~(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod)); 8271 10042 else 8272 setFlags(this->flags() | QGraphicsItem::ItemIsFocusable); 10043 setFlags(this->flags() | QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod); 10044 8273 10045 dd->textControl()->setTextInteractionFlags(flags); 8274 10046 } … … 8419 10191 that you can add to a QGraphicsScene. 8420 10192 \since 4.2 8421 \ingroup multimedia8422 10193 \ingroup graphicsview-api 8423 10194 … … 8655 10426 one. 8656 10427 \since 4.2 8657 \ingroup multimedia8658 10428 \ingroup graphicsview-api 8659 10429 … … 8670 10440 8671 10441 The boundingRect() function of QGraphicsItemGroup returns the 8672 bounding rectangle of all items in the item group. In addition, 8673 item groups have handlesChildEvents() enabled by default, so all 8674 events sent to a member of the group go to the item group (i.e., 8675 selecting one item in a group will select them all). 8676 QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on its 8677 children (i.e., with respect to the geometry of the group item, the 8678 children are treated as if they were transformable). 10442 bounding rectangle of all items in the item group. 10443 QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on 10444 its children (i.e., with respect to the geometry of the group 10445 item, the children are treated as if they were transformable). 8679 10446 8680 10447 There are two ways to construct an item group. The easiest and … … 8761 10528 } 8762 10529 8763 QTransform oldSceneMatrix = item->sceneTransform(); 10530 // COMBINE 10531 bool ok; 10532 QTransform itemTransform = item->itemTransform(this, &ok); 10533 10534 if (!ok) { 10535 qWarning("QGraphicsItemGroup::addToGroup: could not find a valid transformation from item to group coordinates"); 10536 return; 10537 } 10538 10539 QTransform newItemTransform(itemTransform); 8764 10540 item->setPos(mapFromItem(item, 0, 0)); 8765 10541 item->setParentItem(this); 8766 QTransform newItemTransform(oldSceneMatrix); 8767 newItemTransform *= sceneTransform().inverted();10542 10543 // removing position from translation component of the new transform 8768 10544 if (!item->pos().isNull()) 8769 10545 newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y()); 10546 10547 // removing additional transformations properties applied with itemTransform() 10548 QPointF origin = item->transformOriginPoint(); 10549 QMatrix4x4 m; 10550 QList<QGraphicsTransform*> transformList = item->transformations(); 10551 for (int i = 0; i < transformList.size(); ++i) 10552 transformList.at(i)->applyTo(&m); 10553 newItemTransform *= m.toTransform().inverted(); 10554 newItemTransform.translate(origin.x(), origin.y()); 10555 newItemTransform.rotate(-item->rotation()); 10556 newItemTransform.scale(1/item->scale(), 1/item->scale()); 10557 newItemTransform.translate(-origin.x(), -origin.y()); 10558 10559 // ### Expensive, we could maybe use dirtySceneTransform bit for optimization 10560 8770 10561 item->setTransform(newItemTransform); 8771 10562 item->d_func()->setIsMemberOfGroup(true); 8772 10563 prepareGeometryChange(); 8773 QTransform itemTransform(item->transform());8774 if (!item->pos().isNull())8775 itemTransform *= QTransform::fromTranslate(item->x(), item->y());8776 10564 d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect()); 8777 10565 update(); … … 8795 10583 8796 10584 QGraphicsItem *newParent = d_ptr->parent; 10585 10586 // COMBINE 10587 bool ok; 10588 QTransform itemTransform; 10589 if (newParent) 10590 itemTransform = item->itemTransform(newParent, &ok); 10591 else 10592 itemTransform = item->sceneTransform(); 10593 8797 10594 QPointF oldPos = item->mapToItem(newParent, 0, 0); 8798 10595 item->setParentItem(newParent); 8799 // ### This function should remap the item's matrix to keep the item's8800 // transformation unchanged relative to the scene.8801 10596 item->setPos(oldPos); 10597 10598 // removing position from translation component of the new transform 10599 if (!item->pos().isNull()) 10600 itemTransform *= QTransform::fromTranslate(-item->x(), -item->y()); 10601 10602 // removing additional transformations properties applied 10603 // with itemTransform() or sceneTransform() 10604 QPointF origin = item->transformOriginPoint(); 10605 QMatrix4x4 m; 10606 QList<QGraphicsTransform*> transformList = item->transformations(); 10607 for (int i = 0; i < transformList.size(); ++i) 10608 transformList.at(i)->applyTo(&m); 10609 itemTransform *= m.toTransform().inverted(); 10610 itemTransform.translate(origin.x(), origin.y()); 10611 itemTransform.rotate(-item->rotation()); 10612 itemTransform.scale(1 / item->scale(), 1 / item->scale()); 10613 itemTransform.translate(-origin.x(), -origin.y()); 10614 10615 // ### Expensive, we could maybe use dirtySceneTransform bit for optimization 10616 10617 item->setTransform(itemTransform); 8802 10618 item->d_func()->setIsMemberOfGroup(item->group() != 0); 8803 10619 … … 8856 10672 } 8857 10673 10674 #ifndef QT_NO_GRAPHICSEFFECT 10675 QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const 10676 { 10677 const bool deviceCoordinates = (system == Qt::DeviceCoordinates); 10678 if (!info && deviceCoordinates) { 10679 // Device coordinates without info not yet supported. 10680 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context"); 10681 return QRectF(); 10682 } 10683 10684 QRectF rect = item->boundingRect(); 10685 if (!item->d_ptr->children.isEmpty()) 10686 rect |= item->childrenBoundingRect(); 10687 10688 if (deviceCoordinates) { 10689 Q_ASSERT(info->painter); 10690 rect = info->painter->worldTransform().mapRect(rect); 10691 } 10692 10693 return rect; 10694 } 10695 10696 void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) 10697 { 10698 if (!info) { 10699 qWarning("QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw"); 10700 return; 10701 } 10702 10703 Q_ASSERT(item->d_ptr->scene); 10704 QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); 10705 if (painter == info->painter) { 10706 scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, 10707 info->widget, info->opacity, info->effectTransform, info->wasDirtySceneTransform, 10708 info->drawItem); 10709 } else { 10710 QTransform effectTransform = info->painter->worldTransform().inverted(); 10711 effectTransform *= painter->worldTransform(); 10712 scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, 10713 info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, 10714 info->drawItem); 10715 } 10716 } 10717 10718 QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, 10719 QGraphicsEffect::PixmapPadMode mode) const 10720 { 10721 const bool deviceCoordinates = (system == Qt::DeviceCoordinates); 10722 if (!info && deviceCoordinates) { 10723 // Device coordinates without info not yet supported. 10724 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); 10725 return QPixmap(); 10726 } 10727 if (!item->d_ptr->scene) 10728 return QPixmap(); 10729 QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); 10730 10731 const QRectF sourceRect = boundingRect(system); 10732 QRectF effectRectF; 10733 10734 bool unpadded = false; 10735 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) { 10736 if (info) { 10737 effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates)); 10738 unpadded = (effectRectF.size() == sourceRect.size()); 10739 if (info && system == Qt::LogicalCoordinates) 10740 effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF); 10741 } else { 10742 // no choice but to send a logical coordinate bounding rect to boundingRectFor 10743 effectRectF = item->graphicsEffect()->boundingRectFor(sourceRect); 10744 } 10745 } else if (mode == QGraphicsEffect::PadToTransparentBorder) { 10746 // adjust by 1.5 to account for cosmetic pens 10747 effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5); 10748 } else { 10749 effectRectF = sourceRect; 10750 unpadded = true; 10751 } 10752 10753 QRect effectRect = effectRectF.toAlignedRect(); 10754 10755 if (offset) 10756 *offset = effectRect.topLeft(); 10757 10758 bool untransformed = !deviceCoordinates 10759 || info->painter->worldTransform().type() <= QTransform::TxTranslate; 10760 if (untransformed && unpadded && isPixmap()) { 10761 if (offset) 10762 *offset = boundingRect(system).topLeft().toPoint(); 10763 return static_cast<QGraphicsPixmapItem *>(item)->pixmap(); 10764 } 10765 10766 if (deviceCoordinates) { 10767 // Clip to viewport rect. 10768 int left, top, right, bottom; 10769 effectRect.getCoords(&left, &top, &right, &bottom); 10770 if (left < 0) { 10771 if (offset) 10772 offset->rx() += -left; 10773 effectRect.setX(0); 10774 } 10775 if (top < 0) { 10776 if (offset) 10777 offset->ry() += -top; 10778 effectRect.setY(0); 10779 } 10780 // NB! We use +-1 for historical reasons (see QRect documentation). 10781 QPaintDevice *device = info->painter->device(); 10782 const int deviceWidth = device->width(); 10783 const int deviceHeight = device->height(); 10784 if (right + 1 > deviceWidth) 10785 effectRect.setRight(deviceWidth - 1); 10786 if (bottom + 1 > deviceHeight) 10787 effectRect.setBottom(deviceHeight -1); 10788 10789 } 10790 if (effectRect.isEmpty()) 10791 return QPixmap(); 10792 10793 QPixmap pixmap(effectRect.size()); 10794 pixmap.fill(Qt::transparent); 10795 QPainter pixmapPainter(&pixmap); 10796 pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing); 10797 10798 QTransform effectTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y()); 10799 if (deviceCoordinates && info->effectTransform) 10800 effectTransform *= *info->effectTransform; 10801 10802 if (!info) { 10803 // Logical coordinates without info. 10804 QTransform sceneTransform = item->sceneTransform(); 10805 QTransform newEffectTransform = sceneTransform.inverted(); 10806 newEffectTransform *= effectTransform; 10807 scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0), 10808 &newEffectTransform, false, true); 10809 } else if (deviceCoordinates) { 10810 // Device coordinates with info. 10811 scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, 10812 info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, 10813 info->drawItem); 10814 } else { 10815 // Item coordinates with info. 10816 QTransform newEffectTransform = info->transformPtr->inverted(); 10817 newEffectTransform *= effectTransform; 10818 scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, 10819 info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform, 10820 info->drawItem); 10821 } 10822 10823 pixmapPainter.end(); 10824 10825 return pixmap; 10826 } 10827 #endif //QT_NO_GRAPHICSEFFECT 10828 8858 10829 #ifndef QT_NO_DEBUG_STREAM 8859 10830 QDebug operator<<(QDebug debug, QGraphicsItem *item) … … 8864 10835 } 8865 10836 8866 QStringList flags; 8867 if (item->isVisible()) flags << QLatin1String("isVisible"); 8868 if (item->isEnabled()) flags << QLatin1String("isEnabled"); 8869 if (item->isSelected()) flags << QLatin1String("isSelected"); 8870 if (item->hasFocus()) flags << QLatin1String("HasFocus"); 8871 8872 debug << "QGraphicsItem(this =" << ((void*)item) 8873 << ", parent =" << ((void*)item->parentItem()) 10837 if (QGraphicsObject *o = item->toGraphicsObject()) 10838 debug << o->metaObject()->className(); 10839 else 10840 debug << "QGraphicsItem"; 10841 debug << "(this =" << (void*)item 10842 << ", parent =" << (void*)item->parentItem() 8874 10843 << ", pos =" << item->pos() 8875 << ", z =" << item->zValue() << ", flags = {"8876 << flags.join(QLatin1String("|")) << " })";10844 << ", z =" << item->zValue() << ", flags = " 10845 << item->flags() << ")"; 8877 10846 return debug; 10847 } 10848 10849 QDebug operator<<(QDebug debug, QGraphicsObject *item) 10850 { 10851 if (!item) { 10852 debug << "QGraphicsObject(0)"; 10853 return debug; 10854 } 10855 10856 debug.nospace() << item->metaObject()->className() << '(' << (void*)item; 10857 if (!item->objectName().isEmpty()) 10858 debug << ", name = " << item->objectName(); 10859 debug.nospace() << ", parent = " << ((void*)item->parentItem()) 10860 << ", pos = " << item->pos() 10861 << ", z = " << item->zValue() << ", flags = " 10862 << item->flags() << ')'; 10863 return debug.space(); 8878 10864 } 8879 10865 … … 8963 10949 str = "ItemOpacityHasChanged"; 8964 10950 break; 10951 case QGraphicsItem::ItemScenePositionHasChanged: 10952 str = "ItemScenePositionHasChanged"; 10953 break; 8965 10954 } 8966 10955 debug << str; … … 8999 10988 str = "ItemStacksBehindParent"; 9000 10989 break; 10990 case QGraphicsItem::ItemUsesExtendedStyleOption: 10991 str = "ItemUsesExtendedStyleOption"; 10992 break; 10993 case QGraphicsItem::ItemHasNoContents: 10994 str = "ItemHasNoContents"; 10995 break; 10996 case QGraphicsItem::ItemSendsGeometryChanges: 10997 str = "ItemSendsGeometryChanges"; 10998 break; 10999 case QGraphicsItem::ItemAcceptsInputMethod: 11000 str = "ItemAcceptsInputMethod"; 11001 break; 11002 case QGraphicsItem::ItemNegativeZStacksBehindParent: 11003 str = "ItemNegativeZStacksBehindParent"; 11004 break; 11005 case QGraphicsItem::ItemIsPanel: 11006 str = "ItemIsPanel"; 11007 break; 11008 case QGraphicsItem::ItemIsFocusScope: 11009 str = "ItemIsFocusScope"; 11010 break; 11011 case QGraphicsItem::ItemSendsScenePositionChanges: 11012 str = "ItemSendsScenePositionChanges"; 11013 break; 9001 11014 } 9002 11015 debug << str; … … 9006 11019 QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags) 9007 11020 { 9008 debug << "(";11021 debug << '('; 9009 11022 bool f = false; 9010 for (int i = 0; i < 9; ++i) {11023 for (int i = 0; i < 16; ++i) { 9011 11024 if (flags & (1 << i)) { 9012 11025 if (f) 9013 debug << "|";11026 debug << '|'; 9014 11027 f = true; 9015 11028 debug << QGraphicsItem::GraphicsItemFlag(int(flags & (1 << i))); 9016 11029 } 9017 11030 } 9018 debug << ")";11031 debug << ')'; 9019 11032 return debug; 9020 11033 } -
trunk/src/gui/graphicsview/qgraphicsitem.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 47 47 #include <QtCore/qvariant.h> 48 48 #include <QtCore/qrect.h> 49 #include <QtCore/qscopedpointer.h> 49 50 #include <QtGui/qpainterpath.h> 50 51 #include <QtGui/qpixmap.h> … … 63 64 class QCursor; 64 65 class QFocusEvent; 66 class QGraphicsEffect; 65 67 class QGraphicsItemGroup; 68 class QGraphicsObject; 66 69 class QGraphicsSceneContextMenuEvent; 67 70 class QGraphicsSceneDragDropEvent; … … 71 74 class QGraphicsSceneWheelEvent; 72 75 class QGraphicsScene; 76 class QGraphicsTransform; 73 77 class QGraphicsWidget; 74 78 class QInputMethodEvent; … … 95 99 ItemIgnoresParentOpacity = 0x40, 96 100 ItemDoesntPropagateOpacityToChildren = 0x80, 97 ItemStacksBehindParent = 0x100 101 ItemStacksBehindParent = 0x100, 102 ItemUsesExtendedStyleOption = 0x200, 103 ItemHasNoContents = 0x400, 104 ItemSendsGeometryChanges = 0x800, 105 ItemAcceptsInputMethod = 0x1000, 106 ItemNegativeZStacksBehindParent = 0x2000, 107 ItemIsPanel = 0x4000, 108 ItemIsFocusScope = 0x8000, // internal 109 ItemSendsScenePositionChanges = 0x10000 110 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. 98 111 }; 99 112 Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) … … 126 139 ItemZValueHasChanged, 127 140 ItemOpacityChange, 128 ItemOpacityHasChanged 141 ItemOpacityHasChanged, 142 ItemScenePositionHasChanged 129 143 }; 130 144 … … 135 149 }; 136 150 151 enum PanelModality 152 { 153 NonModal, 154 PanelModal, 155 SceneModal 156 }; 157 137 158 QGraphicsItem(QGraphicsItem *parent = 0 138 159 #ifndef Q_QDOC 139 // obsolete argument160 // ### obsolete argument 140 161 , QGraphicsScene *scene = 0 141 162 #endif … … 147 168 QGraphicsItem *parentItem() const; 148 169 QGraphicsItem *topLevelItem() const; 170 QGraphicsObject *parentObject() const; 149 171 QGraphicsWidget *parentWidget() const; 150 172 QGraphicsWidget *topLevelWidget() const; 151 173 QGraphicsWidget *window() const; 174 QGraphicsItem *panel() const; 152 175 void setParentItem(QGraphicsItem *parent); 153 176 QList<QGraphicsItem *> children() const; // ### obsolete … … 155 178 bool isWidget() const; 156 179 bool isWindow() const; 180 bool isPanel() const; 181 182 QGraphicsObject *toGraphicsObject(); 183 const QGraphicsObject *toGraphicsObject() const; 157 184 158 185 QGraphicsItemGroup *group() const; … … 165 192 CacheMode cacheMode() const; 166 193 void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize()); 194 195 PanelModality panelModality() const; 196 void setPanelModality(PanelModality panelModality); 197 bool isBlockedByModalPanel(QGraphicsItem **blockingPanel = 0) const; 167 198 168 199 #ifndef QT_NO_TOOLTIP … … 197 228 void setOpacity(qreal opacity); 198 229 230 #ifndef QT_NO_GRAPHICSEFFECT 231 // Effect 232 QGraphicsEffect *graphicsEffect() const; 233 void setGraphicsEffect(QGraphicsEffect *effect); 234 #endif //QT_NO_GRAPHICSEFFECT 235 199 236 Qt::MouseButtons acceptedMouseButtons() const; 200 237 void setAcceptedMouseButtons(Qt::MouseButtons buttons); 201 238 202 bool acceptsHoverEvents() const; // obsolete203 void setAcceptsHoverEvents(bool enabled); // obsolete239 bool acceptsHoverEvents() const; // ### obsolete 240 void setAcceptsHoverEvents(bool enabled); // ### obsolete 204 241 bool acceptHoverEvents() const; 205 242 void setAcceptHoverEvents(bool enabled); 243 bool acceptTouchEvents() const; 244 void setAcceptTouchEvents(bool enabled); 245 246 bool filtersChildEvents() const; 247 void setFiltersChildEvents(bool enabled); 206 248 207 249 bool handlesChildEvents() const; 208 250 void setHandlesChildEvents(bool enabled); 251 252 bool isActive() const; 253 void setActive(bool active); 209 254 210 255 bool hasFocus() const; 211 256 void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason); 212 257 void clearFocus(); 258 259 QGraphicsItem *focusProxy() const; 260 void setFocusProxy(QGraphicsItem *item); 261 262 QGraphicsItem *focusItem() const; 263 QGraphicsItem *focusScopeItem() const; 213 264 214 265 void grabMouse(); … … 220 271 QPointF pos() const; 221 272 inline qreal x() const { return pos().x(); } 273 void setX(qreal x); 222 274 inline qreal y() const { return pos().y(); } 275 void setY(qreal y); 223 276 QPointF scenePos() const; 224 277 void setPos(const QPointF &pos); … … 240 293 void setTransform(const QTransform &matrix, bool combine = false); 241 294 void resetTransform(); 242 243 void rotate(qreal angle); 244 void scale(qreal sx, qreal sy); 245 void shear(qreal sh, qreal sv); 246 void translate(qreal dx, qreal dy); 295 296 void rotate(qreal angle); // ### obsolete 297 void scale(qreal sx, qreal sy); // ### obsolete 298 void shear(qreal sh, qreal sv); // ### obsolete 299 void translate(qreal dx, qreal dy); // ### obsolete 300 301 void setRotation(qreal angle); 302 qreal rotation() const; 303 304 void setScale(qreal scale); 305 qreal scale() const; 306 307 QList<QGraphicsTransform *> transformations() const; 308 void setTransformations(const QList<QGraphicsTransform *> &transformations); 309 310 QPointF transformOriginPoint() const; 311 void setTransformOriginPoint(const QPointF &origin); 312 inline void setTransformOriginPoint(qreal ax, qreal ay) 313 { setTransformOriginPoint(QPointF(ax,ay)); } 314 247 315 virtual void advance(int phase); 248 316 … … 250 318 qreal zValue() const; 251 319 void setZValue(qreal z); 320 void stackBefore(const QGraphicsItem *sibling); 252 321 253 322 // Hit test … … 337 406 void setData(int key, const QVariant &value); 338 407 408 Qt::InputMethodHints inputMethodHints() const; 409 void setInputMethodHints(Qt::InputMethodHints hints); 410 339 411 enum { 340 412 Type = 1, … … 381 453 QGraphicsItem(QGraphicsItemPrivate &dd, 382 454 QGraphicsItem *parent, QGraphicsScene *scene); 383 Q GraphicsItemPrivate *d_ptr;455 QScopedPointer<QGraphicsItemPrivate> d_ptr; 384 456 385 457 void addToIndex(); … … 394 466 friend class QGraphicsScenePrivate; 395 467 friend class QGraphicsSceneFindItemBspTreeVisitor; 468 friend class QGraphicsSceneBspTree; 396 469 friend class QGraphicsView; 397 470 friend class QGraphicsViewPrivate; 471 friend class QGraphicsObject; 398 472 friend class QGraphicsWidget; 399 473 friend class QGraphicsWidgetPrivate; 400 474 friend class QGraphicsProxyWidgetPrivate; 475 friend class QGraphicsSceneIndex; 476 friend class QGraphicsSceneIndexPrivate; 477 friend class QGraphicsSceneBspTreeIndex; 478 friend class QGraphicsSceneBspTreeIndexPrivate; 479 friend class QGraphicsItemEffectSourcePrivate; 480 friend class QGraphicsTransformPrivate; 481 friend class QGestureManager; 401 482 friend class ::tst_QGraphicsItem; 402 483 friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); … … 405 486 406 487 Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags) 488 Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem") 407 489 408 490 inline void QGraphicsItem::setPos(qreal ax, qreal ay) … … 451 533 { return mapRectFromScene(QRectF(ax, ay, w, h)); } 452 534 535 536 class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem 537 { 538 Q_OBJECT 539 Q_PROPERTY(QGraphicsObject * parent READ parentObject WRITE setParentItem NOTIFY parentChanged DESIGNABLE false) 540 Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL) 541 Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) 542 Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL) 543 Q_PROPERTY(QPointF pos READ pos WRITE setPos) 544 Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged) 545 Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged) 546 Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged) 547 Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) 548 Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) 549 Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint) 550 Q_INTERFACES(QGraphicsItem) 551 public: 552 QGraphicsObject(QGraphicsItem *parent = 0); 553 554 // ### Qt 5: Disambiguate 555 #ifdef Q_NO_USING_KEYWORD 556 const QObjectList &children() const { return QObject::children(); } 557 #else 558 using QObject::children; 559 #endif 560 561 void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags()); 562 void ungrabGesture(Qt::GestureType type); 563 564 Q_SIGNALS: 565 void parentChanged(); 566 void opacityChanged(); 567 void visibleChanged(); 568 void enabledChanged(); 569 void xChanged(); 570 void yChanged(); 571 void zChanged(); 572 void rotationChanged(); 573 void scaleChanged(); 574 575 protected: 576 QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene); 577 private: 578 friend class QGraphicsItem; 579 friend class QGraphicsItemPrivate; 580 }; 581 582 453 583 class QAbstractGraphicsShapeItemPrivate; 454 584 class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem … … 457 587 QAbstractGraphicsShapeItem(QGraphicsItem *parent = 0 458 588 #ifndef Q_QDOC 459 // obsolete argument589 // ### obsolete argument 460 590 , QGraphicsScene *scene = 0 461 591 #endif … … 487 617 QGraphicsPathItem(QGraphicsItem *parent = 0 488 618 #ifndef Q_QDOC 489 // obsolete argument619 // ### obsolete argument 490 620 , QGraphicsScene *scene = 0 491 621 #endif … … 493 623 QGraphicsPathItem(const QPainterPath &path, QGraphicsItem *parent = 0 494 624 #ifndef Q_QDOC 495 // obsolete argument625 // ### obsolete argument 496 626 , QGraphicsScene *scene = 0 497 627 #endif … … 530 660 QGraphicsRectItem(QGraphicsItem *parent = 0 531 661 #ifndef Q_QDOC 532 // obsolete argument662 // ### obsolete argument 533 663 , QGraphicsScene *scene = 0 534 664 #endif … … 536 666 QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent = 0 537 667 #ifndef Q_QDOC 538 // obsolete argument668 // ### obsolete argument 539 669 , QGraphicsScene *scene = 0 540 670 #endif … … 542 672 QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 543 673 #ifndef Q_QDOC 544 // obsolete argument674 // ### obsolete argument 545 675 , QGraphicsScene *scene = 0 546 676 #endif … … 583 713 QGraphicsEllipseItem(QGraphicsItem *parent = 0 584 714 #ifndef Q_QDOC 585 // obsolete argument715 // ### obsolete argument 586 716 , QGraphicsScene *scene = 0 587 717 #endif … … 589 719 QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent = 0 590 720 #ifndef Q_QDOC 591 // obsolete argument721 // ### obsolete argument 592 722 , QGraphicsScene *scene = 0 593 723 #endif … … 595 725 QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 596 726 #ifndef Q_QDOC 597 // obsolete argument727 // ### obsolete argument 598 728 , QGraphicsScene *scene = 0 599 729 #endif … … 642 772 QGraphicsPolygonItem(QGraphicsItem *parent = 0 643 773 #ifndef Q_QDOC 644 // obsolete argument774 // ### obsolete argument 645 775 , QGraphicsScene *scene = 0 646 776 #endif … … 649 779 QGraphicsItem *parent = 0 650 780 #ifndef Q_QDOC 651 // obsolete argument781 // ### obsolete argument 652 782 , QGraphicsScene *scene = 0 653 783 #endif … … 689 819 QGraphicsLineItem(QGraphicsItem *parent = 0 690 820 #ifndef Q_QDOC 691 // obsolete argument821 // ### obsolete argument 692 822 , QGraphicsScene *scene = 0 693 823 #endif … … 695 825 QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent = 0 696 826 #ifndef Q_QDOC 697 // obsolete argument827 // ### obsolete argument 698 828 , QGraphicsScene *scene = 0 699 829 #endif … … 701 831 QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent = 0 702 832 #ifndef Q_QDOC 703 // obsolete argument833 // ### obsolete argument 704 834 , QGraphicsScene *scene = 0 705 835 #endif … … 749 879 QGraphicsPixmapItem(QGraphicsItem *parent = 0 750 880 #ifndef Q_QDOC 751 // obsolete argument881 // ### obsolete argument 752 882 , QGraphicsScene *scene = 0 753 883 #endif … … 755 885 QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0 756 886 #ifndef Q_QDOC 757 // obsolete argument887 // ### obsolete argument 758 888 , QGraphicsScene *scene = 0 759 889 #endif … … 802 932 class QTextDocument; 803 933 class QTextCursor; 804 class Q_GUI_EXPORT QGraphicsTextItem : public Q Object, public QGraphicsItem934 class Q_GUI_EXPORT QGraphicsTextItem : public QGraphicsObject 805 935 { 806 936 Q_OBJECT … … 811 941 QGraphicsTextItem(QGraphicsItem *parent = 0 812 942 #ifndef Q_QDOC 813 // obsolete argument943 // ### obsolete argument 814 944 , QGraphicsScene *scene = 0 815 945 #endif … … 817 947 QGraphicsTextItem(const QString &text, QGraphicsItem *parent = 0 818 948 #ifndef Q_QDOC 819 // obsolete argument949 // ### obsolete argument 820 950 , QGraphicsScene *scene = 0 821 951 #endif … … 912 1042 QGraphicsSimpleTextItem(QGraphicsItem *parent = 0 913 1043 #ifndef Q_QDOC 914 // obsolete argument1044 // ### obsolete argument 915 1045 , QGraphicsScene *scene = 0 916 1046 #endif … … 918 1048 QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent = 0 919 1049 #ifndef Q_QDOC 920 // obsolete argument1050 // ### obsolete argument 921 1051 , QGraphicsScene *scene = 0 922 1052 #endif … … 958 1088 QGraphicsItemGroup(QGraphicsItem *parent = 0 959 1089 #ifndef Q_QDOC 960 // obsolete argument1090 // ### obsolete argument 961 1091 , QGraphicsScene *scene = 0 962 1092 #endif … … 995 1125 #ifndef QT_NO_DEBUG_STREAM 996 1126 Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem *item); 1127 Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsObject *item); 997 1128 Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change); 998 1129 Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag); … … 1014 1145 1015 1146 #endif // QGRAPHICSITEM_H 1016 -
trunk/src/gui/graphicsview/qgraphicsitem_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 // 49 49 // This file is not part of the Qt API. It exists for the convenience 50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header51 // file may change from version toversion without notice, or even be removed.50 // of other Qt classes. This header file may change from version to 51 // version without notice, or even be removed. 52 52 // 53 53 // We mean it. … … 55 55 56 56 #include "qgraphicsitem.h" 57 #include "qset.h" 58 #include "qpixmapcache.h" 59 #include <private/qgraphicsview_p.h> 60 #include "qgraphicstransform.h" 61 #include <private/qgraphicstransform_p.h> 62 63 #include <private/qgraphicseffect_p.h> 64 #include <qgraphicseffect.h> 65 66 #include <QtCore/qpoint.h> 57 67 58 68 #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW … … 70 80 QRect boundingRect; 71 81 QSize fixedSize; 72 Q Stringkey;82 QPixmapCache::Key key; 73 83 74 84 // DeviceCoordinateCache only 75 85 struct DeviceData { 86 DeviceData() {} 76 87 QTransform lastTransform; 77 88 QPoint cacheIndent; 78 Q Stringkey;89 QPixmapCache::Key key; 79 90 }; 80 91 QMap<QPaintDevice *, DeviceData> deviceData; … … 88 99 }; 89 100 90 class Q_ AUTOTEST_EXPORT QGraphicsItemPrivate101 class Q_GUI_EXPORT QGraphicsItemPrivate 91 102 { 92 103 Q_DECLARE_PUBLIC(QGraphicsItem) 93 104 public: 94 105 enum Extra { 95 ExtraTransform,96 106 ExtraToolTip, 97 107 ExtraCursor, 98 108 ExtraCacheData, 99 109 ExtraMaxDeviceCoordCacheSize, 100 ExtraBoundingRegionGranularity, 101 ExtraOpacity, 102 ExtraEffectiveOpacity 110 ExtraBoundingRegionGranularity 103 111 }; 104 112 … … 107 115 AncestorHandlesChildEvents = 0x1, 108 116 AncestorClipsChildren = 0x2, 109 AncestorIgnoresTransformations = 0x4 117 AncestorIgnoresTransformations = 0x4, 118 AncestorFiltersChildEvents = 0x8 110 119 }; 111 120 112 121 inline QGraphicsItemPrivate() 113 122 : z(0), 123 opacity(1.), 114 124 scene(0), 115 125 parent(0), 126 transformData(0), 127 graphicsEffect(0), 116 128 index(-1), 117 depth(0), 129 siblingIndex(-1), 130 itemDepth(-1), 131 focusProxy(0), 132 subFocusItem(0), 133 focusScopeItem(0), 134 imHints(Qt::ImhNone), 135 panelModality(QGraphicsItem::NonModal), 118 136 acceptedMouseButtons(0x1f), 119 137 visible(1), … … 127 145 handlesChildEvents(0), 128 146 itemDiscovered(0), 129 hasTransform(0),130 147 hasCursor(0), 131 148 ancestorFlags(0), 132 149 cacheMode(0), 133 150 hasBoundingRegionGranularity(0), 134 flags(0),135 hasOpacity(0),136 hasEffectiveOpacity(0),137 151 isWidget(0), 138 152 dirty(0), 139 153 dirtyChildren(0), 140 154 localCollisionHack(0), 141 dirtyClipPath(1),142 emptyClipPath(0),143 155 inSetPosHelper(0), 144 allChildrenCombineOpacity(1), 156 needSortChildren(1), // ### can be 0 by default? 157 allChildrenDirty(0), 158 fullUpdatePending(0), 159 flags(0), 160 dirtyChildrenBoundingRect(1), 161 paintedViewBoundingRectsNeedRepaint(0), 162 dirtySceneTransform(1), 163 geometryChanged(1), 164 inDestructor(0), 165 isObject(0), 166 ignoreVisible(0), 167 ignoreOpacity(0), 168 acceptTouchEvents(0), 169 acceptedTouchBeginEvent(0), 170 filtersDescendantEvents(0), 171 sceneTransformTranslateOnly(0), 172 notifyBoundingRectChanged(0), 173 notifyInvalidated(0), 174 mouseSetsFocus(1), 175 explicitActivate(0), 176 wantsActive(0), 177 holesInSiblingIndex(0), 178 sequentialOrdering(1), 179 updateDueToGraphicsEffect(0), 180 scenePosDescendants(0), 145 181 globalStackingOrder(-1), 146 sceneTransformIndex(-1),147 182 q_ptr(0) 148 183 { … … 151 186 inline virtual ~QGraphicsItemPrivate() 152 187 { } 188 189 static const QGraphicsItemPrivate *get(const QGraphicsItem *item) 190 { 191 return item->d_ptr.data(); 192 } 193 static QGraphicsItemPrivate *get(QGraphicsItem *item) 194 { 195 return item->d_ptr.data(); 196 } 153 197 154 198 void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, … … 157 201 void remapItemPos(QEvent *event, QGraphicsItem *item); 158 202 QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; 159 bool itemIsUntransformable() const; 203 inline bool itemIsUntransformable() const 204 { 205 return (flags & QGraphicsItem::ItemIgnoresTransformations) 206 || (ancestorFlags & AncestorIgnoresTransformations); 207 } 208 209 void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; 210 void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; 211 virtual void updateSceneTransformFromParent(); 160 212 161 213 // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. … … 163 215 static bool movableAncestorIsSelected(const QGraphicsItem *item); 164 216 165 void setPosHelper(const QPointF &pos); 217 virtual void setPosHelper(const QPointF &pos); 218 void setTransformHelper(const QTransform &transform); 219 void appendGraphicsTransform(QGraphicsTransform *t); 166 220 void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); 167 221 void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); 168 bool discardUpdateRequest(bool ignoreClipping = false, 169 bool ignoreVisibleBit = false, 170 bool ignoreDirtyBit = false) const; 171 void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false); 172 void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false); 173 void updateEffectiveOpacity(); 174 void resolveEffectiveOpacity(qreal effectiveParentOpacity); 175 void resolveDepth(int parentDepth); 176 void invalidateSceneTransformCache(); 222 bool discardUpdateRequest(bool ignoreVisibleBit = false, 223 bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; 224 int depth() const; 225 #ifndef QT_NO_GRAPHICSEFFECT 226 void invalidateGraphicsEffectsRecursively(); 227 #endif //QT_NO_GRAPHICSEFFECT 228 void invalidateDepthRecursively(); 229 void resolveDepth(); 230 void addChild(QGraphicsItem *child); 231 void removeChild(QGraphicsItem *child); 232 void setParentItemHelper(QGraphicsItem *parent); 233 void childrenBoundingRectHelper(QTransform *x, QRectF *rect); 234 void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, 235 const QRegion &exposedRegion, bool allItems = false) const; 236 QRectF effectiveBoundingRect() const; 237 QRectF sceneEffectiveBoundingRect() const; 238 239 QRectF effectiveBoundingRect(const QRectF &rect) const; 177 240 178 241 virtual void resolveFont(uint inheritedMask) … … 238 301 { return type < extra; } 239 302 }; 303 240 304 QList<ExtraStruct> extras; 241 305 306 QGraphicsItemCache *maybeExtraItemCache() const; 242 307 QGraphicsItemCache *extraItemCache() const; 243 308 void removeExtraItemCache(); 244 309 245 inline void setCachedClipPath(const QPainterPath &path) 246 { 247 cachedClipPath = path; 248 dirtyClipPath = 0; 249 emptyClipPath = 0; 250 } 251 252 inline void setEmptyCachedClipPath() 253 { 254 emptyClipPath = 1; 255 dirtyClipPath = 0; 256 } 257 258 void setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect = QRectF()); 259 260 inline void invalidateCachedClipPath() 261 { /*static int count = 0 ;qWarning("%i", ++count);*/ dirtyClipPath = 1; emptyClipPath = 0; } 262 263 void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); 264 void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); 310 void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem); 311 inline void ensureSceneTransform() 312 { 313 QGraphicsItem *that = q_func(); 314 ensureSceneTransformRecursive(&that); 315 } 316 317 inline bool hasTranslateOnlySceneTransform() 318 { 319 ensureSceneTransform(); 320 return sceneTransformTranslateOnly; 321 } 322 323 inline void invalidateChildrenSceneTransform() 324 { 325 for (int i = 0; i < children.size(); ++i) 326 children.at(i)->d_ptr->dirtySceneTransform = 1; 327 } 328 329 inline qreal calcEffectiveOpacity() const 330 { 331 qreal o = opacity; 332 QGraphicsItem *p = parent; 333 int myFlags = flags; 334 while (p) { 335 int parentFlags = p->d_ptr->flags; 336 337 // If I have a parent, and I don't ignore my parent's opacity, and my 338 // parent propagates to me, then combine my local opacity with my parent's 339 // effective opacity into my effective opacity. 340 if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity) 341 || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { 342 break; 343 } 344 345 o *= p->d_ptr->opacity; 346 p = p->d_ptr->parent; 347 myFlags = parentFlags; 348 } 349 return o; 350 } 265 351 266 352 inline bool isFullyTransparent() const 267 { return hasEffectiveOpacity && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0)); } 353 { 354 if (opacity < 0.001) 355 return true; 356 if (!parent) 357 return false; 358 359 return calcEffectiveOpacity() < 0.001; 360 } 361 362 inline qreal effectiveOpacity() const { 363 if (!parent || !opacity) 364 return opacity; 365 366 return calcEffectiveOpacity(); 367 } 368 369 inline qreal combineOpacityFromParent(qreal parentOpacity) const 370 { 371 if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity) 372 && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { 373 return parentOpacity * opacity; 374 } 375 return opacity; 376 } 268 377 269 378 inline bool childrenCombineOpacity() const 270 { return allChildrenCombineOpacity || children.isEmpty(); } 271 272 inline bool isClippedAway() const 273 { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } 379 { 380 if (!children.size()) 381 return true; 382 if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) 383 return false; 384 385 for (int i = 0; i < children.size(); ++i) { 386 if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity) 387 return false; 388 } 389 return true; 390 } 274 391 275 392 inline bool childrenClippedToShape() const … … 278 395 inline bool isInvisible() const 279 396 { 280 return !visible 281 || (childrenClippedToShape() && isClippedAway()) 282 || (childrenCombineOpacity() && isFullyTransparent()); 283 } 284 285 QPainterPath cachedClipPath; 397 return !visible || (childrenCombineOpacity() && isFullyTransparent()); 398 } 399 400 void setFocusHelper(Qt::FocusReason focusReason, bool climb); 401 void setSubFocus(QGraphicsItem *rootItem = 0); 402 void clearSubFocus(QGraphicsItem *rootItem = 0); 403 void resetFocusProxy(); 404 virtual void subFocusItemChange(); 405 406 inline QTransform transformToParent() const; 407 inline void ensureSortedChildren(); 408 static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b); 409 void ensureSequentialSiblingIndex(); 410 inline void sendScenePosChange(); 411 virtual void siblingOrderChange(); 412 413 QRectF childrenBoundingRect; 414 QRectF needsRepaint; 415 QMap<QWidget *, QRect> paintedViewBoundingRects; 286 416 QPointF pos; 287 417 qreal z; 418 qreal opacity; 288 419 QGraphicsScene *scene; 289 420 QGraphicsItem *parent; 290 421 QList<QGraphicsItem *> children; 422 struct TransformData; 423 TransformData *transformData; 424 QGraphicsEffect *graphicsEffect; 425 QTransform sceneTransform; 291 426 int index; 292 int depth; 293 294 // Packed 32 bytes 427 int siblingIndex; 428 int itemDepth; // Lazily calculated when calling depth(). 429 QGraphicsItem *focusProxy; 430 QList<QGraphicsItem **> focusProxyRefs; 431 QGraphicsItem *subFocusItem; 432 QGraphicsItem *focusScopeItem; 433 Qt::InputMethodHints imHints; 434 QGraphicsItem::PanelModality panelModality; 435 QMap<Qt::GestureType, Qt::GestureFlags> gestureContext; 436 437 // Packed 32 bits 295 438 quint32 acceptedMouseButtons : 5; 296 439 quint32 visible : 1; … … 304 447 quint32 handlesChildEvents : 1; 305 448 quint32 itemDiscovered : 1; 306 quint32 hasTransform : 1;307 449 quint32 hasCursor : 1; 308 quint32 ancestorFlags : 3;450 quint32 ancestorFlags : 4; 309 451 quint32 cacheMode : 2; 310 452 quint32 hasBoundingRegionGranularity : 1; 311 quint32 flags : 9;312 313 // New 32 bytes314 quint32 hasOpacity : 1;315 quint32 hasEffectiveOpacity : 1;316 453 quint32 isWidget : 1; 317 quint32 dirty : 1; 318 quint32 dirtyChildren : 1; 454 quint32 dirty : 1; 455 quint32 dirtyChildren : 1; 319 456 quint32 localCollisionHack : 1; 320 quint32 dirtyClipPath : 1;321 quint32 emptyClipPath : 1;322 457 quint32 inSetPosHelper : 1; 323 quint32 allChildrenCombineOpacity : 1; 458 quint32 needSortChildren : 1; 459 quint32 allChildrenDirty : 1; 460 461 // Packed 32 bits 462 quint32 fullUpdatePending : 1; 463 quint32 flags : 17; 464 quint32 dirtyChildrenBoundingRect : 1; 465 quint32 paintedViewBoundingRectsNeedRepaint : 1; 466 quint32 dirtySceneTransform : 1; 467 quint32 geometryChanged : 1; 468 quint32 inDestructor : 1; 469 quint32 isObject : 1; 470 quint32 ignoreVisible : 1; 471 quint32 ignoreOpacity : 1; 472 quint32 acceptTouchEvents : 1; 473 quint32 acceptedTouchBeginEvent : 1; 474 quint32 filtersDescendantEvents : 1; 475 quint32 sceneTransformTranslateOnly : 1; 476 quint32 notifyBoundingRectChanged : 1; 477 quint32 notifyInvalidated : 1; 478 479 // New 32 bits 480 quint32 mouseSetsFocus : 1; 481 quint32 explicitActivate : 1; 482 quint32 wantsActive : 1; 483 quint32 holesInSiblingIndex : 1; 484 quint32 sequentialOrdering : 1; 485 quint32 updateDueToGraphicsEffect : 1; 486 quint32 scenePosDescendants : 1; 324 487 325 488 // Optional stacking order 326 489 int globalStackingOrder; 327 int sceneTransformIndex;328 329 490 QGraphicsItem *q_ptr; 330 491 }; 331 492 493 struct QGraphicsItemPrivate::TransformData 494 { 495 QTransform transform; 496 qreal scale; 497 qreal rotation; 498 qreal xOrigin; 499 qreal yOrigin; 500 QList<QGraphicsTransform *> graphicsTransforms; 501 bool onlyTransform; 502 503 TransformData() : 504 scale(1.0), rotation(0.0), 505 xOrigin(0.0), yOrigin(0.0), 506 onlyTransform(true) 507 { } 508 509 QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const 510 { 511 if (onlyTransform) { 512 if (!postmultiplyTransform || postmultiplyTransform->isIdentity()) 513 return transform; 514 if (transform.isIdentity()) 515 return *postmultiplyTransform; 516 return transform * *postmultiplyTransform; 517 } 518 519 QTransform x(transform); 520 if (!graphicsTransforms.isEmpty()) { 521 QMatrix4x4 m; 522 for (int i = 0; i < graphicsTransforms.size(); ++i) 523 graphicsTransforms.at(i)->applyTo(&m); 524 x *= m.toTransform(); 525 } 526 x.translate(xOrigin, yOrigin); 527 x.rotate(rotation); 528 x.scale(scale, scale); 529 x.translate(-xOrigin, -yOrigin); 530 if (postmultiplyTransform) 531 x *= *postmultiplyTransform; 532 return x; 533 } 534 }; 535 536 struct QGraphicsItemPaintInfo 537 { 538 inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2, 539 const QTransform *const xform3, 540 QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt, 541 QPainter *p, qreal o, bool b1, bool b2) 542 : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w), 543 option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2) 544 {} 545 546 const QTransform *viewTransform; 547 const QTransform *transformPtr; 548 const QTransform *effectTransform; 549 QRegion *exposedRegion; 550 QWidget *widget; 551 QStyleOptionGraphicsItem *option; 552 QPainter *painter; 553 qreal opacity; 554 quint32 wasDirtySceneTransform : 1; 555 quint32 drawItem : 1; 556 }; 557 558 #ifndef QT_NO_GRAPHICSEFFECT 559 class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate 560 { 561 public: 562 QGraphicsItemEffectSourcePrivate(QGraphicsItem *i) 563 : QGraphicsEffectSourcePrivate(), item(i), info(0) 564 {} 565 566 inline void detach() 567 { 568 item->d_ptr->graphicsEffect = 0; 569 item->prepareGeometryChange(); 570 } 571 572 inline const QGraphicsItem *graphicsItem() const 573 { return item; } 574 575 inline const QWidget *widget() const 576 { return 0; } 577 578 inline void update() { 579 item->d_ptr->updateDueToGraphicsEffect = true; 580 item->update(); 581 item->d_ptr->updateDueToGraphicsEffect = false; 582 } 583 584 inline void effectBoundingRectChanged() 585 { item->prepareGeometryChange(); } 586 587 inline bool isPixmap() const 588 { 589 return item->type() == QGraphicsPixmapItem::Type 590 && !(item->flags() & QGraphicsItem::ItemIsSelectable) 591 && item->d_ptr->children.size() == 0; 592 //|| (item->d_ptr->isObject && qobject_cast<QmlGraphicsImage *>(q_func())); 593 } 594 595 inline const QStyleOption *styleOption() const 596 { return info ? info->option : 0; } 597 598 inline QRect deviceRect() const 599 { 600 if (!info || !info->widget) { 601 qWarning("QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context"); 602 return QRect(); 603 } 604 return info->widget->rect(); 605 } 606 607 QRectF boundingRect(Qt::CoordinateSystem system) const; 608 void draw(QPainter *); 609 QPixmap pixmap(Qt::CoordinateSystem system, 610 QPoint *offset, 611 QGraphicsEffect::PixmapPadMode mode) const; 612 613 QGraphicsItem *item; 614 QGraphicsItemPaintInfo *info; 615 QTransform lastEffectTransform; 616 }; 617 #endif //QT_NO_GRAPHICSEFFECT 618 619 /*! 620 Returns true if \a item1 is on top of \a item2. 621 The items dont need to be siblings. 622 623 \internal 624 */ 625 inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2) 626 { 627 // Siblings? Just check their z-values. 628 const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); 629 const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); 630 if (d1->parent == d2->parent) 631 return qt_closestLeaf(item1, item2); 632 633 // Find common ancestor, and each item's ancestor closest to the common 634 // ancestor. 635 int item1Depth = d1->depth(); 636 int item2Depth = d2->depth(); 637 const QGraphicsItem *p = item1; 638 const QGraphicsItem *t1 = item1; 639 while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { 640 if (p == item2) { 641 // item2 is one of item1's ancestors; item1 is on top 642 return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); 643 } 644 t1 = p; 645 --item1Depth; 646 } 647 p = item2; 648 const QGraphicsItem *t2 = item2; 649 while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { 650 if (p == item1) { 651 // item1 is one of item2's ancestors; item1 is not on top 652 return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); 653 } 654 t2 = p; 655 --item2Depth; 656 } 657 658 // item1Ancestor is now at the same level as item2Ancestor, but not the same. 659 const QGraphicsItem *p1 = t1; 660 const QGraphicsItem *p2 = t2; 661 while (t1 && t1 != t2) { 662 p1 = t1; 663 p2 = t2; 664 t1 = t1->d_ptr->parent; 665 t2 = t2->d_ptr->parent; 666 } 667 668 // in case we have a common ancestor, we compare the immediate children in the ancestor's path. 669 // otherwise we compare the respective items' topLevelItems directly. 670 return qt_closestLeaf(p1, p2); 671 } 672 673 /*! 674 Returns true if \a item2 is on top of \a item1. 675 The items dont need to be siblings. 676 677 \internal 678 */ 679 inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2) 680 { 681 return qt_closestItemFirst(item2, item1); 682 } 683 684 /*! 685 \internal 686 */ 687 inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) 688 { 689 // Return true if sibling item1 is on top of item2. 690 const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); 691 const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); 692 bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; 693 bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; 694 if (f1 != f2) 695 return f2; 696 if (d1->z != d2->z) 697 return d1->z > d2->z; 698 return d1->siblingIndex > d2->siblingIndex; 699 } 700 701 /*! 702 \internal 703 */ 704 inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) 705 { return qt_closestLeaf(item2, item1); } 706 707 /* 708 return the full transform of the item to the parent. This include the position and all the transform data 709 */ 710 inline QTransform QGraphicsItemPrivate::transformToParent() const 711 { 712 QTransform matrix; 713 combineTransformToParent(&matrix); 714 return matrix; 715 } 716 717 /*! 718 \internal 719 */ 720 inline void QGraphicsItemPrivate::ensureSortedChildren() 721 { 722 if (needSortChildren) { 723 qSort(children.begin(), children.end(), qt_notclosestLeaf); 724 needSortChildren = 0; 725 sequentialOrdering = 1; 726 for (int i = 0; i < children.size(); ++i) { 727 if (children[i]->d_ptr->siblingIndex != i) { 728 sequentialOrdering = 0; 729 break; 730 } 731 } 732 } 733 } 734 735 /*! 736 \internal 737 */ 738 inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b) 739 { 740 return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex; 741 } 742 332 743 QT_END_NAMESPACE 333 744 -
trunk/src/gui/graphicsview/qgraphicsitemanimation.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 support for QGraphicsItem. 46 46 \since 4.2 47 \ingroup multimedia48 47 \ingroup graphicsview-api 48 \deprecated 49 49 50 50 The QGraphicsItemAnimation class animates a QGraphicsItem. You can -
trunk/src/gui/graphicsview/qgraphicsitemanimation.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/gui/graphicsview/qgraphicslayout.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 58 58 in Graphics View. 59 59 \since 4.4 60 \ingroup multimedia61 60 \ingroup graphicsview-api 62 61 … … 150 149 \a parent is passed to QGraphicsLayoutItem's constructor and the 151 150 QGraphicsLayoutItem's isLayout argument is set to \e true. 151 152 If \a parent is a QGraphicsWidget the layout will be installed 153 on that widget. (Note that installing a layout will delete the old one 154 installed.) 152 155 */ 153 156 QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent) … … 392 395 reimplementation can assume that \a i is valid (i.e., it respects the 393 396 value of count()). 394 395 The subclass is free to decide how to store the items. 397 Together with count(), it is provided as a means of iterating over all items in a layout. 398 399 The subclass is free to decide how to store the items, and the visual arrangement 400 does not have to be reflected through this function. 396 401 397 402 \sa count(), removeAt() … … 419 424 */ 420 425 426 /*! 427 \since 4.6 428 429 This function is a convenience function provided for custom layouts, and will go through 430 all items in the layout and reparent their graphics items to the closest QGraphicsWidget 431 ancestor of the layout. 432 433 If \a layoutItem is already in a different layout, it will be removed from that layout. 434 435 If custom layouts want special behaviour they can ignore to use this function, and implement 436 their own behaviour. 437 438 \sa graphicsItem() 439 */ 440 void QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) 441 { 442 Q_D(QGraphicsLayout); 443 d->addChildLayoutItem(layoutItem); 444 } 445 421 446 QT_END_NAMESPACE 422 447 -
trunk/src/gui/graphicsview/qgraphicslayout.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 79 79 protected: 80 80 QGraphicsLayout(QGraphicsLayoutPrivate &, QGraphicsLayoutItem *); 81 void addChildLayoutItem(QGraphicsLayoutItem *layoutItem); 81 82 82 83 private: … … 85 86 friend class QGraphicsWidget; 86 87 }; 88 89 Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout") 87 90 88 91 #endif -
trunk/src/gui/graphicsview/qgraphicslayout_p.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 121 121 return false; 122 122 123 QGraphicsLayoutItem *child;124 for (int i = 0; (child = lay->itemAt(i)); ++i) {123 for (int i = lay->count() - 1; i >= 0; --i) { 124 QGraphicsLayoutItem *child = lay->itemAt(i); 125 125 if (child && child->isLayout()) { 126 126 if (removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(child), layoutItem)) -
trunk/src/gui/graphicsview/qgraphicslayout_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 // 49 49 // This file is not part of the Qt API. It exists for the convenience 50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header51 // file may change from version toversion without notice, or even be removed.50 // of other Qt classes. This header file may change from version to 51 // version without notice, or even be removed. 52 52 // 53 53 // We mean it. … … 61 61 #include "qgraphicslayoutitem_p.h" 62 62 #include <QtGui/qstyle.h> 63 #include <QtGui/qwidget.h> 64 #include <QtGui/qstyleoption.h> 63 65 64 66 QT_BEGIN_NAMESPACE … … 76 78 } 77 79 #endif 80 81 82 class QLayoutStyleInfo 83 { 84 public: 85 inline QLayoutStyleInfo() { invalidate(); } 86 inline QLayoutStyleInfo(QStyle *style, QWidget *widget) 87 : m_valid(true), m_style(style), m_widget(widget) 88 { 89 Q_ASSERT(style); 90 if (widget) //### 91 m_styleOption.initFrom(widget); 92 m_defaultSpacing[0] = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); 93 m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing); 94 } 95 96 inline void invalidate() { m_valid = false; m_style = 0; m_widget = 0; } 97 98 inline QStyle *style() const { return m_style; } 99 inline QWidget *widget() const { return m_widget; } 100 101 inline bool operator==(const QLayoutStyleInfo &other) 102 { return m_style == other.m_style && m_widget == other.m_widget; } 103 inline bool operator!=(const QLayoutStyleInfo &other) 104 { return !(*this == other); } 105 106 inline void setDefaultSpacing(Qt::Orientation o, qreal spacing){ 107 if (spacing >= 0) 108 m_defaultSpacing[o - 1] = spacing; 109 } 110 111 inline qreal defaultSpacing(Qt::Orientation o) const { 112 return m_defaultSpacing[o - 1]; 113 } 114 115 inline qreal perItemSpacing(QSizePolicy::ControlType control1, 116 QSizePolicy::ControlType control2, 117 Qt::Orientation orientation) const 118 { 119 Q_ASSERT(style()); 120 return style()->layoutSpacing(control1, control2, orientation, &m_styleOption, widget()); 121 } 122 private: 123 bool m_valid; 124 QStyle *m_style; 125 QWidget *m_widget; 126 QStyleOption m_styleOption; 127 qreal m_defaultSpacing[2]; 128 }; 78 129 79 130 class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPrivate -
trunk/src/gui/graphicsview/qgraphicslayoutitem.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 109 109 */ 110 110 QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout) 111 : parent(par), isLayout(layout), ownedByLayout(false), graphicsItem(0) 112 { 111 : parent(par), userSizeHints(0), isLayout(layout), ownedByLayout(false), graphicsItem(0) 112 { 113 } 114 115 /*! 116 \internal 117 */ 118 QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate() 119 { 120 // Remove any lazily allocated data 121 delete[] userSizeHints; 113 122 } 114 123 … … 133 142 for (int i = 0; i < Qt::NSizeHints; ++i) { 134 143 cachedSizeHints[i] = constraint; 135 combineSize(cachedSizeHints[i], userSizeHints[i]); 144 if (userSizeHints) 145 combineSize(cachedSizeHints[i], userSizeHints[i]); 136 146 } 137 147 … … 199 209 200 210 /*! 211 \internal 212 213 Ensures that userSizeHints is allocated. 214 This function must be called before any dereferencing. 215 */ 216 void QGraphicsLayoutItemPrivate::ensureUserSizeHints() 217 { 218 if (!userSizeHints) 219 userSizeHints = new QSizeF[Qt::NSizeHints]; 220 } 221 222 /*! 223 \internal 224 225 Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint. 226 */ 227 void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size) 228 { 229 Q_Q(QGraphicsLayoutItem); 230 231 if (userSizeHints) { 232 if (size == userSizeHints[which]) 233 return; 234 } else if (!size.isValid()) { 235 return; 236 } 237 238 ensureUserSizeHints(); 239 userSizeHints[which] = size; 240 q->updateGeometry(); 241 } 242 243 /*! 244 \internal 245 246 Sets the width of the user size hint \a which to \a width. 247 */ 248 void QGraphicsLayoutItemPrivate::setSizeComponent( 249 Qt::SizeHint which, SizeComponent component, qreal value) 250 { 251 Q_Q(QGraphicsLayoutItem); 252 ensureUserSizeHints(); 253 qreal &userValue = (component == Width) 254 ? userSizeHints[which].rwidth() 255 : userSizeHints[which].rheight(); 256 if (value == userValue) 257 return; 258 userValue = value; 259 q->updateGeometry(); 260 } 261 262 /*! 201 263 \class QGraphicsLayoutItem 202 264 \brief The QGraphicsLayoutItem class can be inherited to allow your custom 203 265 items to be managed by layouts. 204 266 \since 4.4 205 \ingroup multimedia206 267 \ingroup graphicsview-api 207 268 … … 256 317 protected constructor, or by calling setParentLayoutItem(). The 257 318 parentLayoutItem() function returns a pointer to the item's layoutItem 258 parent. If the item's parent is 0 or if the theparent does not inherit319 parent. If the item's parent is 0 or if the parent does not inherit 259 320 from QGraphicsItem, the parentLayoutItem() function then returns 0. 260 321 isLayout() returns true if the QGraphicsLayoutItem subclass is itself a … … 308 369 } 309 370 } 310 delete d_ptr;311 371 } 312 372 … … 382 442 void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size) 383 443 { 384 Q_D(QGraphicsLayoutItem); 385 if (size == d->userSizeHints[Qt::MinimumSize]) 386 return; 387 388 d->userSizeHints[Qt::MinimumSize] = size; 389 updateGeometry(); 444 d_ptr->setSize(Qt::MinimumSize, size); 390 445 } 391 446 … … 417 472 void QGraphicsLayoutItem::setMinimumWidth(qreal width) 418 473 { 419 Q_D(QGraphicsLayoutItem); 420 qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rwidth(); 421 if (width == userSizeHint) 422 return; 423 userSizeHint = width; 424 updateGeometry(); 474 d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Width, width); 425 475 } 426 476 … … 432 482 void QGraphicsLayoutItem::setMinimumHeight(qreal height) 433 483 { 434 Q_D(QGraphicsLayoutItem); 435 qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rheight(); 436 if (height == userSizeHint) 437 return; 438 userSizeHint = height; 439 updateGeometry(); 484 d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Height, height); 440 485 } 441 486 … … 451 496 void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size) 452 497 { 453 Q_D(QGraphicsLayoutItem); 454 if (size == d->userSizeHints[Qt::PreferredSize]) 455 return; 456 457 d->userSizeHints[Qt::PreferredSize] = size; 458 updateGeometry(); 498 d_ptr->setSize(Qt::PreferredSize, size); 459 499 } 460 500 … … 486 526 void QGraphicsLayoutItem::setPreferredHeight(qreal height) 487 527 { 488 Q_D(QGraphicsLayoutItem); 489 qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rheight(); 490 if (height == userSizeHint) 491 return; 492 userSizeHint = height; 493 updateGeometry(); 528 d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Height, height); 494 529 } 495 530 … … 501 536 void QGraphicsLayoutItem::setPreferredWidth(qreal width) 502 537 { 503 Q_D(QGraphicsLayoutItem); 504 qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rwidth(); 505 if (width == userSizeHint) 506 return; 507 userSizeHint = width; 508 updateGeometry(); 538 d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Width, width); 509 539 } 510 540 … … 520 550 void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size) 521 551 { 522 Q_D(QGraphicsLayoutItem); 523 if (size == d->userSizeHints[Qt::MaximumSize]) 524 return; 525 526 d->userSizeHints[Qt::MaximumSize] = size; 527 updateGeometry(); 552 d_ptr->setSize(Qt::MaximumSize, size); 528 553 } 529 554 … … 555 580 void QGraphicsLayoutItem::setMaximumWidth(qreal width) 556 581 { 557 Q_D(QGraphicsLayoutItem); 558 qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rwidth(); 559 if (width == userSizeHint) 560 return; 561 userSizeHint = width; 562 updateGeometry(); 582 d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Width, width); 563 583 } 564 584 … … 570 590 void QGraphicsLayoutItem::setMaximumHeight(qreal height) 571 591 { 572 Q_D(QGraphicsLayoutItem); 573 qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rheight(); 574 if (height == userSizeHint) 575 return; 576 userSizeHint = height; 577 updateGeometry(); 592 d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Height, height); 578 593 } 579 594 … … 733 748 QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const 734 749 { 750 Q_D(const QGraphicsLayoutItem); 751 752 if (!d->userSizeHints && constraint.isValid()) 753 return constraint; 754 735 755 // ### should respect size policy??? 736 756 return d_ptr->effectiveSizeHints(constraint)[which]; … … 787 807 788 808 /*! 809 \since 4.6 810 789 811 Returns whether a layout should delete this item in its destructor. 790 812 If its true, then the layout will delete it. If its false, then it is … … 813 835 } 814 836 /*! 837 \since 4.6 838 815 839 Sets whether a layout should delete this item in its destructor or not. 816 840 \a ownership must be true to in order for the layout to delete it. -
trunk/src/gui/graphicsview/qgraphicslayoutitem.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 43 43 #define QGRAPHICSLAYOUTITEM_H 44 44 45 #include <QtCore/qscopedpointer.h> 45 46 #include <QtGui/qsizepolicy.h> 46 47 #include <QtGui/qevent.h> … … 113 114 114 115 virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const = 0; 115 Q GraphicsLayoutItemPrivate *d_ptr;116 QScopedPointer<QGraphicsLayoutItemPrivate> d_ptr; 116 117 117 118 private: … … 121 122 friend class QGraphicsLayout; 122 123 }; 124 125 Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem") 123 126 124 127 inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah) -
trunk/src/gui/graphicsview/qgraphicslayoutitem_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 // 49 49 // This file is not part of the Qt API. It exists for the convenience 50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header51 // file may change from version toversion without notice, or even be removed.50 // of other Qt classes. This header file may change from version to 51 // version without notice, or even be removed. 52 52 // 53 53 // We mean it. … … 64 64 Q_DECLARE_PUBLIC(QGraphicsLayoutItem) 65 65 public: 66 virtual ~QGraphicsLayoutItemPrivate() {}66 virtual ~QGraphicsLayoutItemPrivate(); 67 67 QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout); 68 68 void init(); 69 69 QSizeF *effectiveSizeHints(const QSizeF &constraint) const; 70 70 QGraphicsItem *parentItem() const; 71 void ensureUserSizeHints(); 72 void setSize(Qt::SizeHint which, const QSizeF &size); 73 enum SizeComponent { Width, Height }; 74 void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value); 71 75 72 76 QSizePolicy sizePolicy; 73 77 QGraphicsLayoutItem *parent; 74 78 75 QSizeF userSizeHints[Qt::NSizeHints];79 QSizeF *userSizeHints; 76 80 mutable QSizeF cachedSizeHints[Qt::NSizeHints]; 77 81 mutable QSizeF cachedConstraint; -
trunk/src/gui/graphicsview/qgraphicslinearlayout.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 layout for managing widgets in Graphics View. 46 46 \since 4.4 47 \ingroup multimedia48 47 \ingroup graphicsview-api 49 48 … … 61 60 You can add widgets, layouts, stretches (addStretch(), insertStretch() or 62 61 setStretchFactor()), and spacings (setItemSpacing()) to a linear 63 layout. The layout takes ownership of the items. In some cases when the layout 62 layout. The layout takes ownership of the items. In some cases when the layout 64 63 item also inherits from QGraphicsItem (such as QGraphicsWidget) there will be a 65 64 ambiguity in ownership because the layout item belongs to two ownership hierarchies. … … 179 178 wid = new QWidget; 180 179 QGraphicsItem *item = parentItem(); 181 QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();180 QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style(); 182 181 return QLayoutStyleInfo(style, wid); 183 182 } … … 210 209 QGraphicsLayoutItem *item = itemAt(i); 211 210 // The following lines can be removed, but this removes the item 212 // from the layout more efficiently than the implementation of 211 // from the layout more efficiently than the implementation of 213 212 // ~QGraphicsLayoutItem. 214 213 removeAt(i); … … 274 273 return; 275 274 } 275 if (item == this) { 276 qWarning("QGraphicsLinearLayout::insertItem: cannot insert itself"); 277 return; 278 } 276 279 d->addChildLayoutItem(item); 277 280 … … 279 282 d->fixIndex(&index); 280 283 d->engine.insertRow(index, d->orientation); 281 new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index) );284 new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index); 282 285 invalidate(); 283 286 } … … 324 327 { 325 328 Q_D(QGraphicsLinearLayout); 326 if (QGridLayoutItem *gridItem = d->engine.itemAt(d->gridRow(index), d->gridColumn(index))) { 329 if (index < 0 || index >= d->engine.itemCount()) { 330 qWarning("QGraphicsLinearLayout::removeAt: invalid index %d", index); 331 return; 332 } 333 if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) { 327 334 if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem()) 328 335 layoutItem->setParentLayoutItem(0); … … 464 471 { 465 472 Q_D(const QGraphicsLinearLayout); 466 return d->engine. rowCount(d->orientation);473 return d->engine.itemCount(); 467 474 } 468 475 469 476 /*! 470 477 \reimp 478 When iterating from 0 and up, it will return the items in the visual arranged order. 471 479 */ 472 480 QGraphicsLayoutItem *QGraphicsLinearLayout::itemAt(int index) const 473 481 { 474 482 Q_D(const QGraphicsLinearLayout); 483 if (index < 0 || index >= d->engine.itemCount()) { 484 qWarning("QGraphicsLinearLayout::itemAt: invalid index %d", index); 485 return 0; 486 } 475 487 QGraphicsLayoutItem *item = 0; 476 if (QGridLayoutItem *gridItem = d->engine.itemAt( d->gridRow(index), d->gridColumn(index)))488 if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) 477 489 item = gridItem->layoutItem(); 478 490 return item; … … 531 543 } 532 544 545 /*! 546 \internal 547 */ 548 void QGraphicsLinearLayout::dump(int indent) const 549 { 533 550 #ifdef QT_DEBUG 534 void QGraphicsLinearLayout::dump(int indent) const535 {536 551 if (qt_graphicsLayoutDebug()) { 537 552 Q_D(const QGraphicsLinearLayout); … … 540 555 d->engine.dump(indent + 1); 541 556 } 542 }543 557 #endif 558 } 544 559 545 560 QT_END_NAMESPACE 546 561 547 562 #endif //QT_NO_GRAPHICSVIEW -
trunk/src/gui/graphicsview/qgraphicslinearlayout.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 98 98 #endif 99 99 100 #ifdef QT_DEBUG101 100 void dump(int indent = 0) const; 102 #endif103 101 104 102 protected: -
trunk/src/gui/graphicsview/qgraphicsproxywidget.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 58 58 #include <QtGui/qstyleoption.h> 59 59 #include <QtGui/qgraphicsview.h> 60 #include <QtGui/qlistview.h> 61 #include <QtGui/qlineedit.h> 62 #include <QtGui/qtextedit.h> 60 63 61 64 QT_BEGIN_NAMESPACE … … 68 71 a QWidget in a QGraphicsScene. 69 72 \since 4.4 70 \ingroup multimedia71 73 \ingroup graphicsview-api 72 74 … … 88 90 means that when an embedded QComboBox shows its popup list, a new 89 91 QGraphicsProxyWidget is created automatically, embedding the popup, and 90 positioning it correctly. 92 positioning it correctly. This only works if the popup is child of the 93 embedded widget (for example QToolButton::setMenu() requires the QMenu instance 94 to be child of the QToolButton). 91 95 92 96 \section1 Embedding a Widget with QGraphicsProxyWidget … … 178 182 in behavior from when it is not embedded. 179 183 184 \warning This class is provided for convenience when bridging 185 QWidgets and QGraphicsItems, it should not be used for 186 high-performance scenarios. 187 180 188 \sa QGraphicsScene::addWidget(), QGraphicsWidget 181 189 */ 182 190 183 191 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); 192 extern bool qt_tab_all_widgets; 184 193 185 194 /*! … … 272 281 QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber; 273 282 QApplicationPrivate::sendMouseEvent(receiver, mouseEvent, alienWidget, widget, 274 &embeddedMouseGrabberPtr, lastWidgetUnderMouse );283 &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous()); 275 284 embeddedMouseGrabber = embeddedMouseGrabberPtr; 276 285 … … 367 376 /*! 368 377 \internal 378 Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper 369 379 */ 370 380 QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const … … 380 390 if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) { 381 391 return 0; 382 392 } 383 393 } 384 394 385 395 QWidget *oldChild = child; 396 uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus; 386 397 do { 387 398 if (child->isEnabled() 388 399 && child->isVisibleTo(widget) 389 && (child->focusPolicy() & Qt::TabFocus)) { 390 return child; 400 && ((child->focusPolicy() & focus_flag) == focus_flag) 401 && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) { 402 return child; 391 403 } 392 404 child = next ? child->d_func()->focus_next : child->d_func()->focus_prev; … … 448 460 /*! 449 461 \internal 462 */ 463 void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget() 464 { 465 Q_Q(QGraphicsProxyWidget); 466 if (!widget) 467 return; 468 469 QWidget *focusWidget = widget->focusWidget(); 470 if (!focusWidget) 471 focusWidget = widget; 472 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod, 473 focusWidget->testAttribute(Qt::WA_InputMethodEnabled)); 474 } 475 476 /*! 477 \internal 450 478 451 479 Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level … … 457 485 QWExtra *extra; 458 486 if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) { 459 QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func() );487 QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags()); 460 488 subProxy->d_func()->setWidget_helper(subWin, false); 461 489 } … … 540 568 hidden or disabled after embedding is complete. The class documentation 541 569 has a full overview over the shared state. 570 571 QGraphicsProxyWidget's window flags determine whether the widget, after 572 embedding, will be given window decorations or not. 542 573 543 574 After this function returns, QGraphicsProxyWidget will keep its state … … 658 689 q->setCursor(widget->cursor()); 659 690 #endif 660 Qt::WFlags flags = newWidget->windowFlags();661 if (newWidget->windowType() == Qt::Window)662 flags &= ~Qt::Window;663 q->setWindowFlags(flags);664 691 q->setEnabled(newWidget->isEnabled()); 665 692 q->setVisible(newWidget->isVisible()); … … 687 714 688 715 updateProxyGeometryFromWidget(); 716 717 updateProxyInputMethodAcceptanceFromWidget(); 689 718 690 719 // Hook up the event filter to keep the state up to date. … … 837 866 // of inputMethodEvent(). 838 867 QWidget *focusWidget = d->widget->focusWidget(); 839 if (focusWidget ->testAttribute(Qt::WA_InputMethodEnabled))868 if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) 840 869 QApplication::sendEvent(focusWidget, event); 841 870 break; … … 954 983 { 955 984 Q_D(QGraphicsProxyWidget); 956 if (!event || !d->widget || !d->widget->isVisible() )985 if (!event || !d->widget || !d->widget->isVisible() || !hasFocus()) 957 986 return; 958 987 … … 974 1003 #endif // QT_NO_CONTEXTMENU 975 1004 1005 #ifndef QT_NO_DRAGANDDROP 976 1006 /*! 977 1007 \reimp … … 1034 1064 // Try to enter before we leave 1035 1065 QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers()); 1036 dragEnter.setDropAction(event->proposedAction()); 1066 dragEnter.setDropAction(event->proposedAction()); 1037 1067 QApplication::sendEvent(receiver, &dragEnter); 1038 1068 event->setAccepted(dragEnter.isAccepted()); … … 1094 1124 #endif 1095 1125 } 1126 #endif 1096 1127 1097 1128 /*! … … 1299 1330 d->widget->focusWidget()->setFocus(event->reason()); 1300 1331 return; 1301 1302 1332 } 1333 break; 1303 1334 } 1304 1335 } … … 1432 1463 Creates a proxy widget for the given \a child of the widget 1433 1464 contained in this proxy. 1434 1465 1435 1466 This function makes it possible to aquire proxies for 1436 1467 non top-level widgets. For instance, you can embed a dialog, -
trunk/src/gui/graphicsview/qgraphicsproxywidget.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 91 91 #endif 92 92 93 #ifndef QT_NO_DRAGANDDROP 93 94 void dragEnterEvent(QGraphicsSceneDragDropEvent *event); 94 95 void dragLeaveEvent(QGraphicsSceneDragDropEvent *event); 95 96 void dragMoveEvent(QGraphicsSceneDragDropEvent *event); 96 97 void dropEvent(QGraphicsSceneDragDropEvent *event); 98 #endif 97 99 98 100 void hoverEnterEvent(QGraphicsSceneHoverEvent *event); … … 128 130 private: 129 131 Q_DISABLE_COPY(QGraphicsProxyWidget) 130 Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr , QGraphicsProxyWidget)132 Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsProxyWidget) 131 133 Q_PRIVATE_SLOT(d_func(), void _q_removeWidgetSlot()) 132 134 -
trunk/src/gui/graphicsview/qgraphicsproxywidget_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 // 49 49 // This file is not part of the Qt API. It exists for the convenience 50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header51 // file may change from version toversion without notice, or even be removed.50 // of other Qt classes. This header file may change from version to 51 // version without notice, or even be removed. 52 52 // 53 53 // We mean it. … … 103 103 void updateProxyGeometryFromWidget(); 104 104 105 void updateProxyInputMethodAcceptanceFromWidget(); 106 105 107 QPointF mapToReceiver(const QPointF &pos, const QWidget *receiver) const; 106 108 -
trunk/src/gui/graphicsview/qgraphicsscene.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** 40 40 ****************************************************************************/ 41 42 static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;43 41 44 42 /*! … … 47 45 number of 2D graphical items. 48 46 \since 4.2 49 \ingroup multimedia50 47 \ingroup graphicsview-api 51 \mainclass 48 52 49 53 50 The class serves as a container for QGraphicsItems. It is used together … … 220 217 #include "qgraphicswidget.h" 221 218 #include "qgraphicswidget_p.h" 219 #include "qgraphicssceneindex_p.h" 220 #include "qgraphicsscenebsptreeindex_p.h" 221 #include "qgraphicsscenelinearindex_p.h" 222 222 223 223 #include <QtCore/qdebug.h> … … 243 243 #include <QtGui/qtooltip.h> 244 244 #include <QtGui/qtransform.h> 245 #include <QtGui/qinputcontext.h> 246 #include <QtGui/qgraphicseffect.h> 245 247 #include <private/qapplication_p.h> 246 248 #include <private/qobject_p.h> … … 248 250 #include <private/qt_x11_p.h> 249 251 #endif 252 #include <private/qgraphicseffect_p.h> 253 #include <private/qgesturemanager_p.h> 254 255 // #define GESTURE_DEBUG 256 #ifndef GESTURE_DEBUG 257 # define DEBUG if (0) qDebug 258 #else 259 # define DEBUG qDebug 260 #endif 250 261 251 262 QT_BEGIN_NAMESPACE 252 263 253 static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) 254 { 255 qreal xp = s.left(); 256 qreal yp = s.top(); 257 qreal w = s.width(); 258 qreal h = s.height(); 259 qreal l1 = xp; 260 qreal r1 = xp; 261 if (w < 0) 262 l1 += w; 263 else 264 r1 += w; 265 266 qreal l2 = r.left(); 267 qreal r2 = r.left(); 268 if (w < 0) 269 l2 += r.width(); 270 else 271 r2 += r.width(); 272 273 if (l1 >= r2 || l2 >= r1) 274 return false; 275 276 qreal t1 = yp; 277 qreal b1 = yp; 278 if (h < 0) 279 t1 += h; 280 else 281 b1 += h; 282 283 qreal t2 = r.top(); 284 qreal b2 = r.top(); 285 if (r.height() < 0) 286 t2 += r.height(); 287 else 288 b2 += r.height(); 289 290 return !(t1 >= b2 || t2 >= b1); 291 } 292 293 // QRectF::intersects() returns false always if either the source or target 294 // rectangle's width or height are 0. This works around that problem. 295 static inline void _q_adjustRect(QRectF *rect) 296 { 297 Q_ASSERT(rect); 298 if (!rect->width()) 299 rect->adjust(-0.00001, 0, 0.00001, 0); 300 if (!rect->height()) 301 rect->adjust(0, -0.00001, 0, 0.00001); 302 } 303 304 static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) 305 { 306 Q_ASSERT(item); 307 QRectF boundingRect(item->boundingRect()); 308 _q_adjustRect(&boundingRect); 309 return boundingRect; 310 } 264 bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); 311 265 312 266 static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) … … 323 277 } 324 278 279 int QGraphicsScenePrivate::changedSignalIndex; 280 325 281 /*! 326 282 \internal 327 283 */ 328 284 QGraphicsScenePrivate::QGraphicsScenePrivate() 329 : changedSignalMask(0), 330 indexMethod(QGraphicsScene::BspTreeIndex), 331 bspTreeDepth(0), 285 : indexMethod(QGraphicsScene::BspTreeIndex), 286 index(0), 332 287 lastItemCount(0), 333 288 hasSceneRect(false), 289 dirtyGrowingItemsBoundingRect(true), 334 290 updateAll(false), 335 291 calledEmitUpdated(false), 292 processDirtyItemsEmitted(false), 336 293 selectionChanging(0), 337 dirtyItemResetPending(false),338 regenerateIndex(true),339 purgePending(false),340 indexTimerId(0),341 restartIndexTimer(false),294 needSortTopLevelItems(true), 295 unpolishedItemsModified(true), 296 holesInTopLevelSiblingIndex(false), 297 topLevelSequentialOrdering(true), 298 scenePosDescendantsUpdatePending(false), 342 299 stickyFocus(false), 343 300 hasFocus(false), … … 345 302 lastFocusItem(0), 346 303 tabFocusFirst(0), 347 activeWindow(0), 304 activePanel(0), 305 lastActivePanel(0), 348 306 activationRefCount(0), 307 childExplicitActivation(0), 349 308 lastMouseGrabberItem(0), 350 309 lastMouseGrabberItemHasImplicitMouseGrab(false), … … 352 311 enterWidget(0), 353 312 lastDropAction(Qt::IgnoreAction), 313 allItemsIgnoreHoverEvents(true), 314 allItemsUseDefaultCursor(true), 354 315 painterStateProtection(true), 355 316 sortCacheEnabled(false), 356 updatingSortCache(false),357 style(0)317 style(0), 318 allItemsIgnoreTouchEvents(true) 358 319 { 359 320 } … … 366 327 Q_Q(QGraphicsScene); 367 328 329 index = new QGraphicsSceneBspTreeIndex(q); 330 368 331 // Keep this index so we can check for connected slots later on. 369 changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList<QRectF>)")); 332 if (!changedSignalIndex) { 333 changedSignalIndex = signalIndex("changed(QList<QRectF>)"); 334 } 370 335 qApp->d_func()->scene_list.append(q); 371 336 q->update(); … … 375 340 \internal 376 341 */ 377 QList<QGraphicsItem *> QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const 378 { 379 const_cast<QGraphicsScenePrivate *>(this)->purgeRemovedItems(); 380 const_cast<QGraphicsScenePrivate *>(this)->_q_updateSortCache(); 381 382 if (indexMethod == QGraphicsScene::BspTreeIndex) { 383 // ### Only do this once in a while. 384 QGraphicsScenePrivate *that = const_cast<QGraphicsScenePrivate *>(this); 385 386 // Get items from BSP tree 387 QList<QGraphicsItem *> items = that->bspTree.items(rect); 388 389 // Fill in with any unindexed items 390 for (int i = 0; i < unindexedItems.size(); ++i) { 391 if (QGraphicsItem *item = unindexedItems.at(i)) { 392 if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { 393 QRectF boundingRect = item->sceneBoundingRect(); 394 if (QRectF_intersects(boundingRect, rect)) { 395 item->d_ptr->itemDiscovered = 1; 396 items << item; 397 } 398 } 399 } 400 } 401 402 // Reset the discovered state of all discovered items 403 for (int i = 0; i < items.size(); ++i) 404 items.at(i)->d_func()->itemDiscovered = 0; 405 return items; 406 } 407 408 QList<QGraphicsItem *> itemsInRect; 409 for (int i = 0; i < unindexedItems.size(); ++i) { 410 if (QGraphicsItem *item = unindexedItems.at(i)) { 411 if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) 412 continue; 413 if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) 414 itemsInRect << item; 415 } 416 } 417 for (int i = 0; i < indexedItems.size(); ++i) { 418 if (QGraphicsItem *item = indexedItems.at(i)) { 419 if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) 420 continue; 421 if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) 422 itemsInRect << item; 423 } 424 } 425 426 return itemsInRect; 427 } 428 429 /*! 430 \internal 431 */ 432 void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) 433 { 434 if (indexMethod == QGraphicsScene::BspTreeIndex) { 435 if (item->d_func()->index != -1) { 436 bspTree.insertItem(item, item->sceneBoundingRect()); 437 foreach (QGraphicsItem *child, item->children()) 438 child->addToIndex(); 439 } else { 440 // The BSP tree is regenerated if the number of items grows to a 441 // certain threshold, or if the bounding rect of the graph doubles in 442 // size. 443 startIndexTimer(); 444 } 445 } 446 } 447 448 /*! 449 \internal 450 */ 451 void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) 452 { 453 if (indexMethod == QGraphicsScene::BspTreeIndex) { 454 int index = item->d_func()->index; 455 if (index != -1) { 456 bspTree.removeItem(item, item->sceneBoundingRect()); 457 freeItemIndexes << index; 458 indexedItems[index] = 0; 459 item->d_func()->index = -1; 460 unindexedItems << item; 461 462 foreach (QGraphicsItem *child, item->children()) 463 child->removeFromIndex(); 464 } 465 466 startIndexTimer(); 467 } 468 } 469 470 /*! 471 \internal 472 */ 473 void QGraphicsScenePrivate::resetIndex() 474 { 475 purgeRemovedItems(); 476 if (indexMethod == QGraphicsScene::BspTreeIndex) { 477 for (int i = 0; i < indexedItems.size(); ++i) { 478 if (QGraphicsItem *item = indexedItems.at(i)) { 479 item->d_ptr->index = -1; 480 unindexedItems << item; 481 } 482 } 483 indexedItems.clear(); 484 freeItemIndexes.clear(); 485 regenerateIndex = true; 486 startIndexTimer(); 487 } 488 } 489 490 static inline int intmaxlog(int n) 491 { 492 return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); 493 } 494 495 /*! 496 \internal 497 */ 498 void QGraphicsScenePrivate::_q_updateIndex() 499 { 500 if (!indexTimerId) 501 return; 502 503 Q_Q(QGraphicsScene); 504 q->killTimer(indexTimerId); 505 indexTimerId = 0; 506 507 purgeRemovedItems(); 508 509 // Add unindexedItems to indexedItems 510 QRectF unindexedItemsBoundingRect; 511 for (int i = 0; i < unindexedItems.size(); ++i) { 512 if (QGraphicsItem *item = unindexedItems.at(i)) { 513 unindexedItemsBoundingRect |= item->sceneBoundingRect(); 514 if (!freeItemIndexes.isEmpty()) { 515 int freeIndex = freeItemIndexes.takeFirst(); 516 item->d_func()->index = freeIndex; 517 indexedItems[freeIndex] = item; 518 } else { 519 item->d_func()->index = indexedItems.size(); 520 indexedItems << item; 521 } 522 } 523 } 524 525 // Update growing scene rect. 526 QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; 527 growingItemsBoundingRect |= unindexedItemsBoundingRect; 528 529 // Determine whether we should regenerate the BSP tree. 530 if (indexMethod == QGraphicsScene::BspTreeIndex) { 531 int depth = bspTreeDepth; 532 if (depth == 0) { 533 int oldDepth = intmaxlog(lastItemCount); 534 depth = intmaxlog(indexedItems.size()); 535 static const int slack = 100; 536 if (bspTree.leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) { 537 // ### Crude algorithm. 538 regenerateIndex = true; 539 } 540 } 541 542 // Regenerate the tree. 543 if (regenerateIndex) { 544 regenerateIndex = false; 545 bspTree.initialize(q->sceneRect(), depth); 546 unindexedItems = indexedItems; 547 lastItemCount = indexedItems.size(); 548 q->update(); 549 550 // Take this opportunity to reset our largest-item counter for 551 // untransformable items. When the items are inserted into the BSP 552 // tree, we'll get an accurate calculation. 553 largestUntransformableItem = QRectF(); 554 } 555 } 556 557 // Insert all unindexed items into the tree. 558 for (int i = 0; i < unindexedItems.size(); ++i) { 559 if (QGraphicsItem *item = unindexedItems.at(i)) { 560 QRectF rect = item->sceneBoundingRect(); 561 if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) 562 continue; 563 if (indexMethod == QGraphicsScene::BspTreeIndex) 564 bspTree.insertItem(item, rect); 565 566 // If the item ignores view transformations, update our 567 // largest-item-counter to ensure that the view can accurately 568 // discover untransformable items when drawing. 569 if (item->d_ptr->itemIsUntransformable()) { 570 QGraphicsItem *topmostUntransformable = item; 571 while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags 572 & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { 573 topmostUntransformable = topmostUntransformable->parentItem(); 574 } 575 // ### Verify that this is the correct largest untransformable rectangle. 576 largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); 577 } 578 } 579 } 580 unindexedItems.clear(); 581 582 // Notify scene rect changes. 583 if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect) 584 emit q->sceneRectChanged(growingItemsBoundingRect); 585 } 586 587 /*! 588 \internal 589 */ 342 QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q) 343 { 344 return q->d_func(); 345 } 346 590 347 void QGraphicsScenePrivate::_q_emitUpdated() 591 348 { 592 349 Q_Q(QGraphicsScene); 593 350 calledEmitUpdated = false; 351 352 if (dirtyGrowingItemsBoundingRect) { 353 if (!hasSceneRect) { 354 const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; 355 growingItemsBoundingRect |= q->itemsBoundingRect(); 356 if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) 357 emit q->sceneRectChanged(growingItemsBoundingRect); 358 } 359 dirtyGrowingItemsBoundingRect = false; 360 } 594 361 595 362 // Ensure all views are connected if anything is connected. This disables … … 597 364 // needs to happen in order to keep compatibility with the behavior from 598 365 // Qt 4.4 and backward. 599 if ( !views.isEmpty() && (connectedSignals & changedSignalMask)) {366 if (isSignalConnected(changedSignalIndex)) { 600 367 for (int i = 0; i < views.size(); ++i) { 601 368 QGraphicsView *view = views.at(i); … … 606 373 } 607 374 } 608 } 609 610 // Ensure all dirty items's current positions are recorded in the list of 611 // updated rects. 612 for (int i = 0; i < dirtyItems.size(); ++i) 613 updatedRects += dirtyItems.at(i)->sceneBoundingRect(); 375 } else { 376 updateAll = false; 377 for (int i = 0; i < views.size(); ++i) 378 views.at(i)->d_func()->processPendingUpdates(); 379 // It's important that we update all views before we dispatch, hence two for-loops. 380 for (int i = 0; i < views.size(); ++i) 381 views.at(i)->d_func()->dispatchPendingUpdateRequests(); 382 return; 383 } 614 384 615 385 // Notify the changes to anybody interested. … … 624 394 \internal 625 395 626 Updates all items in the pending update list. At this point, the list is627 unlikely to contain partially constructed items. 628 */ 629 void QGraphicsScenePrivate::_q_updateLater() 630 { 631 foreach (QGraphicsItem *item, pendingUpdateItems)632 item->update();633 pendingUpdateItems.clear();396 ### This function is almost identical to QGraphicsItemPrivate::addChild(). 397 */ 398 void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) 399 { 400 item->d_ptr->ensureSequentialSiblingIndex(); 401 needSortTopLevelItems = true; // ### maybe false 402 item->d_ptr->siblingIndex = topLevelItems.size(); 403 topLevelItems.append(item); 634 404 } 635 405 636 406 /*! 637 407 \internal 408 409 ### This function is almost identical to QGraphicsItemPrivate::removeChild(). 410 */ 411 void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) 412 { 413 if (!holesInTopLevelSiblingIndex) 414 holesInTopLevelSiblingIndex = item->d_ptr->siblingIndex != topLevelItems.size() - 1; 415 if (topLevelSequentialOrdering && !holesInTopLevelSiblingIndex) 416 topLevelItems.removeAt(item->d_ptr->siblingIndex); 417 else 418 topLevelItems.removeOne(item); 419 // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because 420 // the item is not guaranteed to be at the index after the list is sorted 421 // (see ensureSortedTopLevelItems()). 422 item->d_ptr->siblingIndex = -1; 423 if (topLevelSequentialOrdering) 424 topLevelSequentialOrdering = !holesInTopLevelSiblingIndex; 425 } 426 427 /*! 428 \internal 638 429 */ 639 430 void QGraphicsScenePrivate::_q_polishItems() 640 431 { 432 QSet<QGraphicsItem *>::Iterator it = unpolishedItems.begin(); 641 433 const QVariant booleanTrueVariant(true); 642 foreach (QGraphicsItem *item, unpolishedItems) { 434 while (!unpolishedItems.isEmpty()) { 435 QGraphicsItem *item = *it; 436 it = unpolishedItems.erase(it); 437 unpolishedItemsModified = false; 643 438 if (!item->d_ptr->explicitlyHidden) { 644 439 item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); … … 649 444 QApplication::sendEvent((QGraphicsWidget *)item, &event); 650 445 } 651 } 652 unpolishedItems.clear(); 446 if (unpolishedItemsModified) 447 it = unpolishedItems.begin(); 448 } 449 } 450 451 void QGraphicsScenePrivate::_q_processDirtyItems() 452 { 453 processDirtyItemsEmitted = false; 454 455 if (updateAll) { 456 Q_ASSERT(calledEmitUpdated); 457 // No need for further processing (except resetting the dirty states). 458 // The growingItemsBoundingRect is updated in _q_emitUpdated. 459 for (int i = 0; i < topLevelItems.size(); ++i) 460 resetDirtyItem(topLevelItems.at(i), /*recursive=*/true); 461 return; 462 } 463 464 const bool wasPendingSceneUpdate = calledEmitUpdated; 465 const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; 466 467 // Process items recursively. 468 for (int i = 0; i < topLevelItems.size(); ++i) 469 processDirtyItemsRecursive(topLevelItems.at(i)); 470 471 dirtyGrowingItemsBoundingRect = false; 472 if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) 473 emit q_func()->sceneRectChanged(growingItemsBoundingRect); 474 475 if (wasPendingSceneUpdate) 476 return; 477 478 for (int i = 0; i < views.size(); ++i) 479 views.at(i)->d_func()->processPendingUpdates(); 480 481 if (calledEmitUpdated) { 482 // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive 483 // and we cannot wait for the control to reach the eventloop before the 484 // changed signal is emitted, so we emit it now. 485 _q_emitUpdated(); 486 } 487 488 // Immediately dispatch all pending update requests on the views. 489 for (int i = 0; i < views.size(); ++i) 490 views.at(i)->d_func()->dispatchPendingUpdateRequests(); 653 491 } 654 492 … … 656 494 \internal 657 495 */ 658 void QGraphicsScenePrivate::_q_resetDirtyItems() 659 { 660 for (int i = 0; i < dirtyItems.size(); ++i) { 661 QGraphicsItem *item = dirtyItems.at(i); 662 item->d_ptr->dirty = 0; 663 item->d_ptr->dirtyChildren = 0; 664 } 665 dirtyItems.clear(); 666 dirtyItemResetPending = false; 496 void QGraphicsScenePrivate::setScenePosItemEnabled(QGraphicsItem *item, bool enabled) 497 { 498 QGraphicsItem *p = item->d_ptr->parent; 499 while (p) { 500 p->d_ptr->scenePosDescendants = enabled; 501 p = p->d_ptr->parent; 502 } 503 if (!enabled && !scenePosDescendantsUpdatePending) { 504 scenePosDescendantsUpdatePending = true; 505 QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection); 506 } 667 507 } 668 508 … … 670 510 \internal 671 511 */ 672 void QGraphicsScenePrivate::resetDirtyItemsLater() 673 { 674 Q_Q(QGraphicsScene); 675 if (dirtyItemResetPending) 676 return; 677 // dirtyItems.reserve(indexedItems.size() + unindexedItems.size()); 678 dirtyItemResetPending = true; 679 QMetaObject::invokeMethod(q, "_q_resetDirtyItems", Qt::QueuedConnection); 512 void QGraphicsScenePrivate::registerScenePosItem(QGraphicsItem *item) 513 { 514 scenePosItems.insert(item); 515 setScenePosItemEnabled(item, true); 680 516 } 681 517 682 518 /*! 683 519 \internal 520 */ 521 void QGraphicsScenePrivate::unregisterScenePosItem(QGraphicsItem *item) 522 { 523 scenePosItems.remove(item); 524 setScenePosItemEnabled(item, false); 525 } 526 527 /*! 528 \internal 529 */ 530 void QGraphicsScenePrivate::_q_updateScenePosDescendants() 531 { 532 foreach (QGraphicsItem *item, scenePosItems) { 533 QGraphicsItem *p = item->d_ptr->parent; 534 while (p) { 535 p->d_ptr->scenePosDescendants = 1; 536 p = p->d_ptr->parent; 537 } 538 } 539 scenePosDescendantsUpdatePending = false; 540 } 541 542 /*! 543 \internal 684 544 685 545 Schedules an item for removal. This function leaves some stale indexes 686 around in the BSP tree ; these will be cleaned up the next time someone687 triggers purgeRemovedItems().688 689 Note: This function iscalled from QGraphicsItem's destructor. \a item is546 around in the BSP tree if called from the item's destructor; these will 547 be cleaned up the next time someone triggers purgeRemovedItems(). 548 549 Note: This function might get called from QGraphicsItem's destructor. \a item is 690 550 being destroyed, so we cannot call any pure virtual functions on it (such 691 551 as boundingRect()). Also, it is unnecessary to update the item's own state 692 552 in any way. 693 694 ### Refactoring: This function shares much functionality with removeItem() 695 */ 696 void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) 553 */ 554 void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) 697 555 { 698 556 Q_Q(QGraphicsScene); 699 557 700 // Clear focus on the item to remove any reference in the focusWidget 701 // chain. 558 // Clear focus on the item to remove any reference in the focusWidget chain. 702 559 item->clearFocus(); 703 560 704 int index = item->d_func()->index; 705 if (index != -1) { 706 // Important: The index is useless until purgeRemovedItems() is 707 // called. 708 indexedItems[index] = (QGraphicsItem *)0; 709 if (!purgePending) { 710 purgePending = true; 711 q->update(); 712 } 713 removedItems << item; 561 markDirty(item, QRectF(), /*invalidateChildren=*/false, /*force=*/false, 562 /*ignoreOpacity=*/false, /*removingItemFromScene=*/true); 563 564 if (item->d_ptr->inDestructor) { 565 // The item is actually in its destructor, we call the special method in the index. 566 index->deleteItem(item); 714 567 } else { 715 // Recently added items are purged immediately. unindexedItems() never 716 // contains stale items. 717 unindexedItems.removeAll(item); 718 q->update(); 568 // Can potentially call item->boundingRect() (virtual function), that's why 569 // we only can call this function if the item is not in its destructor. 570 index->removeItem(item); 571 } 572 573 item->d_ptr->clearSubFocus(); 574 575 if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) 576 unregisterScenePosItem(item); 577 578 QGraphicsScene *oldScene = item->d_func()->scene; 579 item->d_func()->scene = 0; 580 581 //We need to remove all children first because they might use their parent 582 //attributes (e.g. sceneTransform). 583 if (!item->d_ptr->inDestructor) { 584 // Remove all children recursively 585 for (int i = 0; i < item->d_ptr->children.size(); ++i) 586 q->removeItem(item->d_ptr->children.at(i)); 587 } 588 589 if (!item->d_ptr->inDestructor && item == tabFocusFirst) { 590 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); 591 widget->d_func()->fixFocusChainBeforeReparenting(0, oldScene, 0); 592 } 593 594 // Unregister focus proxy. 595 item->d_ptr->resetFocusProxy(); 596 597 // Remove from parent, or unregister from toplevels. 598 if (QGraphicsItem *parentItem = item->parentItem()) { 599 if (parentItem->scene()) { 600 Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem", 601 "Parent item's scene is different from this item's scene"); 602 item->d_ptr->setParentItemHelper(0); 603 } 604 } else { 605 unregisterTopLevelItem(item); 719 606 } 720 607 … … 724 611 if (item == lastFocusItem) 725 612 lastFocusItem = 0; 726 if (item == active Window) {613 if (item == activePanel) { 727 614 // ### deactivate... 728 activeWindow = 0; 615 activePanel = 0; 616 } 617 if (item == lastActivePanel) 618 lastActivePanel = 0; 619 620 // Cancel active touches 621 { 622 QMap<int, QGraphicsItem *>::iterator it = itemForTouchPointId.begin(); 623 while (it != itemForTouchPointId.end()) { 624 if (it.value() == item) { 625 sceneCurrentTouchPoints.remove(it.key()); 626 it = itemForTouchPointId.erase(it); 627 } else { 628 ++it; 629 } 630 } 729 631 } 730 632 … … 736 638 selectedItems.remove(item); 737 639 hoverItems.removeAll(item); 738 pendingUpdateItems.removeAll(item);739 640 cachedItemsUnderMouse.removeAll(item); 740 unpolishedItems.removeAll(item); 741 dirtyItems.removeAll(item); 641 unpolishedItems.remove(item); 642 unpolishedItemsModified = true; 643 resetDirtyItem(item); 742 644 743 645 //We remove all references of item from the sceneEventFilter arrays … … 750 652 } 751 653 752 // Remove from scene transform cache 753 int transformIndex = item->d_func()->sceneTransformIndex; 754 if (transformIndex != -1) { 755 validTransforms.setBit(transformIndex, 0); 756 freeSceneTransformSlots.append(transformIndex); 757 } 758 759 // Remove all children recursively. 760 foreach (QGraphicsItem *child, item->children()) 761 _q_removeItemLater(child); 762 763 // Reset the mouse grabber 654 if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) 655 leaveModal(item); 656 657 // Reset the mouse grabber and focus item data. 764 658 if (mouseGrabberItems.contains(item)) 765 ungrabMouse(item, /* item is dying */ true);659 ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor); 766 660 767 661 // Reset the keyboard grabber 768 662 if (keyboardGrabberItems.contains(item)) 769 ungrabKeyboard(item, /* item is dying */ true);663 ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor); 770 664 771 665 // Reset the last mouse grabber item … … 781 675 /*! 782 676 \internal 783 784 Removes stale pointers from all data structures. 785 */ 786 void QGraphicsScenePrivate::purgeRemovedItems() 677 */ 678 void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent) 787 679 { 788 680 Q_Q(QGraphicsScene); 789 790 if (!purgePending && removedItems.isEmpty()) 681 if (item && item->scene() != q) { 682 qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene", 683 item); 791 684 return; 792 793 // Remove stale items from the BSP tree. 794 if (indexMethod != QGraphicsScene::NoIndex) 795 bspTree.removeItems(removedItems); 796 797 // Purge this list. 798 removedItems.clear(); 799 freeItemIndexes.clear(); 800 for (int i = 0; i < indexedItems.size(); ++i) { 801 if (!indexedItems.at(i)) 802 freeItemIndexes << i; 803 } 804 purgePending = false; 805 806 // No locality info for the items; update the whole scene. 807 q->update(); 685 } 686 687 // Ensure the scene has focus when we change panel activation. 688 q->setFocus(Qt::ActiveWindowFocusReason); 689 690 // Find the item's panel. 691 QGraphicsItem *panel = item ? item->panel() : 0; 692 lastActivePanel = panel ? activePanel : 0; 693 if (panel == activePanel || (!q->isActive() && !duringActivationEvent)) 694 return; 695 696 // Deactivate the last active panel. 697 if (activePanel) { 698 if (QGraphicsItem *fi = activePanel->focusItem()) { 699 // Remove focus from the current focus item. 700 if (fi == q->focusItem()) 701 q->setFocusItem(0, Qt::ActiveWindowFocusReason); 702 } 703 704 QEvent event(QEvent::WindowDeactivate); 705 q->sendEvent(activePanel, &event); 706 } else if (panel && !duringActivationEvent) { 707 // Deactivate the scene if changing activation to a panel. 708 QEvent event(QEvent::WindowDeactivate); 709 foreach (QGraphicsItem *item, q->items()) { 710 if (item->isVisible() && !item->isPanel() && !item->parentItem()) 711 q->sendEvent(item, &event); 712 } 713 } 714 715 // Update activate state. 716 activePanel = panel; 717 QEvent event(QEvent::ActivationChange); 718 QApplication::sendEvent(q, &event); 719 720 // Activate 721 if (panel) { 722 QEvent event(QEvent::WindowActivate); 723 q->sendEvent(panel, &event); 724 725 // Set focus on the panel's focus item. 726 if (QGraphicsItem *focusItem = panel->focusItem()) 727 focusItem->setFocus(Qt::ActiveWindowFocusReason); 728 } else if (q->isActive()) { 729 // Activate the scene 730 QEvent event(QEvent::WindowActivate); 731 foreach (QGraphicsItem *item, q->items()) { 732 if (item->isVisible() && !item->isPanel() && !item->parentItem()) 733 q->sendEvent(item, &event); 734 } 735 } 808 736 } 809 737 810 738 /*! 811 739 \internal 812 813 Starts or restarts the timer used for reindexing unindexed items. 814 */ 815 void QGraphicsScenePrivate::startIndexTimer() 740 */ 741 void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, 742 Qt::FocusReason focusReason) 816 743 { 817 744 Q_Q(QGraphicsScene); 818 if (indexTimerId) { 819 restartIndexTimer = true; 820 } else { 821 indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); 822 } 745 if (item == focusItem) 746 return; 747 748 // Clear focus if asked to set focus on something that can't 749 // accept input focus. 750 if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable) 751 || !item->isVisible() || !item->isEnabled())) { 752 item = 0; 753 } 754 755 // Set focus on the scene if an item requests focus. 756 if (item) { 757 q->setFocus(focusReason); 758 if (item == focusItem) 759 return; 760 } 761 762 if (focusItem) { 763 QFocusEvent event(QEvent::FocusOut, focusReason); 764 lastFocusItem = focusItem; 765 focusItem = 0; 766 sendEvent(lastFocusItem, &event); 767 768 #ifndef QT_NO_IM 769 if (lastFocusItem 770 && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { 771 // Reset any visible preedit text 772 QInputMethodEvent imEvent; 773 sendEvent(lastFocusItem, &imEvent); 774 775 // Close any external input method panel. This happens 776 // automatically by removing WA_InputMethodEnabled on 777 // the views, but if we are changing focus, we have to 778 // do it ourselves. 779 if (item) { 780 for (int i = 0; i < views.size(); ++i) 781 views.at(i)->inputContext()->reset(); 782 } 783 } 784 #endif //QT_NO_IM 785 } 786 787 if (item) { 788 focusItem = item; 789 QFocusEvent event(QEvent::FocusIn, focusReason); 790 sendEvent(item, &event); 791 } 792 793 updateInputMethodSensitivityInViews(); 823 794 } 824 795 … … 864 835 QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason); 865 836 sendEvent(focusItem, &event); 866 } else {867 ungrabKeyboard( (QGraphicsItem *)widget, itemIsDying);837 } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) { 838 ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying); 868 839 } 869 840 if (!itemIsDying && widget->isVisible()) { … … 881 852 // Append to list of mouse grabber items, and send a mouse grab event. 882 853 if (mouseGrabberItems.contains(item)) { 883 if (mouseGrabberItems.last() == item) 884 qWarning("QGraphicsItem::grabMouse: already a mouse grabber"); 885 else 854 if (mouseGrabberItems.last() == item) { 855 Q_ASSERT(!implicit); 856 if (!lastMouseGrabberItemHasImplicitMouseGrab) { 857 qWarning("QGraphicsItem::grabMouse: already a mouse grabber"); 858 } else { 859 // Upgrade to an explicit mouse grab 860 lastMouseGrabberItemHasImplicitMouseGrab = false; 861 } 862 } else { 886 863 qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p", 887 864 mouseGrabberItems.last()); 865 } 888 866 return; 889 867 } … … 1037 1015 } 1038 1016 1017 void QGraphicsScenePrivate::enableMouseTrackingOnViews() 1018 { 1019 foreach (QGraphicsView *view, views) 1020 view->viewport()->setMouseTracking(true); 1021 } 1022 1039 1023 /*! 1040 1024 Returns all items for the screen position in \a event. … … 1046 1030 Q_Q(const QGraphicsScene); 1047 1031 QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0; 1048 QList<QGraphicsItem *> items; 1049 if (view) 1050 items = view->items(view->viewport()->mapFromGlobal(screenPos)); 1051 else 1052 items = q->items(scenePos); 1053 return items; 1054 } 1055 1056 /*! 1057 \internal 1058 1059 Checks if item collides with the path and mode, but also checks that if it 1060 doesn't collide, maybe its frame rect will. 1061 */ 1062 bool QGraphicsScenePrivate::itemCollidesWithPath(QGraphicsItem *item, 1063 const QPainterPath &path, 1064 Qt::ItemSelectionMode mode) 1065 { 1066 if (item->collidesWithPath(path, mode)) 1067 return true; 1068 if (item->isWidget()) { 1069 // Check if this is a window, and if its frame rect collides. 1070 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); 1071 if (widget->isWindow()) { 1072 QRectF frameRect = widget->windowFrameRect(); 1073 QPainterPath framePath; 1074 framePath.addRect(frameRect); 1075 bool intersects = path.intersects(frameRect); 1076 if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) 1077 return intersects || path.contains(frameRect.topLeft()) 1078 || framePath.contains(path.elementAt(0)); 1079 return !intersects && path.contains(frameRect.topLeft()); 1080 } 1081 } 1082 return false; 1032 if (!view) 1033 return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform()); 1034 1035 const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1)); 1036 if (!view->isTransformed()) 1037 return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder); 1038 1039 const QTransform viewTransform = view->viewportTransform(); 1040 if (viewTransform.type() <= QTransform::TxScale) { 1041 return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape, 1042 Qt::DescendingOrder, viewTransform); 1043 } 1044 return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape, 1045 Qt::DescendingOrder, viewTransform); 1083 1046 } 1084 1047 … … 1092 1055 mouseGrabberButtonDownPos.insert(Qt::MouseButton(i), 1093 1056 mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(), 1094 event->widget()));1057 event->widget())); 1095 1058 mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos()); 1096 1059 mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos()); … … 1126 1089 1127 1090 /*! 1091 \internal 1092 */ 1093 bool QGraphicsScenePrivate::filterDescendantEvent(QGraphicsItem *item, QEvent *event) 1094 { 1095 if (item && (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) { 1096 QGraphicsItem *parent = item->parentItem(); 1097 while (parent) { 1098 if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event)) 1099 return true; 1100 if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) 1101 return false; 1102 parent = parent->parentItem(); 1103 } 1104 } 1105 return false; 1106 } 1107 1108 /*! 1128 1109 \internal 1129 1110 */ … … 1155 1136 bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event) 1156 1137 { 1138 if (QGraphicsObject *object = item->toGraphicsObject()) { 1139 QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager; 1140 if (gestureManager) { 1141 if (gestureManager->filterEvent(object, event)) 1142 return true; 1143 } 1144 } 1145 1157 1146 if (filterEvent(item, event)) 1158 1147 return false; 1159 return (item && item->isEnabled()) ? item->sceneEvent(event) : false; 1148 if (filterDescendantEvent(item, event)) 1149 return false; 1150 if (!item || !item->isEnabled()) 1151 return false; 1152 if (QGraphicsObject *o = item->toGraphicsObject()) { 1153 bool spont = event->spontaneous(); 1154 if (spont ? qt_sendSpontaneousEvent(o, event) : QApplication::sendEvent(o, event)) 1155 return true; 1156 event->spont = spont; 1157 } 1158 return item->sceneEvent(event); 1160 1159 } 1161 1160 … … 1220 1219 1221 1220 QGraphicsItem *item = mouseGrabberItems.last(); 1221 if (item->isBlockedByModalPanel()) 1222 return; 1223 1222 1224 for (int i = 0x1; i <= 0x10; i <<= 1) { 1223 1225 Qt::MouseButton button = Qt::MouseButton(i); … … 1243 1245 // Deliver to any existing mouse grabber. 1244 1246 if (!mouseGrabberItems.isEmpty()) { 1247 if (mouseGrabberItems.last()->isBlockedByModalPanel()) 1248 return; 1245 1249 // The event is ignored by default, but we disregard the event's 1246 1250 // accepted state after delivery; the mouse is grabbed, after all. … … 1258 1262 1259 1263 // Update window activation. 1260 QGraphicsWidget *newActiveWindow = windowForItem(cachedItemsUnderMouse.value(0)); 1261 if (newActiveWindow != activeWindow) 1264 QGraphicsItem *topItem = cachedItemsUnderMouse.value(0); 1265 QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0; 1266 if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) { 1267 // pass activation to the blocking modal window 1268 newActiveWindow = topItem ? topItem->window() : 0; 1269 } 1270 1271 if (newActiveWindow != q->activeWindow()) 1262 1272 q->setActiveWindow(newActiveWindow); 1263 1273 … … 1265 1275 bool setFocus = false; 1266 1276 foreach (QGraphicsItem *item, cachedItemsUnderMouse) { 1267 if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { 1277 if (item->isBlockedByModalPanel()) { 1278 // Make sure we don't clear focus. 1279 setFocus = true; 1280 break; 1281 } 1282 if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { 1268 1283 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { 1269 1284 setFocus = true; … … 1273 1288 } 1274 1289 } 1290 if (item->isPanel()) 1291 break; 1292 } 1293 1294 // Check for scene modality. 1295 bool sceneModality = false; 1296 for (int i = 0; i < modalPanels.size(); ++i) { 1297 if (modalPanels.at(i)->panelModality() == QGraphicsItem::SceneModal) { 1298 sceneModality = true; 1299 break; 1300 } 1275 1301 } 1276 1302 1277 1303 // If nobody could take focus, clear it. 1278 if (!stickyFocus && !setFocus )1304 if (!stickyFocus && !setFocus && !sceneModality) 1279 1305 q->setFocusItem(0, Qt::MouseFocusReason); 1306 1307 // Any item will do. 1308 if (sceneModality && cachedItemsUnderMouse.isEmpty()) 1309 cachedItemsUnderMouse << modalPanels.first(); 1280 1310 1281 1311 // Find a mouse grabber by sending mouse press events to all mouse grabber … … 1289 1319 } 1290 1320 1321 // Check if this item is blocked by a modal panel and deliver the mouse event to the 1322 // blocking panel instead of this item if blocked. 1323 (void) item->isBlockedByModalPanel(&item); 1324 1291 1325 grabMouse(item, /* implicit = */ true); 1292 1326 mouseEvent->accept(); … … 1294 1328 // check if the item we are sending to are disabled (before we send the event) 1295 1329 bool disabled = !item->isEnabled(); 1296 bool isWindow = item->isWindow(); 1297 if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick && item != lastMouseGrabberItem) { 1330 bool isPanel = item->isPanel(); 1331 if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick 1332 && item != lastMouseGrabberItem && lastMouseGrabberItem) { 1298 1333 // If this item is different from the item that received the last 1299 1334 // mouse event, and mouseEvent is a doubleclick event, then the … … 1301 1336 // Triple-clicking will not generate a doubleclick, though. 1302 1337 QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress); 1338 mousePress.spont = mouseEvent->spont; 1303 1339 mousePress.accept(); 1304 1340 mousePress.setButton(mouseEvent->button()); … … 1333 1369 ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); 1334 1370 1335 // Don't propagate through windows.1336 if (is Window)1371 // Don't propagate through panels. 1372 if (isPanel) 1337 1373 break; 1338 1374 } … … 1356 1392 } 1357 1393 1358 QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) const1359 {1360 if (!item)1361 return 0;1362 do {1363 if (item->isWidget())1364 return static_cast<const QGraphicsWidget *>(item)->window();1365 item = item->parentItem();1366 } while (item);1367 return 0;1368 }1369 1370 1371 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPointF &pos) const1372 {1373 QList<QGraphicsItem *> items;1374 1375 // The index returns a rough estimate of what items are inside the rect.1376 // Refine it by iterating through all returned items.1377 QRectF adjustedRect = QRectF(pos, QSize(1,1));1378 foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {1379 // Find the item's scene transform in a clever way.1380 QTransform x = item->sceneTransform();1381 bool keep = false;1382 1383 // ### _q_adjustedRect is only needed because QRectF::intersects,1384 // QRectF::contains and QTransform::map() and friends don't work with1385 // flat rectangles.1386 const QRectF br(adjustedItemBoundingRect(item));1387 // Rect intersects/contains item's shape1388 if (QRectF_intersects(adjustedRect, x.mapRect(br))) {1389 bool ok;1390 QTransform xinv = x.inverted(&ok);1391 if (ok) {1392 if (item->contains(xinv.map(pos))) {1393 items << item;1394 keep = true;1395 }1396 }1397 }1398 1399 if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {1400 // Recurse into children that clip children.1401 bool ok;1402 QTransform xinv = x.inverted(&ok);1403 if (ok)1404 childItems_helper(&items, item, xinv.map(pos));1405 }1406 }1407 1408 sortItems(&items, Qt::AscendingOrder, sortCacheEnabled);1409 return items;1410 }1411 1412 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,1413 Qt::ItemSelectionMode mode,1414 Qt::SortOrder order) const1415 {1416 QList<QGraphicsItem *> items;1417 1418 QPainterPath path;1419 1420 // The index returns a rough estimate of what items are inside the rect.1421 // Refine it by iterating through all returned items.1422 QRectF adjustedRect(rect);1423 _q_adjustRect(&adjustedRect);1424 foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {1425 // Find the item's scene transform in a clever way.1426 QTransform x = item->sceneTransform();1427 bool keep = false;1428 1429 // ### _q_adjustedRect is only needed because QRectF::intersects,1430 // QRectF::contains and QTransform::map() and friends don't work with1431 // flat rectangles.1432 const QRectF br(adjustedItemBoundingRect(item));1433 if (mode >= Qt::ContainsItemBoundingRect) {1434 // Rect intersects/contains item's bounding rect1435 QRectF mbr = x.mapRect(br);1436 if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))1437 || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) {1438 items << item;1439 keep = true;1440 }1441 } else {1442 // Rect intersects/contains item's shape1443 if (QRectF_intersects(adjustedRect, x.mapRect(br))) {1444 bool ok;1445 QTransform xinv = x.inverted(&ok);1446 if (ok) {1447 if (path.isEmpty())1448 path.addRect(rect);1449 if (itemCollidesWithPath(item, xinv.map(path), mode)) {1450 items << item;1451 keep = true;1452 }1453 }1454 }1455 }1456 1457 if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {1458 // Recurse into children that clip children.1459 bool ok;1460 QTransform xinv = x.inverted(&ok);1461 if (ok) {1462 if (x.type() <= QTransform::TxScale) {1463 // Rect1464 childItems_helper(&items, item, xinv.mapRect(rect), mode);1465 } else {1466 // Polygon1467 childItems_helper(&items, item, xinv.map(rect), mode);1468 }1469 }1470 }1471 }1472 1473 if (order != Qt::SortOrder(-1))1474 sortItems(&items, order, sortCacheEnabled);1475 return items;1476 }1477 1478 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPolygonF &polygon,1479 Qt::ItemSelectionMode mode,1480 Qt::SortOrder order) const1481 {1482 QList<QGraphicsItem *> items;1483 1484 QRectF polyRect(polygon.boundingRect());1485 _q_adjustRect(&polyRect);1486 QPainterPath path;1487 1488 // The index returns a rough estimate of what items are inside the rect.1489 // Refine it by iterating through all returned items.1490 foreach (QGraphicsItem *item, estimateItemsInRect(polyRect)) {1491 // Find the item's scene transform in a clever way.1492 QTransform x = item->sceneTransform();1493 bool keep = false;1494 1495 // ### _q_adjustedRect is only needed because QRectF::intersects,1496 // QRectF::contains and QTransform::map() and friends don't work with1497 // flat rectangles.1498 const QRectF br(adjustedItemBoundingRect(item));1499 if (mode >= Qt::ContainsItemBoundingRect) {1500 // Polygon contains/intersects item's bounding rect1501 if (path == QPainterPath())1502 path.addPolygon(polygon);1503 if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br)))1504 || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) {1505 items << item;1506 keep = true;1507 }1508 } else {1509 // Polygon contains/intersects item's shape1510 if (QRectF_intersects(polyRect, x.mapRect(br))) {1511 bool ok;1512 QTransform xinv = x.inverted(&ok);1513 if (ok) {1514 if (path == QPainterPath())1515 path.addPolygon(polygon);1516 if (itemCollidesWithPath(item, xinv.map(path), mode)) {1517 items << item;1518 keep = true;1519 }1520 }1521 }1522 }1523 1524 if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {1525 // Recurse into children that clip children.1526 bool ok;1527 QTransform xinv = x.inverted(&ok);1528 if (ok)1529 childItems_helper(&items, item, xinv.map(polygon), mode);1530 }1531 }1532 1533 if (order != Qt::SortOrder(-1))1534 sortItems(&items, order, sortCacheEnabled);1535 return items;1536 }1537 1538 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPainterPath &path,1539 Qt::ItemSelectionMode mode,1540 Qt::SortOrder order) const1541 {1542 QList<QGraphicsItem *> items;1543 QRectF pathRect(path.controlPointRect());1544 _q_adjustRect(&pathRect);1545 1546 // The index returns a rough estimate of what items are inside the rect.1547 // Refine it by iterating through all returned items.1548 foreach (QGraphicsItem *item, estimateItemsInRect(pathRect)) {1549 // Find the item's scene transform in a clever way.1550 QTransform x = item->sceneTransform();1551 bool keep = false;1552 1553 // ### _q_adjustedRect is only needed because QRectF::intersects,1554 // QRectF::contains and QTransform::map() and friends don't work with1555 // flat rectangles.1556 const QRectF br(adjustedItemBoundingRect(item));1557 if (mode >= Qt::ContainsItemBoundingRect) {1558 // Path contains/intersects item's bounding rect1559 if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br)))1560 || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) {1561 items << item;1562 keep = true;1563 }1564 } else {1565 // Path contains/intersects item's shape1566 if (QRectF_intersects(pathRect, x.mapRect(br))) {1567 bool ok;1568 QTransform xinv = x.inverted(&ok);1569 if (ok) {1570 if (itemCollidesWithPath(item, xinv.map(path), mode)) {1571 items << item;1572 keep = true;1573 }1574 }1575 }1576 }1577 1578 if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {1579 bool ok;1580 QTransform xinv = x.inverted(&ok);1581 if (ok)1582 childItems_helper(&items, item, xinv.map(path), mode);1583 }1584 }1585 1586 if (order != Qt::SortOrder(-1))1587 sortItems(&items, order, sortCacheEnabled);1588 return items;1589 }1590 1591 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,1592 const QGraphicsItem *parent,1593 const QPointF &pos) const1594 {1595 bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);1596 if (parentClip && parent->d_ptr->isClippedAway())1597 return;1598 // ### is this needed?1599 if (parentClip && !parent->boundingRect().contains(pos))1600 return;1601 1602 QList<QGraphicsItem *> &children = parent->d_ptr->children;1603 for (int i = 0; i < children.size(); ++i) {1604 QGraphicsItem *item = children.at(i);1605 if (item->d_ptr->hasTransform && !item->transform().isInvertible())1606 continue;1607 1608 // Skip invisible items and all their children.1609 if (item->d_ptr->isInvisible())1610 continue;1611 1612 bool keep = false;1613 if (!item->d_ptr->isClippedAway()) {1614 if (item->contains(item->mapFromParent(pos))) {1615 items->append(item);1616 keep = true;1617 }1618 }1619 1620 if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty())1621 // Recurse into children.1622 childItems_helper(items, item, item->mapFromParent(pos));1623 }1624 }1625 1626 1627 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,1628 const QGraphicsItem *parent,1629 const QRectF &rect,1630 Qt::ItemSelectionMode mode) const1631 {1632 bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);1633 if (parentClip && parent->d_ptr->isClippedAway())1634 return;1635 QRectF adjustedRect(rect);1636 _q_adjustRect(&adjustedRect);1637 QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent));1638 if (r.isEmpty())1639 return;1640 1641 QPainterPath path;1642 QList<QGraphicsItem *> &children = parent->d_ptr->children;1643 for (int i = 0; i < children.size(); ++i) {1644 QGraphicsItem *item = children.at(i);1645 if (item->d_ptr->hasTransform && !item->transform().isInvertible())1646 continue;1647 1648 // Skip invisible items and all their children.1649 if (item->d_ptr->isInvisible())1650 continue;1651 1652 bool keep = false;1653 if (!item->d_ptr->isClippedAway()) {1654 // ### _q_adjustedRect is only needed because QRectF::intersects,1655 // QRectF::contains and QTransform::map() and friends don't work with1656 // flat rectangles.1657 const QRectF br(adjustedItemBoundingRect(item));1658 QRectF mbr = item->mapRectToParent(br);1659 if (mode >= Qt::ContainsItemBoundingRect) {1660 // Rect intersects/contains item's bounding rect1661 if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))1662 || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) {1663 items->append(item);1664 keep = true;1665 }1666 } else {1667 // Rect intersects/contains item's shape1668 if (QRectF_intersects(rect, mbr)) {1669 if (path == QPainterPath())1670 path.addRect(rect);1671 if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {1672 items->append(item);1673 keep = true;1674 }1675 }1676 }1677 }1678 1679 if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {1680 // Recurse into children.1681 if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) {1682 // Rect1683 childItems_helper(items, item, item->mapRectFromParent(rect), mode);1684 } else {1685 // Polygon1686 childItems_helper(items, item, item->mapFromParent(rect), mode);1687 }1688 }1689 }1690 }1691 1692 1693 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,1694 const QGraphicsItem *parent,1695 const QPolygonF &polygon,1696 Qt::ItemSelectionMode mode) const1697 {1698 bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);1699 if (parentClip && parent->d_ptr->isClippedAway())1700 return;1701 QRectF polyRect(polygon.boundingRect());1702 _q_adjustRect(&polyRect);1703 QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent));1704 if (r.isEmpty())1705 return;1706 1707 QPainterPath path;1708 QList<QGraphicsItem *> &children = parent->d_ptr->children;1709 for (int i = 0; i < children.size(); ++i) {1710 QGraphicsItem *item = children.at(i);1711 if (item->d_ptr->hasTransform && !item->transform().isInvertible())1712 continue;1713 1714 // Skip invisible items.1715 if (item->d_ptr->isInvisible())1716 continue;1717 1718 bool keep = false;1719 if (!item->d_ptr->isClippedAway()) {1720 // ### _q_adjustedRect is only needed because QRectF::intersects,1721 // QRectF::contains and QTransform::map() and friends don't work with1722 // flat rectangles.1723 const QRectF br(adjustedItemBoundingRect(item));1724 if (mode >= Qt::ContainsItemBoundingRect) {1725 // Polygon contains/intersects item's bounding rect1726 if (path == QPainterPath())1727 path.addPolygon(polygon);1728 if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))1729 || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {1730 items->append(item);1731 keep = true;1732 }1733 } else {1734 // Polygon contains/intersects item's shape1735 if (QRectF_intersects(polyRect, item->mapRectToParent(br))) {1736 if (path == QPainterPath())1737 path.addPolygon(polygon);1738 if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {1739 items->append(item);1740 keep = true;1741 }1742 }1743 }1744 }1745 1746 if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {1747 // Recurse into children that clip children.1748 childItems_helper(items, item, item->mapFromParent(polygon), mode);1749 }1750 }1751 }1752 1753 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,1754 const QGraphicsItem *parent,1755 const QPainterPath &path,1756 Qt::ItemSelectionMode mode) const1757 {1758 bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);1759 if (parentClip && parent->d_ptr->isClippedAway())1760 return;1761 QRectF pathRect(path.boundingRect());1762 _q_adjustRect(&pathRect);1763 QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent));1764 if (r.isEmpty())1765 return;1766 1767 QList<QGraphicsItem *> &children = parent->d_ptr->children;1768 for (int i = 0; i < children.size(); ++i) {1769 QGraphicsItem *item = children.at(i);1770 if (item->d_ptr->hasTransform && !item->transform().isInvertible())1771 continue;1772 1773 // Skip invisible items.1774 if (item->d_ptr->isInvisible())1775 continue;1776 1777 bool keep = false;1778 if (!item->d_ptr->isClippedAway()) {1779 // ### _q_adjustedRect is only needed because QRectF::intersects,1780 // QRectF::contains and QTransform::map() and friends don't work with1781 // flat rectangles.1782 const QRectF br(adjustedItemBoundingRect(item));1783 if (mode >= Qt::ContainsItemBoundingRect) {1784 // Polygon contains/intersects item's bounding rect1785 if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))1786 || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {1787 items->append(item);1788 keep = true;1789 }1790 } else {1791 // Path contains/intersects item's shape1792 if (QRectF_intersects(pathRect, item->mapRectToParent(br))) {1793 if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {1794 items->append(item);1795 keep = true;1796 }1797 }1798 }1799 }1800 1801 if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {1802 // Recurse into children that clip children.1803 childItems_helper(items, item, item->mapFromParent(path), mode);1804 }1805 }1806 }1807 1808 void QGraphicsScenePrivate::invalidateSortCache()1809 {1810 Q_Q(QGraphicsScene);1811 if (!sortCacheEnabled || updatingSortCache)1812 return;1813 1814 updatingSortCache = true;1815 QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection);1816 }1817 1818 1394 /*! 1819 1395 \internal 1820 1396 1821 Should not be exported, but we can't change that now. 1822 ### Qt 5: Remove symbol / make static 1823 */ 1824 inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) 1825 { 1826 // Return true if sibling item1 is on top of item2. 1827 const QGraphicsItemPrivate *d1 = item1->d_ptr; 1828 const QGraphicsItemPrivate *d2 = item2->d_ptr; 1829 bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; 1830 bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; 1831 if (f1 != f2) return f2; 1832 qreal z1 = d1->z; 1833 qreal z2 = d2->z; 1834 return z1 != z2 ? z1 > z2 : item1 > item2; 1835 } 1836 1837 /*! 1838 \internal 1839 1840 Should not be exported, but we can't change that now. 1841 */ 1842 inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2) 1843 { 1844 return QGraphicsScenePrivate::closestItemFirst_withoutCache(item1, item2); 1845 } 1846 1847 /*! 1848 Returns true if \a item1 is on top of \a item2. 1849 1850 \internal 1851 */ 1852 bool QGraphicsScenePrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) 1853 { 1854 // Siblings? Just check their z-values. 1855 const QGraphicsItemPrivate *d1 = item1->d_ptr; 1856 const QGraphicsItemPrivate *d2 = item2->d_ptr; 1857 if (d1->parent == d2->parent) 1858 return qt_closestLeaf(item1, item2); 1859 1860 // Find common ancestor, and each item's ancestor closest to the common 1861 // ancestor. 1862 int item1Depth = d1->depth; 1863 int item2Depth = d2->depth; 1864 const QGraphicsItem *p = item1; 1865 const QGraphicsItem *t1 = item1; 1866 while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { 1867 if (p == item2) { 1868 // item2 is one of item1's ancestors; item1 is on top 1869 return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); 1870 } 1871 t1 = p; 1872 --item1Depth; 1873 } 1874 p = item2; 1875 const QGraphicsItem *t2 = item2; 1876 while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { 1877 if (p == item1) { 1878 // item1 is one of item2's ancestors; item1 is not on top 1879 return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); 1880 } 1881 t2 = p; 1882 --item2Depth; 1883 } 1884 1885 // item1Ancestor is now at the same level as item2Ancestor, but not the same. 1886 const QGraphicsItem *a1 = t1; 1887 const QGraphicsItem *a2 = t2; 1888 while (a1) { 1889 const QGraphicsItem *p1 = a1; 1890 const QGraphicsItem *p2 = a2; 1891 a1 = a1->parentItem(); 1892 a2 = a2->parentItem(); 1893 if (a1 && a1 == a2) 1894 return qt_closestLeaf(p1, p2); 1895 } 1896 1897 // No common ancestor? Then just compare the items' toplevels directly. 1898 return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); 1899 } 1900 1901 /*! 1902 Returns true if \a item2 is on top of \a item1. 1903 1904 \internal 1905 */ 1906 bool QGraphicsScenePrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) 1907 { 1908 return closestItemFirst_withoutCache(item2, item1); 1909 } 1910 1911 void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) 1912 { 1913 if (!item->d_ptr->children.isEmpty()) { 1914 QList<QGraphicsItem *> childList = item->d_ptr->children; 1915 qSort(childList.begin(), childList.end(), qt_closestLeaf); 1916 for (int i = 0; i < childList.size(); ++i) { 1917 QGraphicsItem *item = childList.at(i); 1918 if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) 1919 climbTree(childList.at(i), stackingOrder); 1920 } 1921 item->d_ptr->globalStackingOrder = (*stackingOrder)++; 1922 for (int i = 0; i < childList.size(); ++i) { 1923 QGraphicsItem *item = childList.at(i); 1924 if (item->flags() & QGraphicsItem::ItemStacksBehindParent) 1925 climbTree(childList.at(i), stackingOrder); 1926 } 1927 } else { 1928 item->d_ptr->globalStackingOrder = (*stackingOrder)++; 1929 } 1930 } 1931 1932 void QGraphicsScenePrivate::_q_updateSortCache() 1933 { 1934 _q_updateIndex(); 1935 1936 if (!sortCacheEnabled || !updatingSortCache) 1937 return; 1938 1939 updatingSortCache = false; 1940 int stackingOrder = 0; 1941 1942 QList<QGraphicsItem *> topLevels; 1943 1944 for (int i = 0; i < indexedItems.size(); ++i) { 1945 QGraphicsItem *item = indexedItems.at(i); 1946 if (item && item->parentItem() == 0) 1947 topLevels << item; 1948 } 1949 for (int i = 0; i < unindexedItems.size(); ++i) { 1950 QGraphicsItem *item = unindexedItems.at(i); 1951 if (item->parentItem() == 0) 1952 topLevels << item; 1953 } 1954 1955 qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); 1956 for (int i = 0; i < topLevels.size(); ++i) 1957 climbTree(topLevels.at(i), &stackingOrder); 1958 } 1959 1960 void QGraphicsScenePrivate::sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order, 1961 bool sortCacheEnabled) 1962 { 1963 if (sortCacheEnabled) { 1964 if (order == Qt::AscendingOrder) { 1965 qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); 1966 } else if (order == Qt::DescendingOrder) { 1967 qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); 1968 } 1969 } else { 1970 if (order == Qt::AscendingOrder) { 1971 qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); 1972 } else if (order == Qt::DescendingOrder) { 1973 qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); 1974 } 1397 Ensures that the list of toplevels is sorted by insertion order, and that 1398 the siblingIndexes are packed (no gaps), and start at 0. 1399 1400 ### This function is almost identical to 1401 QGraphicsItemPrivate::ensureSequentialSiblingIndex(). 1402 */ 1403 void QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes() 1404 { 1405 if (!topLevelSequentialOrdering) { 1406 qSort(topLevelItems.begin(), topLevelItems.end(), QGraphicsItemPrivate::insertionOrder); 1407 topLevelSequentialOrdering = true; 1408 needSortTopLevelItems = 1; 1409 } 1410 if (holesInTopLevelSiblingIndex) { 1411 holesInTopLevelSiblingIndex = 0; 1412 for (int i = 0; i < topLevelItems.size(); ++i) 1413 topLevelItems[i]->d_ptr->siblingIndex = i; 1975 1414 } 1976 1415 } … … 1997 1436 void QGraphicsScenePrivate::resolveFont() 1998 1437 { 1999 QFont naturalFont = qApp->font();1438 QFont naturalFont = QApplication::font(); 2000 1439 naturalFont.resolve(0); 2001 1440 QFont resolvedFont = font.resolve(naturalFont); … … 2053 1492 void QGraphicsScenePrivate::resolvePalette() 2054 1493 { 2055 QPalette naturalPalette = qApp->palette();1494 QPalette naturalPalette = QApplication::palette(); 2056 1495 naturalPalette.resolve(0); 2057 1496 QPalette resolvedPalette = palette.resolve(naturalPalette); … … 2108 1547 : QObject(*new QGraphicsScenePrivate, parent) 2109 1548 { 1549 d_func()->init(); 2110 1550 setSceneRect(sceneRect); 2111 d_func()->init();2112 1551 } 2113 1552 … … 2123 1562 : QObject(*new QGraphicsScenePrivate, parent) 2124 1563 { 1564 d_func()->init(); 2125 1565 setSceneRect(x, y, width, height); 2126 d_func()->init(); 2127 } 2128 2129 /*! 2130 Destroys the QGraphicsScene object. 1566 } 1567 1568 /*! 1569 Removes and deletes all items from the scene object 1570 before destroying the scene object. The scene object 1571 is removed from the application's global scene list, 1572 and it is removed from all associated views. 2131 1573 */ 2132 1574 QGraphicsScene::~QGraphicsScene() 2133 1575 { 2134 1576 Q_D(QGraphicsScene); 1577 2135 1578 // Remove this scene from qApp's global scene list. 2136 1579 qApp->d_func()->scene_list.removeAll(this); … … 2161 1604 { 2162 1605 Q_D(const QGraphicsScene); 2163 const_cast<QGraphicsScenePrivate *>(d)->_q_updateIndex(); 2164 return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; 1606 if (d->hasSceneRect) 1607 return d->sceneRect; 1608 1609 if (d->dirtyGrowingItemsBoundingRect) { 1610 // Lazily update the growing items bounding rect 1611 QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d); 1612 QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect; 1613 thatd->growingItemsBoundingRect |= itemsBoundingRect(); 1614 thatd->dirtyGrowingItemsBoundingRect = false; 1615 if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) 1616 emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect); 1617 } 1618 return d->growingItemsBoundingRect; 2165 1619 } 2166 1620 void QGraphicsScene::setSceneRect(const QRectF &rect) … … 2170 1624 d->hasSceneRect = !rect.isNull(); 2171 1625 d->sceneRect = rect; 2172 d->resetIndex(); 2173 emit sceneRectChanged(rect); 1626 emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect); 2174 1627 } 2175 1628 } … … 2212 1665 Qt::AspectRatioMode aspectRatioMode) 2213 1666 { 2214 Q_D(QGraphicsScene);1667 // ### Switch to using the recursive rendering algorithm instead. 2215 1668 2216 1669 // Default source rect = scene rect … … 2270 1723 // Generate the style options 2271 1724 QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems]; 2272 for (int i = 0; i < numItems; ++i) { 2273 QGraphicsItem *item = itemArray[i]; 2274 2275 QStyleOptionGraphicsItem option; 2276 option.state = QStyle::State_None; 2277 option.rect = item->boundingRect().toRect(); 2278 if (item->isSelected()) 2279 option.state |= QStyle::State_Selected; 2280 if (item->isEnabled()) 2281 option.state |= QStyle::State_Enabled; 2282 if (item->hasFocus()) 2283 option.state |= QStyle::State_HasFocus; 2284 if (d->hoverItems.contains(item)) 2285 option.state |= QStyle::State_MouseOver; 2286 if (item == mouseGrabberItem()) 2287 option.state |= QStyle::State_Sunken; 2288 2289 // Calculate a simple level-of-detail metric. 2290 // ### almost identical code in QGraphicsView::paintEvent() 2291 // and QGraphicsView::render() - consider refactoring 2292 QTransform itemToDeviceTransform; 2293 if (item->d_ptr->itemIsUntransformable()) { 2294 itemToDeviceTransform = item->deviceTransform(painterTransform); 2295 } else { 2296 itemToDeviceTransform = item->sceneTransform() * painterTransform; 2297 } 2298 2299 option.levelOfDetail = qSqrt(itemToDeviceTransform.map(v1).length() * itemToDeviceTransform.map(v2).length()); 2300 option.matrix = itemToDeviceTransform.toAffine(); //### discards perspective 2301 2302 option.exposedRect = item->boundingRect(); 2303 option.exposedRect &= itemToDeviceTransform.inverted().mapRect(targetRect); 2304 2305 styleOptionArray[i] = option; 2306 } 1725 for (int i = 0; i < numItems; ++i) 1726 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect()); 2307 1727 2308 1728 // Render the scene. … … 2341 1761 { 2342 1762 Q_D(QGraphicsScene); 2343 d->resetIndex(); 1763 if (d->indexMethod == method) 1764 return; 1765 2344 1766 d->indexMethod = method; 1767 1768 QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder); 1769 delete d->index; 1770 if (method == BspTreeIndex) 1771 d->index = new QGraphicsSceneBspTreeIndex(this); 1772 else 1773 d->index = new QGraphicsSceneLinearIndex(this); 1774 for (int i = oldItems.size() - 1; i >= 0; --i) 1775 d->index->addItem(oldItems.at(i)); 2345 1776 } 2346 1777 … … 2380 1811 { 2381 1812 Q_D(const QGraphicsScene); 2382 return d->bspTreeDepth; 1813 QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index); 1814 return bspTree ? bspTree->bspTreeDepth() : 0; 2383 1815 } 2384 1816 void QGraphicsScene::setBspTreeDepth(int depth) 2385 1817 { 2386 1818 Q_D(QGraphicsScene); 2387 if (d->bspTreeDepth == depth)2388 return;2389 2390 1819 if (depth < 0) { 2391 1820 qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth); … … 2393 1822 } 2394 1823 2395 d->bspTreeDepth = depth; 2396 d->resetIndex(); 1824 QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index); 1825 if (!bspTree) { 1826 qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); 1827 return; 1828 } 1829 bspTree->setBspTreeDepth(depth); 2397 1830 } 2398 1831 … … 2401 1834 \brief whether sort caching is enabled 2402 1835 \since 4.5 2403 2404 When enabled, this property adds a cache that speeds up sorting and 2405 transformations for scenes with deep hierarchies (i.e., items with many 2406 levels of descendents), at the cost of using more memory (approx. 100 more 2407 bytes of memory per item). 2408 2409 Items that are not part of a deep hierarchy suffer no penalty from this 2410 cache. 1836 \obsolete 1837 1838 Since Qt 4.6, this property has no effect. 2411 1839 */ 2412 1840 bool QGraphicsScene::isSortCacheEnabled() const … … 2418 1846 { 2419 1847 Q_D(QGraphicsScene); 2420 if ( enabled == d->sortCacheEnabled)1848 if (d->sortCacheEnabled == enabled) 2421 1849 return; 2422 if ((d->sortCacheEnabled = enabled)) 2423 d->invalidateSortCache(); 1850 d->sortCacheEnabled = enabled; 2424 1851 } 2425 1852 … … 2433 1860 QRectF QGraphicsScene::itemsBoundingRect() const 2434 1861 { 1862 // Does not take untransformable items into account. 2435 1863 QRectF boundingRect; 2436 1864 foreach (QGraphicsItem *item, items()) … … 2440 1868 2441 1869 /*! 2442 Returns a list of all items on the scene, in no particularorder.2443 2444 \sa addItem(), removeItem() 1870 Returns a list of all items in the scene in descending stacking order. 1871 1872 \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting} 2445 1873 */ 2446 1874 QList<QGraphicsItem *> QGraphicsScene::items() const 2447 1875 { 2448 1876 Q_D(const QGraphicsScene); 2449 const_cast<QGraphicsScenePrivate *>(d)->purgeRemovedItems(); 2450 2451 // If freeItemIndexes is empty, we know there are no holes in indexedItems and 2452 // unindexedItems. 2453 if (d->freeItemIndexes.isEmpty()) { 2454 if (d->unindexedItems.isEmpty()) 2455 return d->indexedItems; 2456 return d->indexedItems + d->unindexedItems; 2457 } 2458 2459 // Rebuild the list of items to avoid holes. ### We could also just 2460 // compress the item lists at this point. 2461 QList<QGraphicsItem *> itemList; 2462 foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { 2463 if (item) 2464 itemList << item; 2465 } 2466 return itemList; 2467 } 2468 2469 /*! 1877 return d->index->items(Qt::DescendingOrder); 1878 } 1879 1880 /*! 1881 Returns an ordered list of all items on the scene. \a order decides the 1882 stacking order. 1883 1884 \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting} 1885 */ 1886 QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const 1887 { 1888 Q_D(const QGraphicsScene); 1889 return d->index->items(order); 1890 } 1891 1892 /*! 1893 \obsolete 1894 2470 1895 Returns all visible items at position \a pos in the scene. The items are 2471 listed in descending Zorder (i.e., the first item in the list is the1896 listed in descending stacking order (i.e., the first item in the list is the 2472 1897 top-most item, and the last item is the bottom-most item). 2473 1898 2474 \sa itemAt() 1899 This function is deprecated and returns incorrect results if the scene 1900 contains items that ignore transformations. Use the overload that takes 1901 a QTransform instead. 1902 1903 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 2475 1904 */ 2476 1905 QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const 2477 1906 { 2478 1907 Q_D(const QGraphicsScene); 2479 return d->items_helper(pos); 2480 } 2481 2482 2483 /*! 2484 \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const 2485 1908 return d->index->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder); 1909 } 1910 1911 /*! 2486 1912 \overload 1913 \obsolete 2487 1914 2488 1915 Returns all visible items that, depending on \a mode, are either inside or … … 2492 1919 exact shape intersects with or is contained by \a rectangle are returned. 2493 1920 2494 \sa itemAt() 2495 */ 2496 QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const 1921 This function is deprecated and returns incorrect results if the scene 1922 contains items that ignore transformations. Use the overload that takes 1923 a QTransform instead. 1924 1925 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 1926 */ 1927 QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const 2497 1928 { 2498 1929 Q_D(const QGraphicsScene); 2499 return d->i tems_helper(rect, mode, Qt::AscendingOrder);1930 return d->index->items(rectangle, mode, Qt::DescendingOrder); 2500 1931 } 2501 1932 2502 1933 /*! 2503 1934 \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const 1935 \obsolete 2504 1936 \since 4.3 2505 1937 2506 1938 This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode). 2507 */ 2508 2509 /*! 1939 1940 This function is deprecated and returns incorrect results if the scene 1941 contains items that ignore transformations. Use the overload that takes 1942 a QTransform instead. 1943 */ 1944 1945 /*! 1946 \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const 2510 1947 \overload 1948 \since 4.6 1949 1950 \brief Returns all visible items that, depending on \a mode, are 1951 either inside or intersect with the rectangle defined by \a x, \a y, 1952 \a w and \a h, in a list sorted using \a order. 1953 1954 \a deviceTransform is the transformation that applies to the view, and needs to 1955 be provided if the scene contains items that ignore transformations. 1956 */ 1957 1958 /*! 1959 \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const 1960 \overload 1961 \obsolete 2511 1962 2512 1963 Returns all visible items that, depending on \a mode, are either inside or … … 2516 1967 exact shape intersects with or is contained by \a polygon are returned. 2517 1968 2518 \sa itemAt() 1969 This function is deprecated and returns incorrect results if the scene 1970 contains items that ignore transformations. Use the overload that takes 1971 a QTransform instead. 1972 1973 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 2519 1974 */ 2520 1975 QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const 2521 1976 { 2522 1977 Q_D(const QGraphicsScene); 2523 return d->items_helper(polygon, mode, Qt::AscendingOrder); 2524 } 2525 2526 /*! 1978 return d->index->items(polygon, mode, Qt::DescendingOrder); 1979 } 1980 1981 /*! 1982 \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const 2527 1983 \overload 1984 \obsolete 2528 1985 2529 1986 Returns all visible items that, depending on \a path, are either inside or … … 2533 1990 exact shape intersects with or is contained by \a path are returned. 2534 1991 2535 \sa itemAt() 1992 This function is deprecated and returns incorrect results if the scene 1993 contains items that ignore transformations. Use the overload that takes 1994 a QTransform instead. 1995 1996 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 2536 1997 */ 2537 1998 QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const 2538 1999 { 2539 2000 Q_D(const QGraphicsScene); 2540 return d->items_helper(path, mode, Qt::AscendingOrder); 2001 return d->index->items(path, mode, Qt::DescendingOrder); 2002 } 2003 2004 /*! 2005 \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const 2006 \since 4.6 2007 2008 \brief Returns all visible items that, depending on \a mode, are at 2009 the specified \a pos in a list sorted using \a order. 2010 2011 The default value for \a mode is Qt::IntersectsItemShape; all items whose 2012 exact shape intersects with \a pos are returned. 2013 2014 \a deviceTransform is the transformation that applies to the view, and needs to 2015 be provided if the scene contains items that ignore transformations. 2016 2017 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 2018 */ 2019 QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, 2020 Qt::SortOrder order, const QTransform &deviceTransform) const 2021 { 2022 Q_D(const QGraphicsScene); 2023 return d->index->items(pos, mode, order, deviceTransform); 2024 } 2025 2026 /*! 2027 \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const 2028 \overload 2029 \since 4.6 2030 2031 \brief Returns all visible items that, depending on \a mode, are 2032 either inside or intersect with the specified \a rect and return a 2033 list sorted using \a order. 2034 2035 The default value for \a mode is Qt::IntersectsItemShape; all items whose 2036 exact shape intersects with or is contained by \a rect are returned. 2037 2038 \a deviceTransform is the transformation that applies to the view, and needs to 2039 be provided if the scene contains items that ignore transformations. 2040 2041 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 2042 */ 2043 QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, 2044 Qt::SortOrder order, const QTransform &deviceTransform) const 2045 { 2046 Q_D(const QGraphicsScene); 2047 return d->index->items(rect, mode, order, deviceTransform); 2048 } 2049 2050 /*! 2051 \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const 2052 \overload 2053 \since 4.6 2054 2055 \brief Returns all visible items that, depending on \a mode, are 2056 either inside or intersect with the specified \a polygon and return 2057 a list sorted using \a order. 2058 2059 The default value for \a mode is Qt::IntersectsItemShape; all items whose 2060 exact shape intersects with or is contained by \a polygon are returned. 2061 2062 \a deviceTransform is the transformation that applies to the view, and needs to 2063 be provided if the scene contains items that ignore transformations. 2064 2065 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 2066 */ 2067 QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, 2068 Qt::SortOrder order, const QTransform &deviceTransform) const 2069 { 2070 Q_D(const QGraphicsScene); 2071 return d->index->items(polygon, mode, order, deviceTransform); 2072 } 2073 2074 /*! 2075 \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const 2076 \overload 2077 \since 4.6 2078 2079 \brief Returns all visible items that, depending on \a mode, are 2080 either inside or intersect with the specified \a path and return a 2081 list sorted using \a order. 2082 2083 The default value for \a mode is Qt::IntersectsItemShape; all items whose 2084 exact shape intersects with or is contained by \a path are returned. 2085 2086 \a deviceTransform is the transformation that applies to the view, and needs to 2087 be provided if the scene contains items that ignore transformations. 2088 2089 \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} 2090 */ 2091 QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, 2092 Qt::SortOrder order, const QTransform &deviceTransform) const 2093 { 2094 Q_D(const QGraphicsScene); 2095 return d->index->items(path, mode, order, deviceTransform); 2541 2096 } 2542 2097 … … 2547 2102 intersects \a item or is contained inside \a item's shape are returned. 2548 2103 2549 The items are returned in descending Z order (i.e., the first item in the 2550 list is the top-most item, and the last item is the bottom-most item). 2551 2552 \sa items(), itemAt(), QGraphicsItem::collidesWithItem() 2104 The items are returned in descending stacking order (i.e., the first item 2105 in the list is the uppermost item, and the last item is the lowermost 2106 item). 2107 2108 \sa items(), itemAt(), QGraphicsItem::collidesWithItem(), {QGraphicsItem#Sorting}{Sorting} 2553 2109 */ 2554 2110 QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item, … … 2561 2117 } 2562 2118 2119 // Does not support ItemIgnoresTransformations. 2563 2120 QList<QGraphicsItem *> tmp; 2564 foreach (QGraphicsItem *itemInVicinity, d-> estimateItemsInRect(item->sceneBoundingRect())) {2121 foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder)) { 2565 2122 if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) 2566 2123 tmp << itemInVicinity; 2567 2124 } 2568 d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled);2569 2125 return tmp; 2570 2126 } 2571 2127 2572 2128 /*! 2573 \fn QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const 2129 \overload 2130 \obsolete 2574 2131 2575 2132 Returns the topmost visible item at the specified \a position, or 0 if 2576 2133 there are no items at this position. 2577 2134 2578 \note The topmost item is the one with the highest Z-value. 2579 2580 \sa items(), collidingItems(), QGraphicsItem::setZValue() 2581 */ 2582 QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const 2583 { 2584 QList<QGraphicsItem *> itemsAtPoint = items(pos); 2135 This function is deprecated and returns incorrect results if the scene 2136 contains items that ignore transformations. Use the overload that takes 2137 a QTransform instead. 2138 2139 \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting} 2140 */ 2141 QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const 2142 { 2143 QList<QGraphicsItem *> itemsAtPoint = items(position); 2585 2144 return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); 2586 2145 } 2146 2147 /*! 2148 \since 4.6 2149 2150 Returns the topmost visible item at the specified \a position, or 0 2151 if there are no items at this position. 2152 2153 \a deviceTransform is the transformation that applies to the view, and needs to 2154 be provided if the scene contains items that ignore transformations. 2155 2156 \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting} 2157 */ 2158 QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const 2159 { 2160 QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape, 2161 Qt::DescendingOrder, deviceTransform); 2162 return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); 2163 } 2164 2165 /*! 2166 \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const 2167 \overload 2168 \since 4.6 2169 2170 Returns the topmost item at the position specified by (\a x, \a 2171 y), or 0 if there are no items at this position. 2172 2173 \a deviceTransform is the transformation that applies to the view, and needs to 2174 be provided if the scene contains items that ignore transformations. 2175 2176 This convenience function is equivalent to calling \c 2177 {itemAt(QPointF(x, y), deviceTransform)}. 2178 */ 2587 2179 2588 2180 /*! 2589 2181 \fn QGraphicsScene::itemAt(qreal x, qreal y) const 2590 2182 \overload 2183 \obsolete 2591 2184 2592 2185 Returns the topmost item at the position specified by (\a x, \a … … 2596 2189 {itemAt(QPointF(x, y))}. 2597 2190 2598 \note The topmost item is the one with the highest Z-value. 2191 This function is deprecated and returns incorrect results if the scene 2192 contains items that ignore transformations. Use the overload that takes 2193 a QTransform instead. 2599 2194 */ 2600 2195 … … 2636 2231 2637 2232 /*! 2233 \since 4.6 2234 2638 2235 Sets the selection area to \a path. All items within this area are 2639 2236 immediately selected, and all items outside are unselected. You can get 2640 2237 the list of all selected items by calling selectedItems(). 2641 2238 2239 \a deviceTransform is the transformation that applies to the view, and needs to 2240 be provided if the scene contains items that ignore transformations. 2241 2642 2242 For an item to be selected, it must be marked as \e selectable 2643 2243 (QGraphicsItem::ItemIsSelectable). … … 2645 2245 \sa clearSelection(), selectionArea() 2646 2246 */ 2247 void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform) 2248 { 2249 setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform); 2250 } 2251 2252 /*! 2253 \obsolete 2254 \overload 2255 2256 Sets the selection area to \a path. 2257 2258 This function is deprecated and leads to incorrect results if the scene 2259 contains items that ignore transformations. Use the overload that takes 2260 a QTransform instead. 2261 */ 2647 2262 void QGraphicsScene::setSelectionArea(const QPainterPath &path) 2648 2263 { 2649 setSelectionArea(path, Qt::IntersectsItemShape); 2650 } 2651 2652 /*! 2264 setSelectionArea(path, Qt::IntersectsItemShape, QTransform()); 2265 } 2266 2267 /*! 2268 \obsolete 2653 2269 \overload 2654 2270 \since 4.3 … … 2660 2276 */ 2661 2277 void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode) 2278 { 2279 setSelectionArea(path, mode, QTransform()); 2280 } 2281 2282 /*! 2283 \overload 2284 \since 4.6 2285 2286 Sets the selection area to \a path using \a mode to determine if items are 2287 included in the selection area. 2288 2289 \a deviceTransform is the transformation that applies to the view, and needs to 2290 be provided if the scene contains items that ignore transformations. 2291 2292 \sa clearSelection(), selectionArea() 2293 */ 2294 void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, 2295 const QTransform &deviceTransform) 2662 2296 { 2663 2297 Q_D(QGraphicsScene); … … 2676 2310 2677 2311 // Set all items in path to selected. 2678 foreach (QGraphicsItem *item, items(path, mode )) {2312 foreach (QGraphicsItem *item, items(path, mode, Qt::DescendingOrder, deviceTransform)) { 2679 2313 if (item->flags() & QGraphicsItem::ItemIsSelectable) { 2680 2314 if (!item->isSelected()) … … 2733 2367 { 2734 2368 Q_D(QGraphicsScene); 2735 // Recursive descent delete 2736 for (int i = 0; i < d->indexedItems.size(); ++i) { 2737 if (QGraphicsItem *item = d->indexedItems.at(i)) { 2738 if (!item->parentItem()) 2739 delete item; 2740 } 2741 } 2742 QList<QGraphicsItem *> unindexedParents; 2743 for (int i = 0; i < d->unindexedItems.size(); ++i) { 2744 QGraphicsItem *item = d->unindexedItems.at(i); 2745 if (!item->parentItem()) 2746 unindexedParents << item; 2747 } 2748 d->unindexedItems.clear(); 2749 qDeleteAll(unindexedParents); 2750 2751 d->indexedItems.clear(); 2752 d->freeItemIndexes.clear(); 2369 // NB! We have to clear the index before deleting items; otherwise the 2370 // index might try to access dangling item pointers. 2371 d->index->clear(); 2372 // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items 2373 while (!d->topLevelItems.isEmpty()) 2374 delete d->topLevelItems.first(); 2375 Q_ASSERT(d->topLevelItems.isEmpty()); 2753 2376 d->lastItemCount = 0; 2754 d->bspTree.clear(); 2755 d->largestUntransformableItem = QRectF(); 2377 d->allItemsIgnoreHoverEvents = true; 2378 d->allItemsUseDefaultCursor = true; 2379 d->allItemsIgnoreTouchEvents = true; 2756 2380 } 2757 2381 … … 2828 2452 2829 2453 /*! 2830 Adds or moves the item \a item and all its childen to the scene. 2454 Adds or moves the \a item and all its childen to this scene. 2455 This scene takes ownership of the \a item. 2831 2456 2832 2457 If the item is visible (i.e., QGraphicsItem::isVisible() returns … … 2834 2459 to the event loop. 2835 2460 2836 If the item is already in a different scene, it will first be removed from 2837 its old scene, and then added to this scene as a top-level. 2838 2839 QGraphicsScene will send ItemSceneChange notifications to \a item while 2840 it is added to the scene. If item does not currently belong to a scene, only one 2841 notification is sent. If it does belong to scene already (i.e., it is 2842 moved to this scene), QGraphicsScene will send an addition notification as 2843 the item is removed from its previous scene. 2461 If the item is already in a different scene, it will first be 2462 removed from its old scene, and then added to this scene as a 2463 top-level. 2464 2465 QGraphicsScene will send ItemSceneChange notifications to \a item 2466 while it is added to the scene. If item does not currently belong 2467 to a scene, only one notification is sent. If it does belong to 2468 scene already (i.e., it is moved to this scene), QGraphicsScene 2469 will send an addition notification as the item is removed from its 2470 previous scene. 2471 2472 If the item is a panel, the scene is active, and there is no 2473 active panel in the scene, then the item will be activated. 2844 2474 2845 2475 \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(), 2846 addRect(), addText(), addWidget() 2476 addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting} 2847 2477 */ 2848 2478 void QGraphicsScene::addItem(QGraphicsItem *item) … … 2857 2487 return; 2858 2488 } 2859 2860 2489 // Remove this item from its existing scene 2861 2490 if (QGraphicsScene *oldScene = item->scene()) … … 2873 2502 } 2874 2503 2875 // Prevent reusing a recently deleted pointer: purge all removed items2876 // from our lists.2877 d->purgeRemovedItems();2878 2879 // Invalidate any sort caching; arrival of a new item means we need to2880 // resort.2881 d->invalidateSortCache();2882 2883 2504 // Detach this item from its parent if the parent's scene is different 2884 2505 // from this scene. … … 2891 2512 item->d_func()->scene = targetScene; 2892 2513 2893 // Indexing requires sceneBoundingRect(), but because \a item might 2894 // not be completely constructed at this point, we need to store it in 2895 // a temporary list and schedule an indexing for later. 2896 d->unindexedItems << item; 2897 item->d_func()->index = -1; 2898 d->startIndexTimer(); 2899 2900 // Update the scene's sort cache settings. 2901 item->d_ptr->globalStackingOrder = -1; 2902 d->invalidateSortCache(); 2514 // Add the item in the index 2515 d->index->addItem(item); 2516 2517 // Add to list of toplevels if this item is a toplevel. 2518 if (!item->d_ptr->parent) 2519 d->registerTopLevelItem(item); 2903 2520 2904 2521 // Add to list of items that require an update. We cannot assume that the 2905 2522 // item is fully constructed, so calling item->update() can lead to a pure 2906 2523 // virtual function call to boundingRect(). 2907 if (!d->updateAll) { 2908 if (d->pendingUpdateItems.isEmpty()) 2909 QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection); 2910 d->pendingUpdateItems << item; 2911 } 2524 d->markDirty(item); 2525 d->dirtyGrowingItemsBoundingRect = true; 2912 2526 2913 2527 // Disable selectionChanged() for individual items 2914 2528 ++d->selectionChanging; 2915 2529 int oldSelectedItemSize = d->selectedItems.size(); 2530 2531 // Enable mouse tracking if the item accepts hover events or has a cursor set. 2532 if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) { 2533 d->allItemsIgnoreHoverEvents = false; 2534 d->enableMouseTrackingOnViews(); 2535 } 2536 #ifndef QT_NO_CURSOR 2537 if (d->allItemsUseDefaultCursor && item->hasCursor()) { 2538 d->allItemsUseDefaultCursor = false; 2539 if (d->allItemsIgnoreHoverEvents) // already enabled otherwise 2540 d->enableMouseTrackingOnViews(); 2541 } 2542 #endif //QT_NO_CURSOR 2543 2544 // Enable touch events if the item accepts touch events. 2545 if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) { 2546 d->allItemsIgnoreTouchEvents = false; 2547 d->enableTouchEventsOnViews(); 2548 } 2916 2549 2917 2550 // Update selection lists … … 2920 2553 if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup) 2921 2554 d->addPopup(static_cast<QGraphicsWidget *>(item)); 2555 if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) 2556 d->enterModal(item); 2922 2557 2923 2558 // Update creation order focus chain. Make sure to leave the widget's … … 2948 2583 item->d_ptr->resolvePalette(d->palette.resolve()); 2949 2584 2950 if (!item->d_ptr->explicitlyHidden) { 2951 if (d->unpolishedItems.isEmpty()) 2952 QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); 2953 d->unpolishedItems << item; 2954 } 2585 if (d->unpolishedItems.isEmpty()) 2586 QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); 2587 d->unpolishedItems.insert(item); 2588 d->unpolishedItemsModified = true; 2955 2589 2956 2590 // Reenable selectionChanged() for individual items … … 2961 2595 // Deliver post-change notification 2962 2596 item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); 2597 2598 // Update explicit activation 2599 bool autoActivate = true; 2600 if (!d->childExplicitActivation && item->d_ptr->explicitActivate) 2601 d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2; 2602 if (d->childExplicitActivation && item->isPanel()) { 2603 if (d->childExplicitActivation == 1) 2604 setActivePanel(item); 2605 else 2606 autoActivate = false; 2607 d->childExplicitActivation = 0; 2608 } else if (!item->d_ptr->parent) { 2609 d->childExplicitActivation = 0; 2610 } 2611 2612 // Auto-activate this item's panel if nothing else has been activated 2613 if (autoActivate) { 2614 if (!d->lastActivePanel && !d->activePanel && item->isPanel()) { 2615 if (isActive()) 2616 setActivePanel(item); 2617 else 2618 d->lastActivePanel = item; 2619 } 2620 } 2621 2622 if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) 2623 d->registerScenePosItem(item); 2624 2625 // Ensure that newly added items that have subfocus set, gain 2626 // focus automatically if there isn't a focus item already. 2627 if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item) 2628 item->focusItem()->setFocus(); 2629 2630 d->updateInputMethodSensitivityInViews(); 2963 2631 } 2964 2632 … … 3232 2900 } 3233 2901 3234 // If the item has focus, remove it (and any focusWidget reference). 3235 item->clearFocus(); 3236 3237 // Clear its background 3238 item->update(); 3239 3240 // Note: This will access item's sceneBoundingRect(), which (as this is 3241 // C++) is why we cannot call removeItem() from QGraphicsItem's 3242 // destructor. 3243 d->removeFromIndex(item); 3244 3245 if (item == d->tabFocusFirst) { 3246 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); 3247 widget->d_func()->fixFocusChainBeforeReparenting(0, 0); 3248 } 3249 // Set the item's scene ptr to 0. 3250 item->d_func()->scene = 0; 3251 3252 // Detach the item from its parent. 3253 if (QGraphicsItem *parentItem = item->parentItem()) { 3254 if (parentItem->scene()) { 3255 Q_ASSERT_X(parentItem->scene() == this, "QGraphicsScene::removeItem", 3256 "Parent item's scene is different from this item's scene"); 3257 item->setParentItem(0); 3258 } 3259 } 3260 3261 // Remove from our item lists. 3262 int index = item->d_func()->index; 3263 if (index != -1) { 3264 d->freeItemIndexes << index; 3265 d->indexedItems[index] = 0; 3266 } else { 3267 d->unindexedItems.removeAll(item); 3268 } 3269 3270 // Remove from scene transform cache 3271 int transformIndex = item->d_func()->sceneTransformIndex; 3272 if (transformIndex != -1) { 3273 d->validTransforms.setBit(transformIndex, 0); 3274 d->freeSceneTransformSlots.append(transformIndex); 3275 item->d_func()->sceneTransformIndex = -1; 3276 } 3277 3278 if (item == d->focusItem) 3279 d->focusItem = 0; 3280 if (item == d->lastFocusItem) 3281 d->lastFocusItem = 0; 3282 if (item == d->activeWindow) { 3283 // ### deactivate... 3284 d->activeWindow = 0; 3285 } 3286 3287 // Disable selectionChanged() for individual items 3288 ++d->selectionChanging; 3289 int oldSelectedItemsSize = d->selectedItems.size(); 3290 3291 // Update selected & hovered item bookkeeping 3292 d->selectedItems.remove(item); 3293 d->hoverItems.removeAll(item); 3294 d->pendingUpdateItems.removeAll(item); 3295 d->cachedItemsUnderMouse.removeAll(item); 3296 d->unpolishedItems.removeAll(item); 3297 d->dirtyItems.removeAll(item); 3298 3299 //We remove all references of item from the sceneEventFilter arrays 3300 QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = d->sceneEventFilters.begin(); 3301 while (iterator != d->sceneEventFilters.end()) { 3302 if (iterator.value() == item || iterator.key() == item) 3303 iterator = d->sceneEventFilters.erase(iterator); 3304 else 3305 ++iterator; 3306 } 3307 3308 3309 //Ensure dirty flag have the correct default value so the next time it will be added it will receive updates 3310 item->d_func()->dirty = 0; 3311 item->d_func()->dirtyChildren = 0; 3312 3313 // Remove all children recursively 3314 foreach (QGraphicsItem *child, item->children()) 3315 removeItem(child); 3316 3317 // Reset the mouse grabber and focus item data. 3318 if (d->mouseGrabberItems.contains(item)) 3319 d->ungrabMouse(item); 3320 3321 // Reset the keyboard grabber 3322 if (d->keyboardGrabberItems.contains(item)) 3323 item->ungrabKeyboard(); 3324 3325 // Reset the last mouse grabber item 3326 if (item == d->lastMouseGrabberItem) 3327 d->lastMouseGrabberItem = 0; 3328 3329 // Reenable selectionChanged() for individual items 3330 --d->selectionChanging; 3331 3332 if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemsSize) 3333 emit selectionChanged(); 2902 d->removeItemHelper(item); 3334 2903 3335 2904 // Deliver post-change notification 3336 2905 item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); 3337 } 3338 3339 /*! 3340 Returns the scene's current focus item, or 0 if no item currently has 3341 focus. 2906 2907 d->updateInputMethodSensitivityInViews(); 2908 } 2909 2910 /*! 2911 When the scene is active, this functions returns the scene's current focus 2912 item, or 0 if no item currently has focus. When the scene is inactive, this 2913 functions returns the item that will gain input focus when the scene becomes 2914 active. 3342 2915 3343 2916 The focus item receives keyboard input when the scene receives a 3344 2917 key event. 3345 2918 3346 \sa setFocusItem(), QGraphicsItem::hasFocus() 2919 \sa setFocusItem(), QGraphicsItem::hasFocus(), isActive() 3347 2920 */ 3348 2921 QGraphicsItem *QGraphicsScene::focusItem() const 3349 2922 { 3350 2923 Q_D(const QGraphicsScene); 3351 return d->focusItem;2924 return isActive() ? d->focusItem : d->lastFocusItem; 3352 2925 } 3353 2926 … … 3371 2944 { 3372 2945 Q_D(QGraphicsScene); 3373 if (item == d->focusItem) 3374 return; 3375 if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable) 3376 || !item->isVisible() || !item->isEnabled())) { 3377 item = 0; 3378 } 3379 3380 if (item) { 3381 setFocus(focusReason); 3382 if (item == d->focusItem) 3383 return; 3384 } 3385 3386 if (d->focusItem) { 3387 QFocusEvent event(QEvent::FocusOut, focusReason); 3388 d->lastFocusItem = d->focusItem; 3389 d->focusItem = 0; 3390 d->sendEvent(d->lastFocusItem, &event); 3391 } 3392 3393 if (item) { 3394 if (item->isWidget()) { 3395 // Update focus child chain. 3396 static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget(); 3397 } 3398 3399 d->focusItem = item; 3400 QFocusEvent event(QEvent::FocusIn, focusReason); 3401 d->sendEvent(item, &event); 3402 } 2946 if (item) 2947 item->setFocus(focusReason); 2948 else 2949 d->setFocusItemHelper(item, focusReason); 3403 2950 } 3404 2951 … … 3429 2976 { 3430 2977 Q_D(QGraphicsScene); 3431 if (d->hasFocus )2978 if (d->hasFocus || !isActive()) 3432 2979 return; 3433 2980 QFocusEvent event(QEvent::FocusIn, focusReason); … … 3455 3002 /*! 3456 3003 \property QGraphicsScene::stickyFocus 3457 \brief whether or not clicking the scene will clear focus 3458 3459 If this property is false (the default), then clicking on the scene 3460 background or on an item that does not accept focus, will clear 3461 focus. Otherwise, focus will remain unchanged. 3462 3463 The focus change happens in response to a mouse press. You can reimplement 3004 \brief whether clicking into the scene background will clear focus 3005 3006 \since 4.6 3007 3008 In a QGraphicsScene with stickyFocus set to true, focus will remain 3009 unchanged when the user clicks into the scene background or on an item 3010 that does not accept focus. Otherwise, focus will be cleared. 3011 3012 By default, this property is false. 3013 3014 Focus changes in response to a mouse press. You can reimplement 3464 3015 mousePressEvent() in a subclass of QGraphicsScene to toggle this property 3465 3016 based on where the user has clicked. … … 3584 3135 { 3585 3136 Q_D(const QGraphicsScene); 3586 if (!d->focusItem )3137 if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) 3587 3138 return QVariant(); 3588 3139 const QTransform matrix = d->focusItem->sceneTransform(); … … 3613 3164 // Check if anyone's connected; if not, we can send updates directly to 3614 3165 // the views. Otherwise or if there are no views, use old behavior. 3615 bool directUpdates = !(d-> connectedSignals & d->changedSignalMask) && !d->views.isEmpty();3166 bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty(); 3616 3167 if (rect.isNull()) { 3617 3168 d->updateAll = true; … … 3620 3171 // Update all views. 3621 3172 for (int i = 0; i < d->views.size(); ++i) 3622 d->views.at(i)->d_func()-> updateAll();3173 d->views.at(i)->d_func()->fullUpdatePending = true; 3623 3174 } 3624 3175 } else { … … 3634 3185 } 3635 3186 3636 if (!d irectUpdates && !d->calledEmitUpdated) {3187 if (!d->calledEmitUpdated) { 3637 3188 d->calledEmitUpdated = true; 3638 3189 QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection); … … 3745 3296 case QEvent::GraphicsSceneHoverLeave: 3746 3297 case QEvent::GraphicsSceneHoverMove: 3298 case QEvent::TouchBegin: 3299 case QEvent::TouchUpdate: 3300 case QEvent::TouchEnd: 3747 3301 // Reset the under-mouse list to ensure that this event gets fresh 3748 3302 // item-under-mouse data. Be careful about this list; if people delete … … 3750 3304 // having stale pointers in it. We need to clear it before dispatching 3751 3305 // events that use it. 3306 // ### this should only be cleared if we received a new mouse move event, 3307 // which relies on us fixing the replay mechanism in QGraphicsView. 3752 3308 d->cachedItemsUnderMouse.clear(); 3753 3309 default: … … 3805 3361 return false; 3806 3362 case QEvent::GraphicsSceneMouseMove: 3807 mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); 3363 { 3364 QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event); 3365 d->lastSceneMousePos = mouseEvent->scenePos(); 3366 mouseMoveEvent(mouseEvent); 3808 3367 break; 3368 } 3809 3369 case QEvent::GraphicsSceneMousePress: 3810 3370 mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); … … 3828 3388 case QEvent::GraphicsSceneHoverLeave: 3829 3389 case QEvent::GraphicsSceneHoverMove: 3830 d->dispatchHoverEvent(static_cast<QGraphicsSceneHoverEvent *>(event)); 3390 { 3391 QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event); 3392 d->lastSceneMousePos = hoverEvent->scenePos(); 3393 d->dispatchHoverEvent(hoverEvent); 3831 3394 break; 3395 } 3832 3396 case QEvent::Leave: 3833 3397 d->leaveScene(); … … 3839 3403 inputMethodEvent(static_cast<QInputMethodEvent *>(event)); 3840 3404 break; 3841 case QEvent::WindowActivate: {3405 case QEvent::WindowActivate: 3842 3406 if (!d->activationRefCount++) { 3843 // Notify all non-window widgets. 3844 foreach (QGraphicsItem *item, items()) { 3845 if (item->isWidget() && item->isVisible() && !item->isWindow() && !item->parentWidget()) { 3846 QEvent event(QEvent::WindowActivate); 3847 QApplication::sendEvent(static_cast<QGraphicsWidget *>(item), &event); 3407 if (d->lastActivePanel) { 3408 // Activate the last panel. 3409 d->setActivePanelHelper(d->lastActivePanel, true); 3410 } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) { 3411 // Activate the panel of the first item in the tab focus 3412 // chain. 3413 d->setActivePanelHelper(d->tabFocusFirst, true); 3414 } else { 3415 // Activate all toplevel items. 3416 QEvent event(QEvent::WindowActivate); 3417 foreach (QGraphicsItem *item, items()) { 3418 if (item->isVisible() && !item->isPanel() && !item->parentItem()) 3419 sendEvent(item, &event); 3848 3420 } 3849 3421 } 3850 3851 // Restore window activation.3852 QGraphicsItem *nextFocusItem = d->focusItem ? d->focusItem : d->lastFocusItem;3853 if (nextFocusItem && nextFocusItem->window())3854 setActiveWindow(static_cast<QGraphicsWidget *>(nextFocusItem));3855 else if (d->tabFocusFirst && d->tabFocusFirst->isWindow())3856 setActiveWindow(d->tabFocusFirst);3857 3422 } 3858 3423 break; 3859 } 3860 case QEvent::WindowDeactivate: { 3424 case QEvent::WindowDeactivate: 3861 3425 if (!--d->activationRefCount) { 3862 // Remove window activation. 3863 setActiveWindow(0); 3864 3865 // Notify all non-window widgets. 3866 foreach (QGraphicsItem *item, items()) { 3867 if (item->isWidget() && item->isVisible() && !item->isWindow() && !item->parentWidget()) { 3868 QEvent event(QEvent::WindowDeactivate); 3869 QApplication::sendEvent(static_cast<QGraphicsWidget *>(item), &event); 3426 if (d->activePanel) { 3427 // Deactivate the active panel (but keep it so we can 3428 // reactivate it later). 3429 QGraphicsItem *lastActivePanel = d->activePanel; 3430 d->setActivePanelHelper(0, true); 3431 d->lastActivePanel = lastActivePanel; 3432 } else { 3433 // Activate all toplevel items. 3434 QEvent event(QEvent::WindowDeactivate); 3435 foreach (QGraphicsItem *item, items()) { 3436 if (item->isVisible() && !item->isPanel() && !item->parentItem()) 3437 sendEvent(item, &event); 3870 3438 } 3871 3439 } 3872 3440 } 3873 3441 break; 3874 }3875 3442 case QEvent::ApplicationFontChange: { 3876 3443 // Resolve the existing scene font. … … 3896 3463 update(); 3897 3464 break; 3898 case QEvent::Timer: 3899 if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) { 3900 if (d->restartIndexTimer) { 3901 d->restartIndexTimer = false; 3902 } else { 3903 // this call will kill the timer 3904 d->_q_updateIndex(); 3905 } 3906 } 3907 // Fallthrough intended - support timers in subclasses. 3465 case QEvent::TouchBegin: 3466 case QEvent::TouchUpdate: 3467 case QEvent::TouchEnd: 3468 d->touchEventHandler(static_cast<QTouchEvent *>(event)); 3469 break; 3470 case QEvent::Gesture: 3471 case QEvent::GestureOverride: 3472 d->gestureEventHandler(static_cast<QGestureEvent *>(event)); 3473 break; 3908 3474 default: 3909 3475 return QObject::event(event); … … 3925 3491 switch (event->type()) { 3926 3492 case QEvent::ApplicationPaletteChange: 3927 qApp->postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));3493 QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange)); 3928 3494 break; 3929 3495 case QEvent::ApplicationFontChange: 3930 qApp->postEvent(this, new QEvent(QEvent::ApplicationFontChange));3496 QApplication::postEvent(this, new QEvent(QEvent::ApplicationFontChange)); 3931 3497 break; 3932 3498 default: … … 4194 3760 point = helpEvent->screenPos(); 4195 3761 } 4196 QToolTip::showText(point, text );3762 QToolTip::showText(point, text, helpEvent->widget()); 4197 3763 helpEvent->setAccepted(!text.isEmpty()); 4198 3764 #endif … … 4201 3767 bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const 4202 3768 { 4203 return item->acceptHoverEvents() 4204 || (item->isWidget() && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()); 3769 return (!item->isBlockedByModalPanel() && 3770 (item->acceptHoverEvents() 3771 || (item->isWidget() 3772 && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))); 4205 3773 } 4206 3774 … … 4215 3783 bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent) 4216 3784 { 3785 if (allItemsIgnoreHoverEvents) 3786 return false; 3787 4217 3788 // Find the first item that accepts hover events, reusing earlier 4218 3789 // calculated data is possible. … … 4237 3808 while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem)) 4238 3809 commonAncestorItem = commonAncestorItem->parentItem(); 4239 if (commonAncestorItem && commonAncestorItem-> window() != item->window()) {4240 // The common ancestor isn't in the same windowas the two hovered3810 if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) { 3811 // The common ancestor isn't in the same panel as the two hovered 4241 3812 // items. 4242 3813 commonAncestorItem = 0; … … 4259 3830 while (parent && parent != commonAncestorItem) { 4260 3831 parents.prepend(parent); 4261 if (parent->is Window()) {4262 // Stop at the window- we don't deliver beyond this point.3832 if (parent->isPanel()) { 3833 // Stop at the panel - we don't deliver beyond this point. 4263 3834 break; 4264 3835 } … … 4273 3844 4274 3845 // Generate a move event for the item itself 4275 if (item && !hoverItems.isEmpty() && item == hoverItems.last()) { 3846 if (item 3847 && !hoverItems.isEmpty() 3848 && item == hoverItems.last()) { 4276 3849 sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent); 4277 3850 return true; … … 4290 3863 Q_Q(QGraphicsScene); 4291 3864 #ifndef QT_NO_TOOLTIP 4292 // Remove any tooltips 4293 QToolTip::showText(QPoint(), QString()); 3865 QToolTip::hideText(); 4294 3866 #endif 4295 3867 // Send HoverLeave events to all existing hover items, topmost first. … … 4308 3880 while (!hoverItems.isEmpty()) { 4309 3881 QGraphicsItem *lastItem = hoverItems.takeLast(); 4310 if (lastItem->acceptHoverEvents() 4311 || (lastItem->isWidget() && static_cast<QGraphicsWidget*>(lastItem)->d_func()->hasDecoration())) 3882 if (itemAcceptsHoverEvents_helper(lastItem)) 4312 3883 sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent); 4313 3884 } … … 4336 3907 // Send it; QGraphicsItem::keyPressEvent ignores it. If the event 4337 3908 // is filtered out, stop propagating it. 3909 if (p->isBlockedByModalPanel()) 3910 break; 4338 3911 if (!d->sendEvent(p, keyEvent)) 4339 3912 break; 4340 } while (!keyEvent->isAccepted() && !p->is Window() && (p = p->parentItem()));3913 } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem())); 4341 3914 } else { 4342 3915 keyEvent->ignore(); … … 4366 3939 // Send it; QGraphicsItem::keyPressEvent ignores it. If the event 4367 3940 // is filtered out, stop propagating it. 3941 if (p->isBlockedByModalPanel()) 3942 break; 4368 3943 if (!d->sendEvent(p, keyEvent)) 4369 3944 break; 4370 } while (!keyEvent->isAccepted() && !p->is Window() && (p = p->parentItem()));3945 } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem())); 4371 3946 } else { 4372 3947 keyEvent->ignore(); … … 4394 3969 { 4395 3970 Q_D(QGraphicsScene); 3971 if (d->mouseGrabberItems.isEmpty()) { 3972 // Dispatch hover events 3973 QGraphicsSceneHoverEvent hover; 3974 _q_hoverFromMouseEvent(&hover, mouseEvent); 3975 d->dispatchHoverEvent(&hover); 3976 } 3977 4396 3978 d->mousePressEventHandler(mouseEvent); 4397 3979 } … … 4511 4093 bool hasSetFocus = false; 4512 4094 foreach (QGraphicsItem *item, wheelCandidates) { 4513 if (!hasSetFocus && item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { 4095 if (!hasSetFocus && item->isEnabled() 4096 && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { 4514 4097 if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) { 4515 4098 hasSetFocus = true; … … 4522 4105 wheelEvent->widget())); 4523 4106 wheelEvent->accept(); 4524 bool is Window = item->isWindow();4107 bool isPanel = item->isPanel(); 4525 4108 d->sendEvent(item, wheelEvent); 4526 if (is Window|| wheelEvent->isAccepted())4109 if (isPanel || wheelEvent->isAccepted()) 4527 4110 break; 4528 4111 } … … 4534 4117 4535 4118 The default implementation forwards the event to the focusItem(). 4536 If no item currently has focus, this function does nothing. 4119 If no item currently has focus or the current focus item does not 4120 accept input methods, this function does nothing. 4537 4121 4538 4122 \sa QGraphicsItem::inputMethodEvent() … … 4541 4125 { 4542 4126 Q_D(QGraphicsScene); 4543 if (!d->focusItem) 4544 return; 4545 d->sendEvent(d->focusItem, event); 4127 if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) 4128 d->sendEvent(d->focusItem, event); 4546 4129 } 4547 4130 … … 4614 4197 const qreal oldPainterOpacity = painter->opacity(); 4615 4198 4616 if (qFuzzy Compare(windowOpacity + 1, qreal(1.0)))4199 if (qFuzzyIsNull(windowOpacity)) 4617 4200 return; 4618 4201 // Set new painter opacity. … … 4651 4234 4652 4235 // Don't use subpixmap if we get a full update. 4653 if (pixmapExposed.isEmpty() || (pixmapExposed. numRects() == 1 && br.contains(pix->rect()))) {4236 if (pixmapExposed.isEmpty() || (pixmapExposed.rectCount() == 1 && br.contains(pix->rect()))) { 4654 4237 pix->fill(Qt::transparent); 4655 4238 pixmapPainter.begin(pix); … … 4677 4260 // Blit the subpixmap into the main pixmap. 4678 4261 pixmapPainter.begin(pix); 4679 pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);4680 4262 pixmapPainter.setClipRegion(pixmapExposed); 4681 4263 pixmapPainter.drawPixmap(br.topLeft(), subPix); … … 4693 4275 bool painterStateProtection) 4694 4276 { 4695 QGraphicsItemPrivate *itemd = item->d_ptr ;4277 QGraphicsItemPrivate *itemd = item->d_ptr.data(); 4696 4278 QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode); 4697 4279 … … 4723 4305 4724 4306 // Fetch the off-screen transparent buffer and exposed area info. 4725 Q StringpixmapKey;4307 QPixmapCache::Key pixmapKey; 4726 4308 QPixmap pix; 4309 bool pixmapFound; 4727 4310 QGraphicsItemCache *itemCache = itemd->extraItemCache(); 4728 4311 if (cacheMode == QGraphicsItem::ItemCoordinateCache) { … … 4734 4317 pixmapKey = itemCache->key; 4735 4318 } else { 4736 if ((pixmapKey = itemCache->deviceData.value(widget).key).isEmpty()) { 4737 pixmapKey.sprintf("qgv-%p-%p", item, widget); 4738 QGraphicsItemCache::DeviceData data; 4739 data.key = pixmapKey; 4740 itemCache->deviceData.insert(widget, data); 4741 } 4319 pixmapKey = itemCache->deviceData.value(widget).key; 4742 4320 } 4743 4321 4744 4322 // Find pixmap in cache. 4745 if (!itemCache->allExposed) 4746 QPixmapCache::find(pixmapKey, pix); 4323 pixmapFound = QPixmapCache::find(pixmapKey, &pix); 4747 4324 4748 4325 // Render using item coordinate cache mode. … … 4769 4346 // Redraw any newly exposed areas. 4770 4347 if (itemCache->allExposed || !itemCache->exposed.isEmpty()) { 4348 4349 //We know that we will modify the pixmap, removing it from the cache 4350 //will detach the one we have and avoid a deep copy 4351 if (pixmapFound) 4352 QPixmapCache::remove(pixmapKey); 4353 4771 4354 // Fit the item's bounding rect into the pixmap's coordinates. 4772 4355 QTransform itemToPixmap; … … 4779 4362 // Generate the item's exposedRect and map its list of expose 4780 4363 // rects to device coordinates. 4781 QStyleOptionGraphicsItem cacheOption= *option;4364 styleOptionTmp = *option; 4782 4365 QRegion pixmapExposed; 4783 4366 QRectF exposedRect; … … 4791 4374 exposedRect = brect; 4792 4375 } 4793 cacheOption.exposedRect = exposedRect;4376 styleOptionTmp.exposedRect = exposedRect; 4794 4377 4795 4378 // Render. 4796 4379 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(), 4797 & cacheOption, painterStateProtection);4798 4799 // Reinsert this pixmap into the cache.4800 QPixmapCache::insert(pixmapKey,pix);4380 &styleOptionTmp, painterStateProtection); 4381 4382 // insert this pixmap into the cache. 4383 itemCache->key = QPixmapCache::insert(pix); 4801 4384 4802 4385 // Reset expose data. … … 4864 4447 #else 4865 4448 // Only if deviceRect is 20% taller or wider than the desktop. 4866 QRect desktopRect = qApp->desktop()->availableGeometry(widget); 4867 bool allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width() 4868 || desktopRect.height() * 1.2 < deviceRect.height()); 4449 bool allowPartialCacheExposure = false; 4450 if (widget) { 4451 QRect desktopRect = QApplication::desktop()->availableGeometry(widget); 4452 allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width() 4453 || desktopRect.height() * 1.2 < deviceRect.height()); 4454 } 4869 4455 #endif 4870 4456 QRegion scrollExposure; … … 4925 4511 // Check for newly invalidated areas. 4926 4512 if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) { 4513 //We know that we will modify the pixmap, removing it from the cache 4514 //will detach the one we have and avoid a deep copy 4515 if (pixmapFound) 4516 QPixmapCache::remove(pixmapKey); 4517 4927 4518 // Construct an item-to-pixmap transform. 4928 4519 QPointF p = deviceRect.topLeft(); … … 4951 4542 br |= pixmapToItem.mapRect(r); 4952 4543 } 4953 QStyleOptionGraphicsItem cacheOption= *option;4954 cacheOption.exposedRect = br.adjusted(-1, -1, 1, 1);4544 styleOptionTmp = *option; 4545 styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1); 4955 4546 4956 4547 // Render the exposed areas. 4957 4548 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(), 4958 & cacheOption, painterStateProtection);4549 &styleOptionTmp, painterStateProtection); 4959 4550 4960 4551 // Reset expose data. … … 4965 4556 4966 4557 if (pixModified) { 4967 // Reinsert this pixmap into the cache4968 QPixmapCache::insert(pixmapKey,pix);4558 // Insert this pixmap into the cache. 4559 deviceData->key = QPixmapCache::insert(pix); 4969 4560 } 4970 4561 … … 4985 4576 } 4986 4577 4578 void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform, 4579 QRegion *exposedRegion, QWidget *widget) 4580 { 4581 // Make sure we don't have unpolished items before we draw. 4582 if (!unpolishedItems.isEmpty()) 4583 _q_polishItems(); 4584 4585 QRectF exposedSceneRect; 4586 if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { 4587 exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); 4588 if (viewTransform) 4589 exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); 4590 } 4591 const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder); 4592 for (int i = 0; i < tli.size(); ++i) 4593 drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); 4594 } 4595 4596 void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, 4597 const QTransform *const viewTransform, 4598 QRegion *exposedRegion, QWidget *widget, 4599 qreal parentOpacity, const QTransform *const effectTransform) 4600 { 4601 Q_ASSERT(item); 4602 4603 if (!item->d_ptr->visible) 4604 return; 4605 4606 const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents); 4607 const bool itemHasChildren = !item->d_ptr->children.isEmpty(); 4608 if (!itemHasContents && !itemHasChildren) 4609 return; // Item has neither contents nor children!(?) 4610 4611 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); 4612 const bool itemIsFullyTransparent = (opacity < 0.0001); 4613 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) 4614 return; 4615 4616 QTransform transform(Qt::Uninitialized); 4617 QTransform *transformPtr = 0; 4618 bool translateOnlyTransform = false; 4619 #define ENSURE_TRANSFORM_PTR \ 4620 if (!transformPtr) { \ 4621 Q_ASSERT(!itemIsUntransformable); \ 4622 if (viewTransform) { \ 4623 transform = item->d_ptr->sceneTransform; \ 4624 transform *= *viewTransform; \ 4625 transformPtr = &transform; \ 4626 } else { \ 4627 transformPtr = &item->d_ptr->sceneTransform; \ 4628 translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \ 4629 } \ 4630 } 4631 4632 // Update the item's scene transform if the item is transformable; 4633 // otherwise calculate the full transform, 4634 bool wasDirtyParentSceneTransform = false; 4635 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); 4636 if (itemIsUntransformable) { 4637 transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform()); 4638 transformPtr = &transform; 4639 } else if (item->d_ptr->dirtySceneTransform) { 4640 item->d_ptr->updateSceneTransformFromParent(); 4641 Q_ASSERT(!item->d_ptr->dirtySceneTransform); 4642 wasDirtyParentSceneTransform = true; 4643 } 4644 4645 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); 4646 bool drawItem = itemHasContents && !itemIsFullyTransparent; 4647 if (drawItem) { 4648 const QRectF brect = adjustedItemEffectiveBoundingRect(item); 4649 ENSURE_TRANSFORM_PTR 4650 QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect() 4651 : transformPtr->mapRect(brect).toRect(); 4652 if (widget) 4653 item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); 4654 viewBoundingRect.adjust(-1, -1, 1, 1); 4655 drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty(); 4656 if (!drawItem) { 4657 if (!itemHasChildren) 4658 return; 4659 if (itemClipsChildrenToShape) { 4660 if (wasDirtyParentSceneTransform) 4661 item->d_ptr->invalidateChildrenSceneTransform(); 4662 return; 4663 } 4664 } 4665 } // else we know for sure this item has children we must process. 4666 4667 if (itemHasChildren && itemClipsChildrenToShape) 4668 ENSURE_TRANSFORM_PTR; 4669 4670 #ifndef QT_NO_GRAPHICSEFFECT 4671 if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { 4672 ENSURE_TRANSFORM_PTR; 4673 QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp, 4674 painter, opacity, wasDirtyParentSceneTransform, drawItem); 4675 QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; 4676 QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *> 4677 (source->d_func()); 4678 sourced->info = &info; 4679 const QTransform restoreTransform = painter->worldTransform(); 4680 if (effectTransform) 4681 painter->setWorldTransform(*transformPtr * *effectTransform); 4682 else 4683 painter->setWorldTransform(*transformPtr); 4684 painter->setOpacity(opacity); 4685 4686 if (sourced->currentCachedSystem() != Qt::LogicalCoordinates 4687 && sourced->lastEffectTransform != painter->worldTransform()) 4688 { 4689 sourced->lastEffectTransform = painter->worldTransform(); 4690 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged); 4691 } 4692 4693 item->d_ptr->graphicsEffect->draw(painter); 4694 painter->setWorldTransform(restoreTransform); 4695 sourced->info = 0; 4696 } else 4697 #endif //QT_NO_GRAPHICSEFFECT 4698 { 4699 draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, 4700 effectTransform, wasDirtyParentSceneTransform, drawItem); 4701 } 4702 } 4703 4704 void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, 4705 const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget, 4706 qreal opacity, const QTransform *effectTransform, 4707 bool wasDirtyParentSceneTransform, bool drawItem) 4708 { 4709 const bool itemIsFullyTransparent = (opacity < 0.0001); 4710 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); 4711 const bool itemHasChildren = !item->d_ptr->children.isEmpty(); 4712 4713 int i = 0; 4714 if (itemHasChildren) { 4715 item->d_ptr->ensureSortedChildren(); 4716 4717 if (itemClipsChildrenToShape) { 4718 painter->save(); 4719 Q_ASSERT(transformPtr); 4720 if (effectTransform) 4721 painter->setWorldTransform(*transformPtr * *effectTransform); 4722 else 4723 painter->setWorldTransform(*transformPtr); 4724 painter->setClipPath(item->shape(), Qt::IntersectClip); 4725 } 4726 4727 // Draw children behind 4728 for (i = 0; i < item->d_ptr->children.size(); ++i) { 4729 QGraphicsItem *child = item->d_ptr->children.at(i); 4730 if (wasDirtyParentSceneTransform) 4731 child->d_ptr->dirtySceneTransform = 1; 4732 if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) 4733 break; 4734 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) 4735 continue; 4736 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); 4737 } 4738 } 4739 4740 // Draw item 4741 if (drawItem) { 4742 Q_ASSERT(!itemIsFullyTransparent); 4743 Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)); 4744 Q_ASSERT(transformPtr); 4745 item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion 4746 ? *exposedRegion : QRegion(), exposedRegion == 0); 4747 4748 const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape; 4749 const bool savePainter = itemClipsToShape || painterStateProtection; 4750 if (savePainter) 4751 painter->save(); 4752 4753 if (!itemHasChildren || !itemClipsChildrenToShape) { 4754 if (effectTransform) 4755 painter->setWorldTransform(*transformPtr * *effectTransform); 4756 else 4757 painter->setWorldTransform(*transformPtr); 4758 } 4759 4760 if (itemClipsToShape) 4761 painter->setClipPath(item->shape(), Qt::IntersectClip); 4762 painter->setOpacity(opacity); 4763 4764 if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) 4765 item->paint(painter, &styleOptionTmp, widget); 4766 else 4767 drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); 4768 4769 if (savePainter) 4770 painter->restore(); 4771 } 4772 4773 // Draw children in front 4774 if (itemHasChildren) { 4775 for (; i < item->d_ptr->children.size(); ++i) { 4776 QGraphicsItem *child = item->d_ptr->children.at(i); 4777 if (wasDirtyParentSceneTransform) 4778 child->d_ptr->dirtySceneTransform = 1; 4779 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) 4780 continue; 4781 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); 4782 } 4783 } 4784 4785 // Restore child clip 4786 if (itemHasChildren && itemClipsChildrenToShape) 4787 painter->restore(); 4788 } 4789 4790 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, 4791 bool force, bool ignoreOpacity, bool removingItemFromScene) 4792 { 4793 Q_ASSERT(item); 4794 if (updateAll) 4795 return; 4796 4797 if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force, 4798 /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren, 4799 /*ignoreOpacity=*/ignoreOpacity)) { 4800 if (item->d_ptr->dirty) { 4801 // The item is already marked as dirty and will be processed later. However, 4802 // we have to make sure ignoreVisible and ignoreOpacity are set properly; 4803 // otherwise things like: item->update(); item->hide() (force is now true) 4804 // won't work as expected. 4805 if (force) 4806 item->d_ptr->ignoreVisible = 1; 4807 if (ignoreOpacity) 4808 item->d_ptr->ignoreOpacity = 1; 4809 } 4810 return; 4811 } 4812 4813 const bool fullItemUpdate = rect.isNull(); 4814 if (!fullItemUpdate && rect.isEmpty()) 4815 return; 4816 4817 if (!processDirtyItemsEmitted) { 4818 QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection); 4819 processDirtyItemsEmitted = true; 4820 } 4821 4822 if (removingItemFromScene) { 4823 // Note that this function can be called from the item's destructor, so 4824 // do NOT call any virtual functions on it within this block. 4825 if (isSignalConnected(changedSignalIndex) || views.isEmpty()) { 4826 // This block of code is kept for compatibility. Since 4.5, by default 4827 // QGraphicsView does not connect the signal and we use the below 4828 // method of delivering updates. 4829 q_func()->update(); 4830 return; 4831 } 4832 4833 for (int i = 0; i < views.size(); ++i) { 4834 QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func(); 4835 QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport); 4836 rect.translate(viewPrivate->dirtyScrollOffset); 4837 viewPrivate->updateRect(rect); 4838 } 4839 return; 4840 } 4841 4842 bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents 4843 && !item->d_ptr->graphicsEffect; 4844 if (!hasNoContents) { 4845 item->d_ptr->dirty = 1; 4846 if (fullItemUpdate) 4847 item->d_ptr->fullUpdatePending = 1; 4848 else if (!item->d_ptr->fullUpdatePending) 4849 item->d_ptr->needsRepaint |= rect; 4850 } 4851 4852 if (invalidateChildren) { 4853 item->d_ptr->allChildrenDirty = 1; 4854 item->d_ptr->dirtyChildren = 1; 4855 } 4856 4857 if (force) 4858 item->d_ptr->ignoreVisible = 1; 4859 if (ignoreOpacity) 4860 item->d_ptr->ignoreOpacity = 1; 4861 4862 QGraphicsItem *p = item->d_ptr->parent; 4863 while (p) { 4864 p->d_ptr->dirtyChildren = 1; 4865 #ifndef QT_NO_GRAPHICSEFFECT 4866 if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) { 4867 p->d_ptr->dirty = 1; 4868 p->d_ptr->fullUpdatePending = 1; 4869 } 4870 #endif //QT_NO_GRAPHICSEFFECT 4871 p = p->d_ptr->parent; 4872 } 4873 } 4874 4875 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, 4876 const QRectF &rect, bool itemIsUntransformable) 4877 { 4878 Q_ASSERT(view); 4879 Q_ASSERT(item); 4880 4881 QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr); 4882 QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr); 4883 4884 if (itemIsUntransformable) { 4885 const QTransform xform = itemq->deviceTransform(viewq->viewportTransform()); 4886 if (!item->hasBoundingRegionGranularity) 4887 return view->updateRect(xform.mapRect(rect).toRect()); 4888 return view->updateRegion(xform.map(QRegion(rect.toRect()))); 4889 } 4890 4891 if (item->sceneTransformTranslateOnly && view->identityMatrix) { 4892 const qreal dx = item->sceneTransform.dx(); 4893 const qreal dy = item->sceneTransform.dy(); 4894 if (!item->hasBoundingRegionGranularity) { 4895 QRectF r(rect); 4896 r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll()); 4897 return view->updateRect(r.toRect()); 4898 } 4899 QRegion r(rect.toRect()); 4900 r.translate(qRound(dx) - view->horizontalScroll(), qRound(dy) - view->verticalScroll()); 4901 return view->updateRegion(r); 4902 } 4903 4904 if (!viewq->isTransformed()) { 4905 if (!item->hasBoundingRegionGranularity) 4906 return view->updateRect(item->sceneTransform.mapRect(rect).toRect()); 4907 return view->updateRegion(item->sceneTransform.map(QRegion(rect.toRect()))); 4908 } 4909 4910 QTransform xform = item->sceneTransform; 4911 xform *= viewq->viewportTransform(); 4912 if (!item->hasBoundingRegionGranularity) 4913 return view->updateRect(xform.mapRect(rect).toRect()); 4914 return view->updateRegion(xform.map(QRegion(rect.toRect()))); 4915 } 4916 4917 void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, 4918 qreal parentOpacity) 4919 { 4920 Q_Q(QGraphicsScene); 4921 Q_ASSERT(item); 4922 Q_ASSERT(!updateAll); 4923 4924 if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) { 4925 resetDirtyItem(item); 4926 return; 4927 } 4928 4929 const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible; 4930 if (itemIsHidden) { 4931 resetDirtyItem(item, /*recursive=*/true); 4932 return; 4933 } 4934 4935 bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents); 4936 const bool itemHasChildren = !item->d_ptr->children.isEmpty(); 4937 if (!itemHasContents) { 4938 if (!itemHasChildren) { 4939 resetDirtyItem(item); 4940 return; // Item has neither contents nor children!(?) 4941 } 4942 if (item->d_ptr->graphicsEffect) 4943 itemHasContents = true; 4944 } 4945 4946 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); 4947 const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001; 4948 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) { 4949 resetDirtyItem(item, /*recursive=*/itemHasChildren); 4950 return; 4951 } 4952 4953 bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform; 4954 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); 4955 if (wasDirtyParentSceneTransform && !itemIsUntransformable) { 4956 item->d_ptr->updateSceneTransformFromParent(); 4957 Q_ASSERT(!item->d_ptr->dirtySceneTransform); 4958 } 4959 4960 const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; 4961 if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) { 4962 // Make sure we don't process invisible items or items with no content. 4963 item->d_ptr->dirty = 0; 4964 item->d_ptr->fullUpdatePending = 0; 4965 // Might have a dirty view bounding rect otherwise. 4966 if (itemIsFullyTransparent || !itemHasContents) 4967 item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; 4968 } 4969 4970 if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) { 4971 // Update growingItemsBoundingRect. 4972 if (item->d_ptr->sceneTransformTranslateOnly) { 4973 growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(), 4974 item->d_ptr->sceneTransform.dy()); 4975 } else { 4976 growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); 4977 } 4978 } 4979 4980 // Process item. 4981 if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) { 4982 const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex); 4983 const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item); 4984 4985 if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) { 4986 // This block of code is kept for compatibility. Since 4.5, by default 4987 // QGraphicsView does not connect the signal and we use the below 4988 // method of delivering updates. 4989 if (item->d_ptr->sceneTransformTranslateOnly) { 4990 q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(), 4991 item->d_ptr->sceneTransform.dy())); 4992 } else { 4993 q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect)); 4994 } 4995 } else { 4996 QRectF dirtyRect; 4997 bool uninitializedDirtyRect = true; 4998 4999 for (int j = 0; j < views.size(); ++j) { 5000 QGraphicsView *view = views.at(j); 5001 QGraphicsViewPrivate *viewPrivate = view->d_func(); 5002 QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; 5003 if (viewPrivate->fullUpdatePending 5004 || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) { 5005 // Okay, if we have a full update pending or no viewport update, this item's 5006 // paintedViewBoundingRect will be updated correctly in the next paintEvent if 5007 // it is inside the viewport, but for now we can pretend that it is outside. 5008 paintedViewBoundingRect = QRect(-1, -1, -1, -1); 5009 continue; 5010 } 5011 5012 if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { 5013 paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); 5014 if (!viewPrivate->updateRect(paintedViewBoundingRect)) 5015 paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. 5016 } 5017 5018 if (!item->d_ptr->dirty) 5019 continue; 5020 5021 if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint 5022 && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1 5023 && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) { 5024 continue; // Outside viewport. 5025 } 5026 5027 if (uninitializedDirtyRect) { 5028 dirtyRect = itemBoundingRect; 5029 if (!item->d_ptr->fullUpdatePending) { 5030 _q_adjustRect(&item->d_ptr->needsRepaint); 5031 dirtyRect &= item->d_ptr->needsRepaint; 5032 } 5033 uninitializedDirtyRect = false; 5034 } 5035 5036 if (dirtyRect.isEmpty()) 5037 continue; // Discard updates outside the bounding rect. 5038 5039 if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable) 5040 && item->d_ptr->paintedViewBoundingRectsNeedRepaint) { 5041 paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. 5042 } 5043 } 5044 } 5045 } 5046 5047 // Process children. 5048 if (itemHasChildren && item->d_ptr->dirtyChildren) { 5049 if (!dirtyAncestorContainsChildren) { 5050 dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending 5051 && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); 5052 } 5053 const bool allChildrenDirty = item->d_ptr->allChildrenDirty; 5054 const bool parentIgnoresVisible = item->d_ptr->ignoreVisible; 5055 const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity; 5056 for (int i = 0; i < item->d_ptr->children.size(); ++i) { 5057 QGraphicsItem *child = item->d_ptr->children.at(i); 5058 if (wasDirtyParentSceneTransform) 5059 child->d_ptr->dirtySceneTransform = 1; 5060 if (wasDirtyParentViewBoundingRects) 5061 child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1; 5062 if (parentIgnoresVisible) 5063 child->d_ptr->ignoreVisible = 1; 5064 if (parentIgnoresOpacity) 5065 child->d_ptr->ignoreOpacity = 1; 5066 if (allChildrenDirty) { 5067 child->d_ptr->dirty = 1; 5068 child->d_ptr->fullUpdatePending = 1; 5069 child->d_ptr->dirtyChildren = 1; 5070 child->d_ptr->allChildrenDirty = 1; 5071 } 5072 processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity); 5073 } 5074 } else if (wasDirtyParentSceneTransform) { 5075 item->d_ptr->invalidateChildrenSceneTransform(); 5076 } 5077 5078 resetDirtyItem(item); 5079 } 5080 4987 5081 /*! 4988 5082 Paints the given \a items using the provided \a painter, after the … … 4990 5084 drawn. All painting is done in \e scene coordinates. Before 4991 5085 drawing each item, the painter must be transformed using 4992 QGraphicsItem::scene Matrix().5086 QGraphicsItem::sceneTransform(). 4993 5087 4994 5088 The \a options parameter is the list of style option objects for … … 5008 5102 \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0 5009 5103 5104 \obsolete Since Qt 4.6, this function is not called anymore unless 5105 the QGraphicsView::IndirectPainting flag is given as an Optimization 5106 flag. 5107 5010 5108 \sa drawBackground(), drawForeground() 5011 5109 */ … … 5016 5114 { 5017 5115 Q_D(QGraphicsScene); 5018 5019 // Detect if painter state protection is disabled. 5116 // Make sure we don't have unpolished items before we draw. 5117 if (!d->unpolishedItems.isEmpty()) 5118 d->_q_polishItems(); 5119 5020 5120 QTransform viewTransform = painter->worldTransform(); 5021 QVarLengthArray<QGraphicsItem *, 16> childClippers; 5022 5121 Q_UNUSED(options); 5122 5123 // Determine view, expose and flags. 5124 QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0; 5125 QRegion *expose = 0; 5126 if (view) 5127 expose = &view->d_func()->exposedRegion; 5128 5129 // Find all toplevels, they are already sorted. 5130 QList<QGraphicsItem *> topLevelItems; 5023 5131 for (int i = 0; i < numItems; ++i) { 5024 QGraphicsItem *item = items[i]; 5025 if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { 5026 if (!childClippers.isEmpty()) { 5027 // Item is not clipped to any ancestor: pop all current clippers. 5028 for (int i = 0; i < childClippers.size(); ++i) 5029 painter->restore(); 5030 childClippers.clear(); 5031 } 5032 } else { 5033 // Item is clipped to an ancestor, which may or may not be in our 5034 // child clipper list. Let's start by finding the item's closest 5035 // clipping ancestor. 5036 QGraphicsItem *clipParent = item->parentItem(); 5037 while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) 5038 clipParent = clipParent->parentItem(); 5039 5040 // Pop any in-between clippers. If the clipper is unknown, pop 5041 // them all. ### QVarLengthArray::lastIndexOf(). 5042 int index = -1; 5043 for (int n = childClippers.size() - 1; n >= 0; --n) { 5044 if (childClippers[n] == clipParent) { 5045 index = n; 5046 break; 5047 } 5048 } 5049 if (index != -1) { 5050 int toPop = childClippers.size() - index - 1; 5051 if (toPop > 0) { 5052 for (int i = 0; i < toPop; ++i) 5053 painter->restore(); 5054 childClippers.resize(index + 1); 5055 } 5056 } 5057 5058 // Sanity check 5059 if (!childClippers.isEmpty()) 5060 Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent); 5061 5062 // If the clipper list is empty at this point, but we're still 5063 // clipped to an ancestor, then we need to build the clip chain 5064 // ourselves. There is only one case that can produce this issue: 5065 // This item is stacked behind an ancestor: 5066 // ItemStacksBehindParent. 5067 if (childClippers.isEmpty()) { 5068 Q_ASSERT(clipParent != 0); 5069 // Build a stack of clippers. 5070 QVarLengthArray<QGraphicsItem *, 16> clippers; 5071 QGraphicsItem *p = clipParent; 5072 do { 5073 if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) 5074 clippers.append(p); 5075 } while ((p = p->parentItem()) && (p->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)); 5076 5077 // ### This code path can also use the itemTransform 5078 // optimization, but it's hit very rarely. 5079 for (int i = clippers.size() - 1; i >= 0; --i) { 5080 QGraphicsItem *clipper = clippers[i]; 5081 if (clipper->d_ptr->itemIsUntransformable()) { 5082 painter->setWorldTransform(clipper->deviceTransform(viewTransform), false); 5083 } else { 5084 painter->setWorldTransform(clipper->sceneTransform() * viewTransform, false); 5085 } 5086 5087 childClippers.append(clipper); 5088 painter->save(); 5089 painter->setClipPath(clipper->shape(), Qt::IntersectClip); 5090 } 5091 Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent); 5092 } 5093 } 5094 5095 // Set up the painter transform 5096 if (item->d_ptr->itemIsUntransformable()) { 5097 painter->setWorldTransform(item->deviceTransform(viewTransform), false); 5098 } else { 5099 painter->setWorldTransform(item->sceneTransform() * viewTransform, false); 5100 } 5101 5102 // Save painter 5103 bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape)); 5104 if (saveState) 5105 painter->save(); 5106 5107 // Set local clip 5108 if (item->flags() & QGraphicsItem::ItemClipsToShape) 5109 painter->setClipPath(item->shape(), Qt::IntersectClip); 5110 5111 // Setup opacity 5112 painter->setOpacity(item->effectiveOpacity()); 5113 5114 // Draw the item 5115 d->drawItemHelper(item, painter, &options[i], widget, d->painterStateProtection); 5116 5117 if (saveState) 5118 painter->restore(); 5119 5120 if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape) { 5121 // Clip descendents to this item's shape, and keep the painter 5122 // saved. 5123 childClippers.append(item); 5124 painter->save(); 5125 painter->setClipPath(item->shape(), Qt::IntersectClip); 5126 } 5127 } 5128 5129 for (int i = 0; i < childClippers.size(); ++i) 5130 painter->restore(); 5132 QGraphicsItem *item = items[i]->topLevelItem(); 5133 if (!item->d_ptr->itemDiscovered) { 5134 topLevelItems << item; 5135 item->d_ptr->itemDiscovered = 1; 5136 d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget); 5137 } 5138 } 5139 5140 // Reset discovery bits. 5141 for (int i = 0; i < topLevelItems.size(); ++i) 5142 topLevelItems.at(i)->d_ptr->itemDiscovered = 0; 5131 5143 5132 5144 painter->setWorldTransform(viewTransform); … … 5185 5197 && widget->isEnabled() && widget->isVisibleTo(0) 5186 5198 && (widget->focusPolicy() & Qt::TabFocus) 5187 && (!item || !item->is Window() || item->isAncestorOf(widget))5199 && (!item || !item->isPanel() || item->isAncestorOf(widget)) 5188 5200 ) { 5189 5201 setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason); … … 5240 5252 5241 5253 /*! 5242 \internal5243 5244 This private function is called by QGraphicsItem, which is a friend of5245 QGraphicsScene. It is used by QGraphicsScene to record the rectangles that5246 need updating. It also launches a single-shot timer to ensure that5247 updated() will be emitted later.5248 5249 The \a item parameter is the item that changed, and \a rect is the5250 area of the item that changed given in item coordinates.5251 */5252 void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)5253 {5254 Q_D(QGraphicsScene);5255 // Deliver the actual update.5256 if (!d->updateAll) {5257 if (d->views.isEmpty() || ((d->connectedSignals & d->changedSignalMask) && !item->d_ptr->itemIsUntransformable()5258 && qFuzzyCompare(item->boundingRegionGranularity(), qreal(0.0)))) {5259 // This block of code is kept for compatibility. Since 4.5, by default5260 // QGraphicsView does not connect the signal and we use the below5261 // method of delivering updates.5262 update(item->sceneBoundingRect());5263 } else {5264 // ### Remove _q_adjustedRects().5265 QRectF boundingRect(adjustedItemBoundingRect(item));5266 if (!rect.isNull()) {5267 QRectF adjustedRect(rect);5268 _q_adjustRect(&adjustedRect);5269 boundingRect &= adjustedRect;5270 }5271 5272 // Update each view directly.5273 for (int i = 0; i < d->views.size(); ++i)5274 d->views.at(i)->d_func()->itemUpdated(item, boundingRect);5275 }5276 }5277 if (item->d_ptr->dirty) {5278 d->dirtyItems << item;5279 d->resetDirtyItemsLater();5280 }5281 5282 if (!item->isVisible())5283 return; // Hiding an item won't effect the largestUntransformableItem/sceneRect.5284 5285 // Update d->largestUntransformableItem by mapping this item's bounding5286 // rect back to the topmost untransformable item's untransformed5287 // coordinate system (which sort of equals the 1:1 coordinate system of an5288 // untransformed view).5289 if (item->d_ptr->itemIsUntransformable()) {5290 QGraphicsItem *parent = item;5291 while (parent && (parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations))5292 parent = parent->parentItem();5293 d->largestUntransformableItem |= item->mapToItem(parent, item->boundingRect()).boundingRect();5294 }5295 5296 // Only track the automatically growing scene rect if the scene has no5297 // defined scene rect.5298 if (!d->hasSceneRect) {5299 QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect;5300 QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect());5301 _q_adjustRect(&adjustedItemSceneBoundingRect);5302 d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect;5303 if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect)5304 emit sceneRectChanged(d->growingItemsBoundingRect);5305 }5306 }5307 5308 /*!5309 5254 \since 4.4 5310 5255 … … 5318 5263 Q_D(const QGraphicsScene); 5319 5264 // ### This function, and the use of styles in general, is non-reentrant. 5320 return d->style ? d->style : qApp->style();5265 return d->style ? d->style : QApplication::style(); 5321 5266 } 5322 5267 … … 5395 5340 { 5396 5341 Q_D(QGraphicsScene); 5397 QFont naturalFont = qApp->font();5342 QFont naturalFont = QApplication::font(); 5398 5343 naturalFont.resolve(0); 5399 5344 QFont resolvedFont = font.resolve(naturalFont); … … 5432 5377 { 5433 5378 Q_D(QGraphicsScene); 5434 QPalette naturalPalette = qApp->palette();5379 QPalette naturalPalette = QApplication::palette(); 5435 5380 naturalPalette.resolve(0); 5436 5381 QPalette resolvedPalette = palette.resolve(naturalPalette); … … 5439 5384 5440 5385 /*! 5386 \since 4.6 5387 5388 Returns true if the scene is active (e.g., it's viewed by 5389 at least one QGraphicsView that is active); otherwise returns false. 5390 5391 \sa QGraphicsItem::isActive(), QWidget::isActiveWindow() 5392 */ 5393 bool QGraphicsScene::isActive() const 5394 { 5395 Q_D(const QGraphicsScene); 5396 return d->activationRefCount > 0; 5397 } 5398 5399 /*! 5400 \since 4.6 5401 Returns the current active panel, or 0 if no panel is currently active. 5402 5403 \sa QGraphicsScene::setActivePanel() 5404 */ 5405 QGraphicsItem *QGraphicsScene::activePanel() const 5406 { 5407 Q_D(const QGraphicsScene); 5408 return d->activePanel; 5409 } 5410 5411 /*! 5412 \since 4.6 5413 Activates \a item, which must be an item in this scene. You 5414 can also pass 0 for \a item, in which case QGraphicsScene will 5415 deactivate any currently active panel. 5416 5417 If the scene is currently inactive, \a item remains inactive until the 5418 scene becomes active (or, ir \a item is 0, no item will be activated). 5419 5420 \sa activePanel(), isActive(), QGraphicsItem::isActive() 5421 */ 5422 void QGraphicsScene::setActivePanel(QGraphicsItem *item) 5423 { 5424 Q_D(QGraphicsScene); 5425 d->setActivePanelHelper(item, false); 5426 } 5427 5428 /*! 5441 5429 \since 4.4 5442 5430 5443 Returns the current active window, or 0 if there isno window is currently5431 Returns the current active window, or 0 if no window is currently 5444 5432 active. 5445 5433 … … 5449 5437 { 5450 5438 Q_D(const QGraphicsScene); 5451 return d->activeWindow; 5439 if (d->activePanel && d->activePanel->isWindow()) 5440 return static_cast<QGraphicsWidget *>(d->activePanel); 5441 return 0; 5452 5442 } 5453 5443 … … 5462 5452 void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) 5463 5453 { 5464 Q_D(QGraphicsScene);5465 5454 if (widget && widget->scene() != this) { 5466 5455 qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene", … … 5469 5458 } 5470 5459 5471 // Activate the widget's window. 5472 QGraphicsWidget *window = widget ? widget->window() : 0; 5473 if (window == d->activeWindow) 5474 return; 5475 5476 // Deactivate the last active window. 5477 if (d->activeWindow) { 5478 if (QGraphicsWidget *fw = d->activeWindow->focusWidget()) { 5479 // Remove focus from the current focus item. 5480 if (fw == focusItem()) 5481 setFocusItem(0, Qt::ActiveWindowFocusReason); 5482 } 5483 5484 QEvent event(QEvent::WindowDeactivate); 5485 QApplication::sendEvent(d->activeWindow, &event); 5486 } 5487 5488 // Update activate state. 5489 d->activeWindow = window; 5490 QEvent event(QEvent::ActivationChange); 5491 QApplication::sendEvent(this, &event); 5492 5493 // Activate 5494 if (window) { 5495 QEvent event(QEvent::WindowActivate); 5496 QApplication::sendEvent(window, &event); 5497 5460 // Activate the widget's panel (all windows are panels). 5461 QGraphicsItem *panel = widget ? widget->panel() : 0; 5462 setActivePanel(panel); 5463 5464 // Raise 5465 if (panel) { 5498 5466 QList<QGraphicsItem *> siblingWindows; 5499 QGraphicsItem *parent = window->parentItem();5467 QGraphicsItem *parent = panel->parentItem(); 5500 5468 // Raise ### inefficient for toplevels 5501 5469 foreach (QGraphicsItem *sibling, parent ? parent->children() : items()) { 5502 if (sibling != window && sibling->isWidget() 5503 && static_cast<QGraphicsWidget *>(sibling)->isWindow()) { 5470 if (sibling != panel && sibling->isWindow()) 5504 5471 siblingWindows << sibling; 5505 }5506 5472 } 5507 5473 5508 5474 // Find the highest z value. 5509 qreal z = window->zValue();5475 qreal z = panel->zValue(); 5510 5476 for (int i = 0; i < siblingWindows.size(); ++i) 5511 5477 z = qMax(z, siblingWindows.at(i)->zValue()); … … 5513 5479 // This will probably never overflow. 5514 5480 const qreal litt = qreal(0.001); 5515 window->setZValue(z + litt); 5516 5517 if (QGraphicsWidget *focusChild = window->focusWidget()) 5518 focusChild->setFocus(Qt::ActiveWindowFocusReason); 5481 panel->setZValue(z + litt); 5482 } 5483 } 5484 5485 /*! 5486 \since 4.6 5487 5488 Sends event \a event to item \a item through possible event filters. 5489 5490 The event is sent only if the item is enabled. 5491 5492 Returns \c false if the event was filtered or if the item is disabled. 5493 Otherwise returns the value that was returned from the event handler. 5494 5495 \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter() 5496 */ 5497 bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event) 5498 { 5499 Q_D(QGraphicsScene); 5500 if (!item) { 5501 qWarning("QGraphicsScene::sendEvent: cannot send event to a null item"); 5502 return false; 5503 } 5504 if (item->scene() != this) { 5505 qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)" 5506 " is different from this scene (%p)", 5507 item, item->scene(), this); 5508 return false; 5509 } 5510 return d->sendEvent(item, event); 5511 } 5512 5513 void QGraphicsScenePrivate::addView(QGraphicsView *view) 5514 { 5515 views << view; 5516 } 5517 5518 void QGraphicsScenePrivate::removeView(QGraphicsView *view) 5519 { 5520 views.removeAll(view); 5521 } 5522 5523 void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent) 5524 { 5525 QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints(); 5526 for (int i = 0; i < touchPoints.count(); ++i) { 5527 QTouchEvent::TouchPoint &touchPoint = touchPoints[i]; 5528 touchPoint.setRect(item->mapFromScene(touchPoint.sceneRect()).boundingRect()); 5529 touchPoint.setStartPos(item->d_ptr->genericMapFromScene(touchPoint.startScenePos(), touchEvent->widget())); 5530 touchPoint.setLastPos(item->d_ptr->genericMapFromScene(touchPoint.lastScenePos(), touchEvent->widget())); 5531 } 5532 touchEvent->setTouchPoints(touchPoints); 5533 } 5534 5535 int QGraphicsScenePrivate::findClosestTouchPointId(const QPointF &scenePos) 5536 { 5537 int closestTouchPointId = -1; 5538 qreal closestDistance = qreal(0.); 5539 foreach (const QTouchEvent::TouchPoint &touchPoint, sceneCurrentTouchPoints) { 5540 qreal distance = QLineF(scenePos, touchPoint.scenePos()).length(); 5541 if (closestTouchPointId == -1|| distance < closestDistance) { 5542 closestTouchPointId = touchPoint.id(); 5543 closestDistance = distance; 5544 } 5545 } 5546 return closestTouchPointId; 5547 } 5548 5549 void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent) 5550 { 5551 typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints; 5552 QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents; 5553 5554 for (int i = 0; i < sceneTouchEvent->touchPoints().count(); ++i) { 5555 const QTouchEvent::TouchPoint &touchPoint = sceneTouchEvent->touchPoints().at(i); 5556 5557 // update state 5558 QGraphicsItem *item = 0; 5559 if (touchPoint.state() == Qt::TouchPointPressed) { 5560 if (sceneTouchEvent->deviceType() == QTouchEvent::TouchPad) { 5561 // on touch-pad devices, send all touch points to the same item 5562 item = itemForTouchPointId.isEmpty() 5563 ? 0 5564 : itemForTouchPointId.constBegin().value(); 5565 } 5566 5567 if (!item) { 5568 // determine which item this touch point will go to 5569 cachedItemsUnderMouse = itemsAtPosition(touchPoint.screenPos().toPoint(), 5570 touchPoint.scenePos(), 5571 sceneTouchEvent->widget()); 5572 item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.first(); 5573 } 5574 5575 if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) { 5576 // on touch-screens, combine this touch point with the closest one we find if it 5577 // is a a direct descendent or ancestor ( 5578 int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos()); 5579 QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId); 5580 if (!item 5581 || (closestItem 5582 && (item->isAncestorOf(closestItem) 5583 || closestItem->isAncestorOf(item)))) { 5584 item = closestItem; 5585 } 5586 } 5587 if (!item) 5588 continue; 5589 5590 itemForTouchPointId.insert(touchPoint.id(), item); 5591 sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint); 5592 } else if (touchPoint.state() == Qt::TouchPointReleased) { 5593 item = itemForTouchPointId.take(touchPoint.id()); 5594 if (!item) 5595 continue; 5596 5597 sceneCurrentTouchPoints.remove(touchPoint.id()); 5598 } else { 5599 item = itemForTouchPointId.value(touchPoint.id()); 5600 if (!item) 5601 continue; 5602 Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id())); 5603 sceneCurrentTouchPoints[touchPoint.id()] = touchPoint; 5604 } 5605 5606 StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item]; 5607 statesAndTouchPoints.first |= touchPoint.state(); 5608 statesAndTouchPoints.second.append(touchPoint); 5609 } 5610 5611 if (itemsNeedingEvents.isEmpty()) { 5612 sceneTouchEvent->accept(); 5613 return; 5614 } 5615 5616 bool ignoreSceneTouchEvent = true; 5617 QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin(); 5618 const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd(); 5619 for (; it != end; ++it) { 5620 QGraphicsItem *item = it.key(); 5621 5622 (void) item->isBlockedByModalPanel(&item); 5623 5624 // determine event type from the state mask 5625 QEvent::Type eventType; 5626 switch (it.value().first) { 5627 case Qt::TouchPointPressed: 5628 // all touch points have pressed state 5629 eventType = QEvent::TouchBegin; 5630 break; 5631 case Qt::TouchPointReleased: 5632 // all touch points have released state 5633 eventType = QEvent::TouchEnd; 5634 break; 5635 case Qt::TouchPointStationary: 5636 // don't send the event if nothing changed 5637 continue; 5638 default: 5639 // all other combinations 5640 eventType = QEvent::TouchUpdate; 5641 break; 5642 } 5643 5644 QTouchEvent touchEvent(eventType); 5645 touchEvent.setWidget(sceneTouchEvent->widget()); 5646 touchEvent.setDeviceType(sceneTouchEvent->deviceType()); 5647 touchEvent.setModifiers(sceneTouchEvent->modifiers()); 5648 touchEvent.setTouchPointStates(it.value().first); 5649 touchEvent.setTouchPoints(it.value().second); 5650 5651 switch (touchEvent.type()) { 5652 case QEvent::TouchBegin: 5653 { 5654 // if the TouchBegin handler recurses, we assume that means the event 5655 // has been implicitly accepted and continue to send touch events 5656 item->d_ptr->acceptedTouchBeginEvent = true; 5657 bool res = sendTouchBeginEvent(item, &touchEvent) 5658 && touchEvent.isAccepted(); 5659 if (!res) 5660 ignoreSceneTouchEvent = false; 5661 break; 5662 } 5663 default: 5664 if (item->d_ptr->acceptedTouchBeginEvent) { 5665 updateTouchPointsForItem(item, &touchEvent); 5666 (void) sendEvent(item, &touchEvent); 5667 ignoreSceneTouchEvent = false; 5668 } 5669 break; 5670 } 5671 } 5672 sceneTouchEvent->setAccepted(ignoreSceneTouchEvent); 5673 } 5674 5675 bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent) 5676 { 5677 Q_Q(QGraphicsScene); 5678 5679 if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.first() != origin) { 5680 const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first(); 5681 cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(), 5682 firstTouchPoint.scenePos(), 5683 touchEvent->widget()); 5684 } 5685 Q_ASSERT(cachedItemsUnderMouse.first() == origin); 5686 5687 // Set focus on the topmost enabled item that can take focus. 5688 bool setFocus = false; 5689 foreach (QGraphicsItem *item, cachedItemsUnderMouse) { 5690 if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { 5691 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { 5692 setFocus = true; 5693 if (item != q->focusItem()) 5694 q->setFocusItem(item, Qt::MouseFocusReason); 5695 break; 5696 } 5697 } 5698 if (item->isPanel()) 5699 break; 5700 } 5701 5702 // If nobody could take focus, clear it. 5703 if (!stickyFocus && !setFocus) 5704 q->setFocusItem(0, Qt::MouseFocusReason); 5705 5706 bool res = false; 5707 bool eventAccepted = touchEvent->isAccepted(); 5708 foreach (QGraphicsItem *item, cachedItemsUnderMouse) { 5709 // first, try to deliver the touch event 5710 updateTouchPointsForItem(item, touchEvent); 5711 bool acceptTouchEvents = item->acceptTouchEvents(); 5712 touchEvent->setAccepted(acceptTouchEvents); 5713 res = acceptTouchEvents && sendEvent(item, touchEvent); 5714 eventAccepted = touchEvent->isAccepted(); 5715 if (itemForTouchPointId.value(touchEvent->touchPoints().first().id()) == 0) { 5716 // item was deleted 5717 item = 0; 5718 } else { 5719 item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted); 5720 } 5721 touchEvent->spont = false; 5722 if (res && eventAccepted) { 5723 // the first item to accept the TouchBegin gets an implicit grab. 5724 for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { 5725 const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); 5726 itemForTouchPointId[touchPoint.id()] = item; // can be zero 5727 } 5728 break; 5729 } 5730 if (item && item->isPanel()) 5731 break; 5732 } 5733 5734 touchEvent->setAccepted(eventAccepted); 5735 return res; 5736 } 5737 5738 void QGraphicsScenePrivate::enableTouchEventsOnViews() 5739 { 5740 foreach (QGraphicsView *view, views) 5741 view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true); 5742 } 5743 5744 void QGraphicsScenePrivate::updateInputMethodSensitivityInViews() 5745 { 5746 for (int i = 0; i < views.size(); ++i) 5747 views.at(i)->d_func()->updateInputMethodSensitivity(); 5748 } 5749 5750 void QGraphicsScenePrivate::enterModal(QGraphicsItem *panel, QGraphicsItem::PanelModality previousModality) 5751 { 5752 Q_Q(QGraphicsScene); 5753 Q_ASSERT(panel && panel->isPanel()); 5754 5755 QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality; 5756 if (previousModality != QGraphicsItem::NonModal) { 5757 // the panel is changing from one modality type to another... temporarily set it back so 5758 // that blockedPanels is populated correctly 5759 panel->d_ptr->panelModality = previousModality; 5760 } 5761 5762 QSet<QGraphicsItem *> blockedPanels; 5763 QList<QGraphicsItem *> items = q->items(); // ### store panels separately 5764 for (int i = 0; i < items.count(); ++i) { 5765 QGraphicsItem *item = items.at(i); 5766 if (item->isPanel() && item->isBlockedByModalPanel()) 5767 blockedPanels.insert(item); 5768 } 5769 // blockedPanels contains all currently blocked panels 5770 5771 if (previousModality != QGraphicsItem::NonModal) { 5772 // reset the modality to the proper value, since we changed it above 5773 panel->d_ptr->panelModality = panelModality; 5774 // remove this panel so that it will be reinserted at the front of the stack 5775 modalPanels.removeAll(panel); 5776 } 5777 5778 modalPanels.prepend(panel); 5779 5780 if (!hoverItems.isEmpty()) { 5781 // send GraphicsSceneHoverLeave events to newly blocked hoverItems 5782 QGraphicsSceneHoverEvent hoverEvent; 5783 hoverEvent.setScenePos(lastSceneMousePos); 5784 dispatchHoverEvent(&hoverEvent); 5785 } 5786 5787 if (!mouseGrabberItems.isEmpty() && lastMouseGrabberItemHasImplicitMouseGrab) { 5788 QGraphicsItem *item = mouseGrabberItems.last(); 5789 if (item->isBlockedByModalPanel()) 5790 ungrabMouse(item, /*itemIsDying =*/ false); 5791 } 5792 5793 QEvent windowBlockedEvent(QEvent::WindowBlocked); 5794 QEvent windowUnblockedEvent(QEvent::WindowUnblocked); 5795 for (int i = 0; i < items.count(); ++i) { 5796 QGraphicsItem *item = items.at(i); 5797 if (item->isPanel()) { 5798 if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) { 5799 // send QEvent::WindowBlocked to newly blocked panels 5800 sendEvent(item, &windowBlockedEvent); 5801 } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) { 5802 // send QEvent::WindowUnblocked to unblocked panels when downgrading 5803 // a panel from SceneModal to PanelModal 5804 sendEvent(item, &windowUnblockedEvent); 5805 } 5806 } 5807 } 5808 } 5809 5810 void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel) 5811 { 5812 Q_Q(QGraphicsScene); 5813 Q_ASSERT(panel && panel->isPanel()); 5814 5815 QSet<QGraphicsItem *> blockedPanels; 5816 QList<QGraphicsItem *> items = q->items(); // ### same as above 5817 for (int i = 0; i < items.count(); ++i) { 5818 QGraphicsItem *item = items.at(i); 5819 if (item->isPanel() && item->isBlockedByModalPanel()) 5820 blockedPanels.insert(item); 5821 } 5822 5823 modalPanels.removeAll(panel); 5824 5825 QEvent e(QEvent::WindowUnblocked); 5826 for (int i = 0; i < items.count(); ++i) { 5827 QGraphicsItem *item = items.at(i); 5828 if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel()) 5829 sendEvent(item, &e); 5830 } 5831 5832 // send GraphicsSceneHoverEnter events to newly unblocked items 5833 QGraphicsSceneHoverEvent hoverEvent; 5834 hoverEvent.setScenePos(lastSceneMousePos); 5835 dispatchHoverEvent(&hoverEvent); 5836 } 5837 5838 void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures, 5839 QWidget *viewport, 5840 QMap<Qt::GestureType, QGesture *> *conflictedGestures, 5841 QList<QList<QGraphicsObject *> > *conflictedItems, 5842 QHash<QGesture *, QGraphicsObject *> *normalGestures) 5843 { 5844 foreach (QGesture *gesture, gestures) { 5845 Qt::GestureType gestureType = gesture->gestureType(); 5846 if (gesture->hasHotSpot()) { 5847 QPoint screenPos = gesture->hotSpot().toPoint(); 5848 QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport); 5849 QList<QGraphicsObject *> result; 5850 for (int j = 0; j < items.size(); ++j) { 5851 QGraphicsObject *item = items.at(j)->toGraphicsObject(); 5852 if (!item) 5853 continue; 5854 QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); 5855 if (d->gestureContext.contains(gestureType)) { 5856 result.append(item); 5857 } 5858 } 5859 DEBUG() << "QGraphicsScenePrivate::getGestureTargets:" 5860 << gesture << result; 5861 if (result.size() == 1) { 5862 normalGestures->insert(gesture, result.first()); 5863 } else if (!result.isEmpty()) { 5864 conflictedGestures->insert(gestureType, gesture); 5865 conflictedItems->append(result); 5866 } 5867 } 5868 } 5869 } 5870 5871 void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) 5872 { 5873 QWidget *viewport = event->widget(); 5874 if (!viewport) 5875 return; 5876 QList<QGesture *> allGestures = event->gestures(); 5877 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 5878 << "Delivering gestures:" << allGestures; 5879 5880 typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem; 5881 GesturesPerItem gesturesPerItem; 5882 5883 QSet<QGesture *> startedGestures; 5884 foreach (QGesture *gesture, allGestures) { 5885 QGraphicsObject *target = gestureTargets.value(gesture, 0); 5886 if (!target) { 5887 // when we are not in started mode but don't have a target 5888 // then the only one interested in gesture is the view/scene 5889 if (gesture->state() == Qt::GestureStarted) 5890 startedGestures.insert(gesture); 5891 } else { 5892 gesturesPerItem[target].append(gesture); 5893 } 5894 } 5895 5896 QMap<Qt::GestureType, QGesture *> conflictedGestures; 5897 QList<QList<QGraphicsObject *> > conflictedItems; 5898 QHash<QGesture *, QGraphicsObject *> normalGestures; 5899 getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems, 5900 &normalGestures); 5901 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 5902 << "Conflicting gestures:" << conflictedGestures.values() << conflictedItems; 5903 Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) || 5904 (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty())); 5905 5906 // gestures that were sent as override events, but no one accepted them 5907 QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures; 5908 5909 // deliver conflicted gestures as override events first 5910 while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) { 5911 // get the topmost item to deliver the override event 5912 Q_ASSERT(!conflictedItems.isEmpty()); 5913 Q_ASSERT(!conflictedItems.first().isEmpty()); 5914 QGraphicsObject *topmost = conflictedItems.first().first(); 5915 for (int i = 1; i < conflictedItems.size(); ++i) { 5916 QGraphicsObject *item = conflictedItems.at(i).first(); 5917 if (qt_closestItemFirst(item, topmost)) { 5918 topmost = item; 5919 } 5920 } 5921 // get a list of gestures to send to the item 5922 QList<Qt::GestureType> grabbedGestures = 5923 topmost->QGraphicsItem::d_func()->gestureContext.keys(); 5924 QList<QGesture *> gestures; 5925 for (int i = 0; i < grabbedGestures.size(); ++i) { 5926 if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) { 5927 gestures.append(g); 5928 if (!ignoredConflictedGestures.contains(g)) 5929 ignoredConflictedGestures.insert(g, topmost); 5930 } 5931 } 5932 5933 // send gesture override to the topmost item 5934 QGestureEvent ev(gestures); 5935 ev.t = QEvent::GestureOverride; 5936 ev.setWidget(event->widget()); 5937 // mark event and individual gestures as ignored 5938 ev.ignore(); 5939 foreach(QGesture *g, gestures) 5940 ev.setAccepted(g, false); 5941 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 5942 << "delivering override to" 5943 << topmost << gestures; 5944 sendEvent(topmost, &ev); 5945 // mark all accepted gestures to deliver them as normal gesture events 5946 foreach (QGesture *g, gestures) { 5947 if (ev.isAccepted() || ev.isAccepted(g)) { 5948 conflictedGestures.remove(g->gestureType()); 5949 gestureTargets.remove(g); 5950 // add the gesture to the list of normal delivered gestures 5951 normalGestures.insert(g, topmost); 5952 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 5953 << "override was accepted:" 5954 << g << topmost; 5955 ignoredConflictedGestures.remove(g); 5956 } 5957 } 5958 // remove the item that we've already delivered from the list 5959 for (int i = 0; i < conflictedItems.size(); ) { 5960 QList<QGraphicsObject *> &items = conflictedItems[i]; 5961 if (items.first() == topmost) { 5962 items.removeFirst(); 5963 if (items.isEmpty()) { 5964 conflictedItems.removeAt(i); 5965 continue; 5966 } 5967 } 5968 ++i; 5969 } 5970 } 5971 5972 // put back those started gestures that are not in the conflicted state 5973 // and remember their targets 5974 QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(), 5975 e = normalGestures.end(); 5976 for (; it != e; ++it) { 5977 QGesture *g = it.key(); 5978 QGraphicsObject *receiver = it.value(); 5979 Q_ASSERT(!gestureTargets.contains(g)); 5980 gestureTargets.insert(g, receiver); 5981 gesturesPerItem[receiver].append(g); 5982 } 5983 it = ignoredConflictedGestures.begin(); 5984 e = ignoredConflictedGestures.end(); 5985 for (; it != e; ++it) { 5986 QGesture *g = it.key(); 5987 QGraphicsObject *receiver = it.value(); 5988 Q_ASSERT(!gestureTargets.contains(g)); 5989 gestureTargets.insert(g, receiver); 5990 gesturesPerItem[receiver].append(g); 5991 } 5992 5993 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 5994 << "Started gestures:" << normalGestures.keys() 5995 << "All gestures:" << gesturesPerItem.values(); 5996 5997 // deliver all events 5998 QList<QGesture *> alreadyIgnoredGestures; 5999 QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures; 6000 QList<QGraphicsObject *> targetItems = gesturesPerItem.keys(); 6001 qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst); 6002 for (int i = 0; i < targetItems.size(); ++i) { 6003 QGraphicsObject *item = targetItems.at(i); 6004 QList<QGesture *> gestures = gesturesPerItem.value(item); 6005 // remove gestures that were already delivered once and were ignored 6006 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 6007 << "already ignored gestures for item" 6008 << item << ":" << itemIgnoredGestures.value(item); 6009 6010 if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item 6011 continue; 6012 6013 QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func(); 6014 foreach(QGesture *g, alreadyIgnoredGestures) { 6015 QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit = 6016 gid->gestureContext.find(g->gestureType()); 6017 bool deliver = contextit != gid->gestureContext.end() && 6018 (g->state() == Qt::GestureStarted || 6019 (contextit.value() & Qt::ReceivePartialGestures)); 6020 if (deliver) 6021 gestures += g; 6022 } 6023 if (gestures.isEmpty()) 6024 continue; 6025 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 6026 << "delivering to" 6027 << item << gestures; 6028 QGestureEvent ev(gestures); 6029 ev.setWidget(event->widget()); 6030 sendEvent(item, &ev); 6031 QSet<QGesture *> ignoredGestures; 6032 foreach (QGesture *g, gestures) { 6033 if (!ev.isAccepted() && !ev.isAccepted(g)) { 6034 ignoredGestures.insert(g); 6035 } else { 6036 if (g->state() == Qt::GestureStarted) 6037 gestureTargets[g] = item; 6038 } 6039 } 6040 if (!ignoredGestures.isEmpty()) { 6041 // get a list of items under the (current) hotspot of each ignored 6042 // gesture and start delivery again from the beginning 6043 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 6044 << "item has ignored the event, will propagate." 6045 << item << ignoredGestures; 6046 itemIgnoredGestures[item] += ignoredGestures; 6047 QMap<Qt::GestureType, QGesture *> conflictedGestures; 6048 QList<QList<QGraphicsObject *> > itemsForConflictedGestures; 6049 QHash<QGesture *, QGraphicsObject *> normalGestures; 6050 getGestureTargets(ignoredGestures, viewport, 6051 &conflictedGestures, &itemsForConflictedGestures, 6052 &normalGestures); 6053 QSet<QGraphicsObject *> itemsSet = targetItems.toSet(); 6054 for (int k = 0; k < itemsForConflictedGestures.size(); ++k) 6055 itemsSet += itemsForConflictedGestures.at(k).toSet(); 6056 targetItems = itemsSet.toList(); 6057 qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst); 6058 alreadyIgnoredGestures = conflictedGestures.values(); 6059 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" 6060 << "new targets:" << targetItems; 6061 i = -1; // start delivery again 6062 continue; 6063 } 6064 } 6065 foreach (QGesture *g, startedGestures) { 6066 if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) { 6067 DEBUG() << "lets try to cancel some"; 6068 // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them 6069 cancelGesturesForChildren(g, event->widget()); 6070 } 6071 } 6072 6073 // forget about targets for gestures that have ended 6074 foreach (QGesture *g, allGestures) { 6075 switch (g->state()) { 6076 case Qt::GestureFinished: 6077 case Qt::GestureCanceled: 6078 gestureTargets.remove(g); 6079 break; 6080 default: 6081 break; 6082 } 6083 } 6084 } 6085 6086 void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidget *viewport) 6087 { 6088 Q_ASSERT(original); 6089 QGraphicsItem *originalItem = gestureTargets.value(original); 6090 Q_ASSERT(originalItem); 6091 6092 // iterate over all active gestures and for each find the owner 6093 // if the owner is part of our sub-hierarchy, cancel it. 6094 6095 QSet<QGesture *> canceledGestures; 6096 QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin(); 6097 while (iter != gestureTargets.end()) { 6098 QGraphicsObject *item = iter.value(); 6099 // note that we don't touch the gestures for our originalItem 6100 if (item != originalItem && originalItem->isAncestorOf(item)) { 6101 DEBUG() << " found a gesture to cancel" << iter.key(); 6102 iter.key()->d_func()->state = Qt::GestureCanceled; 6103 canceledGestures << iter.key(); 6104 } 6105 ++iter; 6106 } 6107 6108 // sort them per target item by cherry picking from almostCanceledGestures and delivering 6109 QSet<QGesture *> almostCanceledGestures = canceledGestures; 6110 QSet<QGesture *>::Iterator setIter; 6111 while (!almostCanceledGestures.isEmpty()) { 6112 QGraphicsObject *target = 0; 6113 QSet<QGesture*> gestures; 6114 setIter = almostCanceledGestures.begin(); 6115 // sort per target item 6116 while (setIter != almostCanceledGestures.end()) { 6117 QGraphicsObject *item = gestureTargets.value(*setIter); 6118 if (target == 0) 6119 target = item; 6120 if (target == item) { 6121 gestures << *setIter; 6122 setIter = almostCanceledGestures.erase(setIter); 6123 } else { 6124 ++setIter; 6125 } 6126 } 6127 Q_ASSERT(target); 6128 6129 QList<QGesture *> list = gestures.toList(); 6130 QGestureEvent ev(list); 6131 sendEvent(target, &ev); 6132 6133 foreach (QGesture *g, list) { 6134 if (ev.isAccepted() || ev.isAccepted(g)) 6135 gestures.remove(g); 6136 } 6137 6138 foreach (QGesture *g, gestures) { 6139 if (!g->hasHotSpot()) 6140 continue; 6141 6142 QPoint screenPos = g->hotSpot().toPoint(); 6143 QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport); 6144 for (int j = 0; j < items.size(); ++j) { 6145 QGraphicsObject *item = items.at(j)->toGraphicsObject(); 6146 if (!item) 6147 continue; 6148 QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); 6149 if (d->gestureContext.contains(g->gestureType())) { 6150 QList<QGesture *> list; 6151 list << g; 6152 QGestureEvent ev(list); 6153 sendEvent(item, &ev); 6154 if (ev.isAccepted() || ev.isAccepted(g)) 6155 break; // successfully delivered 6156 } 6157 } 6158 } 6159 } 6160 6161 QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager; 6162 Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager. 6163 for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) { 6164 gestureManager->recycle(*setIter); 6165 gestureTargets.remove(*setIter); 5519 6166 } 5520 6167 } -
trunk/src/gui/graphicsview/qgraphicsscene.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 84 84 class QGraphicsView; 85 85 class QGraphicsWidget; 86 class QGraphicsSceneIndex; 86 87 class QHelpEvent; 87 88 class QInputMethodEvent; … … 153 154 154 155 QList<QGraphicsItem *> items() const; 155 QList<QGraphicsItem *> items(const QPointF &pos) const; 156 QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; 157 QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; 158 QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; 156 QList<QGraphicsItem *> items(Qt::SortOrder order) const; // ### Qt 5: unify 157 158 QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; 159 QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; 160 QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; 161 QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; 162 163 QList<QGraphicsItem *> items(const QPointF &pos) const; // ### obsolete 164 QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete 165 QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete 166 QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete 167 159 168 QList<QGraphicsItem *> collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; 160 QGraphicsItem *itemAt(const QPointF &pos) const; 169 170 QGraphicsItem *itemAt(const QPointF &pos) const; // ### obsolete 171 QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const; 161 172 162 173 inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const 163 { return items(QRectF(x, y, w, h), mode); } 164 inline QGraphicsItem *itemAt(qreal x, qreal y) const 174 { return items(QRectF(x, y, w, h), mode); } // ### obsolete 175 inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, 176 const QTransform &deviceTransform = QTransform()) const 177 { return items(QRectF(x, y, w, h), mode, order, deviceTransform); } 178 inline QGraphicsItem *itemAt(qreal x, qreal y) const // ### obsolete 165 179 { return itemAt(QPointF(x, y)); } 180 inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const 181 { return itemAt(QPointF(x, y), deviceTransform); } 166 182 167 183 QList<QGraphicsItem *> selectedItems() const; 168 184 QPainterPath selectionArea() const; 169 void setSelectionArea(const QPainterPath &path); 170 void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode); 185 void setSelectionArea(const QPainterPath &path); // ### obsolete 186 void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform); 187 void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); // ### obsolete 188 void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform); 171 189 172 190 QGraphicsItemGroup *createItemGroup(const QList<QGraphicsItem *> &items); … … 190 208 { return addRect(QRectF(x, y, w, h), pen, brush); } 191 209 void removeItem(QGraphicsItem *item); 192 210 193 211 QGraphicsItem *focusItem() const; 194 212 void setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason = Qt::OtherFocusReason); … … 226 244 void setPalette(const QPalette &palette); 227 245 246 bool isActive() const; 247 QGraphicsItem *activePanel() const; 248 void setActivePanel(QGraphicsItem *item); 228 249 QGraphicsWidget *activeWindow() const; 229 250 void setActiveWindow(QGraphicsWidget *widget); 251 252 bool sendEvent(QGraphicsItem *item, QEvent *event); 230 253 231 254 public Q_SLOTS: … … 272 295 273 296 private: 274 void itemUpdated(QGraphicsItem *item, const QRectF &rect);275 276 297 Q_DECLARE_PRIVATE(QGraphicsScene) 277 298 Q_DISABLE_COPY(QGraphicsScene) 278 Q_PRIVATE_SLOT(d_func(), void _q_updateIndex())279 299 Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) 280 Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item))281 Q_PRIVATE_SLOT(d_func(), void _q_updateLater())282 300 Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) 283 Q_PRIVATE_SLOT(d_func(), void _q_ updateSortCache())284 Q_PRIVATE_SLOT(d_func(), void _q_ resetDirtyItems())301 Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems()) 302 Q_PRIVATE_SLOT(d_func(), void _q_updateScenePosDescendants()) 285 303 friend class QGraphicsItem; 286 304 friend class QGraphicsItemPrivate; … … 289 307 friend class QGraphicsWidget; 290 308 friend class QGraphicsWidgetPrivate; 309 friend class QGraphicsEffect; 310 friend class QGraphicsSceneIndex; 311 friend class QGraphicsSceneIndexPrivate; 312 friend class QGraphicsSceneBspTreeIndex; 313 friend class QGraphicsSceneBspTreeIndexPrivate; 314 friend class QGraphicsItemEffectSourcePrivate; 315 friend class QGesture; 291 316 }; 292 317 -
trunk/src/gui/graphicsview/qgraphicsscene_bsp.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 71 71 public: 72 72 QList<QGraphicsItem *> *foundItems; 73 bool onlyTopLevelItems; 73 74 74 75 void visit(QList<QGraphicsItem *> *items) … … 76 77 for (int i = 0; i < items->size(); ++i) { 77 78 QGraphicsItem *item = items->at(i); 78 if (!item->d_func()->itemDiscovered && item->isVisible()) { 79 if (onlyTopLevelItems && item->d_ptr->parent) 80 item = item->topLevelItem(); 81 if (!item->d_func()->itemDiscovered && item->d_ptr->visible) { 79 82 item->d_func()->itemDiscovered = 1; 80 83 foundItems->prepend(item); … … 144 147 } 145 148 146 QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect )149 QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const 147 150 { 148 151 QList<QGraphicsItem *> tmp; 149 152 findVisitor->foundItems = &tmp; 153 findVisitor->onlyTopLevelItems = onlyTopLevelItems; 150 154 climbTree(findVisitor, rect); 151 return tmp; 152 } 153 154 QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QPointF &pos) 155 { 156 QList<QGraphicsItem *> tmp; 157 findVisitor->foundItems = &tmp; 158 climbTree(findVisitor, pos); 155 // Reset discovery bits. 156 for (int i = 0; i < tmp.size(); ++i) 157 tmp.at(i)->d_ptr->itemDiscovered = 0; 159 158 return tmp; 160 159 } … … 236 235 } 237 236 238 void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const Q PointF &pos, int index)237 void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const 239 238 { 240 239 if (nodes.isEmpty()) … … 242 241 243 242 const Node &node = nodes.at(index); 244 int childIndex = firstChildIndex(index);243 const int childIndex = firstChildIndex(index); 245 244 246 245 switch (node.type) { 247 246 case Node::Leaf: { 248 visitor->visit(&leaves[node.leafIndex]); 249 break; 250 } 251 case Node::Vertical: 252 if (pos.x() < node.offset) { 253 climbTree(visitor, pos, childIndex); 254 } else { 255 climbTree(visitor, pos, childIndex + 1); 256 } 257 break; 258 case Node::Horizontal: 259 if (pos.y() < node.offset) { 260 climbTree(visitor, pos, childIndex); 261 } else { 262 climbTree(visitor, pos, childIndex + 1); 263 } 264 break; 265 } 266 } 267 268 void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) 269 { 270 if (nodes.isEmpty()) 271 return; 272 273 const Node &node = nodes.at(index); 274 int childIndex = firstChildIndex(index); 275 276 switch (node.type) { 277 case Node::Leaf: { 278 visitor->visit(&leaves[node.leafIndex]); 247 visitor->visit(const_cast<QList<QGraphicsItem*>*>(&leaves[node.leafIndex])); 279 248 break; 280 249 } … … 289 258 break; 290 259 case Node::Horizontal: 291 int childIndex = firstChildIndex(index);292 260 if (rect.top() < node.offset) { 293 261 climbTree(visitor, rect, childIndex); -
trunk/src/gui/graphicsview/qgraphicsscene_bsp_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 93 93 void removeItems(const QSet<QGraphicsItem *> &items); 94 94 95 QList<QGraphicsItem *> items(const QRectF &rect); 96 QList<QGraphicsItem *> items(const QPointF &pos); 95 QList<QGraphicsItem *> items(const QRectF &rect, bool onlyTopLevelItems = false) const; 97 96 int leafCount() const; 98 97 … … 107 106 private: 108 107 void initialize(const QRectF &rect, int depth, int index); 109 void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0); 110 void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0); 111 112 void findItems(QList<QGraphicsItem *> *foundItems, const QRectF &rect, int index); 113 void findItems(QList<QGraphicsItem *> *foundItems, const QPointF &pos, int index); 108 void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const; 114 109 QRectF rectForIndex(int index) const; 115 110 -
trunk/src/gui/graphicsview/qgraphicsscene_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 // 49 49 // This file is not part of the Qt API. It exists for the convenience 50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header51 // file may change from version toversion without notice, or even be removed.50 // of other Qt classes. This header file may change from version to 51 // version without notice, or even be removed. 52 52 // 53 53 // We mean it. … … 58 58 #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW 59 59 60 #include "qgraphicsscene_bsp_p.h" 60 #include "qgraphicssceneevent.h" 61 #include "qgraphicsview.h" 62 #include "qgraphicsview_p.h" 61 63 #include "qgraphicsitem_p.h" 62 64 … … 69 71 #include <QtGui/qpalette.h> 70 72 #include <QtGui/qstyle.h> 73 #include <QtGui/qstyleoption.h> 71 74 72 75 QT_BEGIN_NAMESPACE 73 76 77 class QGraphicsSceneIndex; 74 78 class QGraphicsView; 75 79 class QGraphicsWidget; 76 80 77 class Q GraphicsScenePrivate : public QObjectPrivate81 class Q_AUTOTEST_EXPORT QGraphicsScenePrivate : public QObjectPrivate 78 82 { 79 83 Q_DECLARE_PUBLIC(QGraphicsScene) … … 82 86 void init(); 83 87 84 quint32 changedSignalMask; 88 static QGraphicsScenePrivate *get(QGraphicsScene *q); 89 90 static int changedSignalIndex; 85 91 86 92 QGraphicsScene::ItemIndexMethod indexMethod; 87 int bspTreeDepth; 88 89 QList<QGraphicsItem *> estimateItemsInRect(const QRectF &rect) const; 90 void addToIndex(QGraphicsItem *item); 91 void removeFromIndex(QGraphicsItem *item); 92 void resetIndex(); 93 94 QGraphicsSceneBspTree bspTree; 95 void _q_updateIndex(); 93 QGraphicsSceneIndex *index; 94 96 95 int lastItemCount; 97 96 98 97 QRectF sceneRect; 99 98 bool hasSceneRect; 99 bool dirtyGrowingItemsBoundingRect; 100 100 QRectF growingItemsBoundingRect; 101 QRectF largestUntransformableItem;102 101 103 102 void _q_emitUpdated(); … … 105 104 bool updateAll; 106 105 bool calledEmitUpdated; 106 bool processDirtyItemsEmitted; 107 107 108 108 QPainterPath selectionArea; 109 109 int selectionChanging; 110 110 QSet<QGraphicsItem *> selectedItems; 111 QList<QGraphicsItem *> unindexedItems; 112 QList<QGraphicsItem *> indexedItems; 113 QList<QGraphicsItem *> dirtyItems; 114 QList<QGraphicsItem *> pendingUpdateItems; 115 QList<QGraphicsItem *> unpolishedItems; 111 QSet<QGraphicsItem *> unpolishedItems; 112 QList<QGraphicsItem *> topLevelItems; 113 bool needSortTopLevelItems; 114 bool unpolishedItemsModified; 115 bool holesInTopLevelSiblingIndex; 116 bool topLevelSequentialOrdering; 117 116 118 QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions; 119 void registerTopLevelItem(QGraphicsItem *item); 120 void unregisterTopLevelItem(QGraphicsItem *item); 117 121 void _q_updateLater(); 118 122 void _q_polishItems(); 119 123 120 void _q_resetDirtyItems(); 121 void resetDirtyItemsLater(); 122 bool dirtyItemResetPending; 123 124 QList<int> freeItemIndexes; 125 bool regenerateIndex; 126 127 bool purgePending; 128 void _q_removeItemLater(QGraphicsItem *item); 129 QSet<QGraphicsItem *> removedItems; 130 void purgeRemovedItems(); 124 void _q_processDirtyItems(); 125 126 QSet<QGraphicsItem *> scenePosItems; 127 bool scenePosDescendantsUpdatePending; 128 void setScenePosItemEnabled(QGraphicsItem *item, bool enabled); 129 void registerScenePosItem(QGraphicsItem *item); 130 void unregisterScenePosItem(QGraphicsItem *item); 131 void _q_updateScenePosDescendants(); 132 133 void removeItemHelper(QGraphicsItem *item); 131 134 132 135 QBrush backgroundBrush; 133 136 QBrush foregroundBrush; 134 135 int indexTimerId;136 bool restartIndexTimer;137 void startIndexTimer();138 137 139 138 bool stickyFocus; … … 142 141 QGraphicsItem *lastFocusItem; 143 142 QGraphicsWidget *tabFocusFirst; 144 QGraphicsWidget *activeWindow; 143 QGraphicsItem *activePanel; 144 QGraphicsItem *lastActivePanel; 145 145 int activationRefCount; 146 int childExplicitActivation; 147 void setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent); 148 void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason); 146 149 147 150 QList<QGraphicsWidget *> popupWidgets; … … 160 163 void ungrabKeyboard(QGraphicsItem *item, bool itemIsDying = false); 161 164 void clearKeyboardGrabber(); 162 165 163 166 QGraphicsItem *dragDropItem; 164 167 QGraphicsWidget *enterWidget; … … 166 169 QList<QGraphicsItem *> cachedItemsUnderMouse; 167 170 QList<QGraphicsItem *> hoverItems; 171 QPointF lastSceneMousePos; 172 bool allItemsIgnoreHoverEvents; 173 bool allItemsUseDefaultCursor; 174 void enableMouseTrackingOnViews(); 168 175 QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos; 169 176 QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownScenePos; … … 172 179 const QPointF &scenePos, 173 180 QWidget *widget) const; 174 static bool itemCollidesWithPath(QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode);175 181 void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event); 176 182 177 183 QList<QGraphicsView *> views; 184 void addView(QGraphicsView *view); 185 void removeView(QGraphicsView *view); 186 178 187 bool painterStateProtection; 179 188 … … 181 190 void installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter); 182 191 void removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter); 192 bool filterDescendantEvent(QGraphicsItem *item, QEvent *event); 183 193 bool filterEvent(QGraphicsItem *item, QEvent *event); 184 194 bool sendEvent(QGraphicsItem *item, QEvent *event); … … 198 208 QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; 199 209 200 QList<QGraphicsItem *> items_helper(const QPointF &pos) const; 201 QList<QGraphicsItem *> items_helper(const QRectF &rect, 202 Qt::ItemSelectionMode mode, 203 Qt::SortOrder order) const; 204 QList<QGraphicsItem *> items_helper(const QPolygonF &rect, 205 Qt::ItemSelectionMode mode, 206 Qt::SortOrder order) const; 207 QList<QGraphicsItem *> items_helper(const QPainterPath &rect, 208 Qt::ItemSelectionMode mode, 209 Qt::SortOrder order) const; 210 void childItems_helper(QList<QGraphicsItem *> *items, 211 const QGraphicsItem *parent, 212 const QPointF &pos) const; 213 void childItems_helper(QList<QGraphicsItem *> *items, 214 const QGraphicsItem *parent, 215 const QRectF &rect, 216 Qt::ItemSelectionMode mode) const; 217 void childItems_helper(QList<QGraphicsItem *> *items, 218 const QGraphicsItem *parent, 219 const QPolygonF &polygon, 220 Qt::ItemSelectionMode mode) const; 221 void childItems_helper(QList<QGraphicsItem *> *items, 222 const QGraphicsItem *parent, 223 const QPainterPath &path, 224 Qt::ItemSelectionMode mode) const; 225 226 bool sortCacheEnabled; 227 bool updatingSortCache; 228 void invalidateSortCache(); 229 static void climbTree(QGraphicsItem *item, int *stackingOrder); 230 void _q_updateSortCache(); 231 232 static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); 233 static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); 234 235 static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) 236 { 237 return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; 238 } 239 static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) 240 { 241 return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; 242 } 243 244 static void sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order, bool cached); 210 bool sortCacheEnabled; // for compatibility 245 211 246 212 void drawItemHelper(QGraphicsItem *item, QPainter *painter, 247 213 const QStyleOptionGraphicsItem *option, QWidget *widget, 248 214 bool painterStateProtection); 249 215 216 void drawItems(QPainter *painter, const QTransform *const viewTransform, 217 QRegion *exposedRegion, QWidget *widget); 218 219 void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, 220 QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0), 221 const QTransform *const effectTransform = 0); 222 void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const, 223 QRegion *, QWidget *, qreal, const QTransform *const, bool, bool); 224 225 void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, 226 bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false); 227 void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false, 228 qreal parentOpacity = qreal(1.0)); 229 230 inline void resetDirtyItem(QGraphicsItem *item, bool recursive = false) 231 { 232 Q_ASSERT(item); 233 item->d_ptr->dirty = 0; 234 item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; 235 item->d_ptr->geometryChanged = 0; 236 if (!item->d_ptr->dirtyChildren) 237 recursive = false; 238 item->d_ptr->dirtyChildren = 0; 239 item->d_ptr->needsRepaint = QRectF(); 240 item->d_ptr->allChildrenDirty = 0; 241 item->d_ptr->fullUpdatePending = 0; 242 item->d_ptr->ignoreVisible = 0; 243 item->d_ptr->ignoreOpacity = 0; 244 #ifndef QT_NO_GRAPHICSEFFECT 245 QGraphicsEffect::ChangeFlags flags; 246 if (item->d_ptr->notifyBoundingRectChanged) { 247 flags |= QGraphicsEffect::SourceBoundingRectChanged; 248 item->d_ptr->notifyBoundingRectChanged = 0; 249 } 250 if (item->d_ptr->notifyInvalidated) { 251 flags |= QGraphicsEffect::SourceInvalidated; 252 item->d_ptr->notifyInvalidated = 0; 253 } 254 #endif //QT_NO_GRAPHICSEFFECT 255 if (recursive) { 256 for (int i = 0; i < item->d_ptr->children.size(); ++i) 257 resetDirtyItem(item->d_ptr->children.at(i), recursive); 258 } 259 #ifndef QT_NO_GRAPHICSEFFECT 260 if (flags && item->d_ptr->graphicsEffect) 261 item->d_ptr->graphicsEffect->sourceChanged(flags); 262 #endif //QT_NO_GRAPHICSEFFECT 263 } 264 265 inline void ensureSortedTopLevelItems() 266 { 267 if (needSortTopLevelItems) { 268 qSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); 269 topLevelSequentialOrdering = false; 270 needSortTopLevelItems = false; 271 } 272 } 273 274 void ensureSequentialTopLevelSiblingIndexes(); 275 250 276 QStyle *style; 251 277 QFont font; … … 258 284 void updatePalette(const QPalette &palette); 259 285 260 mutable QVector<QTransform> sceneTransformCache; 261 mutable QBitArray validTransforms; 262 mutable QVector<int> freeSceneTransformSlots; 286 QStyleOptionGraphicsItem styleOptionTmp; 287 288 QMap<int, QTouchEvent::TouchPoint> sceneCurrentTouchPoints; 289 QMap<int, QGraphicsItem *> itemForTouchPointId; 290 static void updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent); 291 int findClosestTouchPointId(const QPointF &scenePos); 292 void touchEventHandler(QTouchEvent *touchEvent); 293 bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent); 294 bool allItemsIgnoreTouchEvents; 295 void enableTouchEventsOnViews(); 296 297 QHash<QGesture *, QGraphicsObject *> gestureTargets; 298 void gestureEventHandler(QGestureEvent *event); 299 void getGestureTargets(const QSet<QGesture *> &gestures, QWidget *viewport, 300 QMap<Qt::GestureType, QGesture *> *conflictedGestures, 301 QList<QList<QGraphicsObject *> > *conflictedItems, 302 QHash<QGesture *, QGraphicsObject *> *normalGestures); 303 void cancelGesturesForChildren(QGesture *original, QWidget *viewport); 304 305 void updateInputMethodSensitivityInViews(); 306 307 QList<QGraphicsItem *> modalPanels; 308 void enterModal(QGraphicsItem *item, 309 QGraphicsItem::PanelModality panelModality = QGraphicsItem::NonModal); 310 void leaveModal(QGraphicsItem *item); 263 311 }; 264 312 313 // QRectF::intersects() returns false always if either the source or target 314 // rectangle's width or height are 0. This works around that problem. 315 static inline void _q_adjustRect(QRectF *rect) 316 { 317 Q_ASSERT(rect); 318 if (!rect->width()) 319 rect->adjust(qreal(-0.00001), 0, qreal(0.00001), 0); 320 if (!rect->height()) 321 rect->adjust(0, qreal(-0.00001), 0, qreal(0.00001)); 322 } 323 324 static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) 325 { 326 Q_ASSERT(item); 327 QRectF boundingRect(item->boundingRect()); 328 _q_adjustRect(&boundingRect); 329 return boundingRect; 330 } 331 332 static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item) 333 { 334 Q_ASSERT(item); 335 QRectF boundingRect(QGraphicsItemPrivate::get(item)->effectiveBoundingRect()); 336 _q_adjustRect(&boundingRect); 337 return boundingRect; 338 } 339 265 340 QT_END_NAMESPACE 266 341 -
trunk/src/gui/graphicsview/qgraphicssceneevent.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 graphics view related events. 46 46 \since 4.2 47 \ingroup multimedia48 47 \ingroup graphicsview-api 49 48 … … 77 76 \l{QGraphicsSceneMouseEvent::}{lastScreenPos()}, 78 77 \l{QGraphicsSceneMouseEvent::}{lastScenePos()}, and 79 \l{QGraphicsSceneMouseEvent::}{lastPos()}). 78 \l{QGraphicsSceneMouseEvent::}{lastPos()}). 80 79 81 80 \sa QEvent … … 84 83 /*! 85 84 \class QGraphicsSceneMouseEvent 86 \brief The QGraphicsSceneMouseEvent class provides mouse events 85 \brief The QGraphicsSceneMouseEvent class provides mouse events 87 86 in the graphics view framework. 88 87 \since 4.2 89 \ingroup multimedia90 88 \ingroup graphicsview-api 91 89 92 When a QGraphicsView receives a QMouseEvent, it translates it to 93 a QGraphicsSceneMouseEvent. The event is then forwarded to the 94 QGraphicsScene associated with the view. 90 When a QGraphicsView receives a QMouseEvent, it translates it to a 91 QGraphicsSceneMouseEvent. The event is then forwarded to the 92 QGraphicsScene associated with the view. If the event is not 93 handled by the scene, the view may use it, e.g., for the 94 \l{QGraphicsView::}{DragMode}. 95 95 96 96 In addition to containing the item, scene, and screen coordinates … … 107 107 /*! 108 108 \class QGraphicsSceneWheelEvent 109 \brief The QGraphicsSceneWheelEvent class provides wheel events 109 \brief The QGraphicsSceneWheelEvent class provides wheel events 110 110 in the graphics view framework. 111 111 \brief The QGraphicsSceneWheelEvent class provides wheel events in the 112 112 graphics view framework. 113 113 \since 4.2 114 \ingroup multimedia115 114 \ingroup graphicsview-api 116 115 … … 129 128 menu events in the graphics view framework. 130 129 \since 4.2 131 \ingroup multimedia132 130 \ingroup graphicsview-api 133 131 … … 158 156 /*! 159 157 \class QGraphicsSceneHoverEvent 160 \brief The QGraphicsSceneHoverEvent class provides hover events 158 \brief The QGraphicsSceneHoverEvent class provides hover events 161 159 in the graphics view framework. 162 160 \since 4.2 163 \ingroup multimedia164 161 \ingroup graphicsview-api 165 162 … … 174 171 /*! 175 172 \class QGraphicsSceneHelpEvent 176 \brief The QGraphicsSceneHelpEvent class provides events when a 173 \brief The QGraphicsSceneHelpEvent class provides events when a 177 174 tooltip is requested. 178 175 \since 4.2 179 \ingroup multimedia180 176 \ingroup graphicsview-api 181 177 … … 200 196 \class QGraphicsSceneDragDropEvent 201 197 \brief The QGraphicsSceneDragDropEvent class provides events for 202 drag and drop in the graphics view framework. 198 drag and drop in the graphics view framework. 203 199 \since 4.2 204 \ingroup multimedia205 200 \ingroup graphicsview-api 206 201 … … 227 222 resizing in the graphics view framework. 228 223 \since 4.4 229 \ingroup multimedia230 224 \ingroup graphicsview-api 231 225 … … 244 238 moving in the graphics view framework. 245 239 \since 4.4 246 \ingroup multimedia247 240 \ingroup graphicsview-api 248 241 … … 269 262 #include <QtCore/qsize.h> 270 263 #include <QtCore/qstring.h> 264 #include "qgraphicsview.h" 265 #include "qgraphicsitem.h" 266 #include <QtGui/qgesture.h> 267 #include <private/qevent_p.h> 271 268 272 269 QT_BEGIN_NAMESPACE … … 314 311 QGraphicsSceneEvent::~QGraphicsSceneEvent() 315 312 { 316 delete d_ptr;317 313 } 318 314 … … 523 519 524 520 /*! 525 Returns the last recorded mouse cursor position in scene 521 Returns the last recorded mouse cursor position in scene 526 522 coordinates. The last recorded position is the position of 527 523 the previous mouse event received by the view that created … … 546 542 547 543 /*! 548 Returns the last recorded mouse cursor position in screen 544 Returns the last recorded mouse cursor position in screen 549 545 coordinates. The last recorded position is the position of 550 546 the previous mouse event received by the view that created … … 845 841 /*! 846 842 Returns the position of the mouse cursor in item coordinates at the moment 847 the thecontext menu was requested.843 the context menu was requested. 848 844 849 845 \sa scenePos(), screenPos() … … 993 989 /*! 994 990 Returns the position of the mouse cursor in item coordinates at the moment 995 the thehover event was sent.991 the hover event was sent. 996 992 997 993 \sa scenePos(), screenPos() … … 1018 1014 /*! 1019 1015 Returns the position of the mouse cursor in scene coordinates at the 1020 moment the thehover event was sent.1016 moment the hover event was sent. 1021 1017 1022 1018 \sa pos(), screenPos() … … 1043 1039 /*! 1044 1040 Returns the position of the mouse cursor in screen coordinates at the 1045 moment the thehover event was sent.1041 moment the hover event was sent. 1046 1042 1047 1043 \sa pos(), scenePos() … … 1139 1135 \since 4.4 1140 1136 1141 Returns the keyboard modifiers at the moment the thehover event was sent.1137 Returns the keyboard modifiers at the moment the hover event was sent. 1142 1138 */ 1143 1139 Qt::KeyboardModifiers QGraphicsSceneHoverEvent::modifiers() const … … 1185 1181 /*! 1186 1182 Returns the position of the mouse cursor in scene coordinates at the 1187 moment the thehelp event was sent.1183 moment the help event was sent. 1188 1184 1189 1185 \sa screenPos() … … 1210 1206 /*! 1211 1207 Returns the position of the mouse cursor in screen coordinates at the 1212 moment the thehelp event was sent.1208 moment the help event was sent. 1213 1209 1214 1210 \sa scenePos() … … 1276 1272 Returns the mouse position of the event relative to the 1277 1273 view that sent the event. 1278 1274 1279 1275 \sa QGraphicsView, screenPos(), scenePos() 1280 1276 */ … … 1374 1370 /*! 1375 1371 Returns the keyboard modifiers that were pressed when the drag 1376 and drop event was created. 1372 and drop event was created. 1377 1373 1378 1374 \sa Qt::KeyboardModifiers … … 1429 1425 \c possibleActions(). 1430 1426 1431 \sa Qt::DropAction, possibleActions() 1427 \sa Qt::DropAction, possibleActions() 1432 1428 */ 1433 1429 … … 1473 1469 Returns the action that was performed in this drag and drop. 1474 1470 This should be set by the receiver of the drop and is 1475 returned by QDrag:: start().1471 returned by QDrag::exec(). 1476 1472 1477 1473 \sa setDropAction(), acceptProposedAction() -
trunk/src/gui/graphicsview/qgraphicssceneevent.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 #include <QtCore/qcoreevent.h> 46 46 #include <QtCore/qpoint.h> 47 #include <QtCore/qscopedpointer.h> 48 #include <QtCore/qrect.h> 49 #include <QtGui/qpolygon.h> 50 #include <QtCore/qset.h> 51 #include <QtCore/qhash.h> 47 52 48 53 QT_BEGIN_HEADER … … 71 76 protected: 72 77 QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type = None); 73 Q GraphicsSceneEventPrivate *d_ptr;78 QScopedPointer<QGraphicsSceneEventPrivate> d_ptr; 74 79 Q_DECLARE_PRIVATE(QGraphicsSceneEvent) 75 80 }; -
trunk/src/gui/graphicsview/qgraphicsview.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** 40 40 ****************************************************************************/ 41 42 //#define QGRAPHICSVIEW_DEBUG43 41 44 42 static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50; … … 51 49 contents of a QGraphicsScene. 52 50 \since 4.2 53 \ingroup multimedia54 51 \ingroup graphicsview-api 55 \mainclass 52 56 53 57 54 QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable … … 100 97 widget. 101 98 102 QGraphicsView supports affine transformations, using Q Matrix. You can103 either pass a matrix to set Matrix(), or you can call one of the99 QGraphicsView supports affine transformations, using QTransform. You can 100 either pass a matrix to setTransform(), or you can call one of the 104 101 convenience functions rotate(), scale(), translate() or shear(). The most 105 102 two common transformations are scaling, which is used to implement … … 201 198 can vary between paint devices and platforms. 202 199 203 \value DontClipPainter QGraphicsView sometimes clips the painter when 204 rendering the scene contents. This can generally improve performance 205 (e.g., rendering only small parts of a large pixmap), and protects against 206 rendering mistakes (e.g., drawing outside bounding rectangles, or outside 207 the exposed area). In some situations, however, the painter clip can slow 208 down rendering; especially when all painting is restricted to inside 209 exposed areas. By enabling this flag, QGraphicsView will completely 210 disable its implicit clipping. Note that rendering artifacts from using a 211 semi-transparent foreground or background brush can occur if clipping is 212 disabled. 200 \value DontClipPainter This value is obsolete and has no effect. 213 201 214 202 \value DontSavePainterState When rendering, QGraphicsView protects the … … 229 217 common side effect is that items that do draw with antialiasing can leave 230 218 painting traces behind on the scene as they are moved. 219 220 \value IndirectPainting Since Qt 4.6, restore the old painting algorithm 221 that calls QGraphicsView::drawItems() and QGraphicsScene::drawItems(). 222 To be used only for compatibility with old code. 231 223 */ 232 224 … … 290 282 #include <QtGui/qscrollbar.h> 291 283 #include <QtGui/qstyleoption.h> 284 #include <QtGui/qinputcontext.h> 292 285 #ifdef Q_WS_X11 286 #include <QtGui/qpaintengine.h> 293 287 #include <private/qt_x11_p.h> 294 288 #endif 295 289 290 #include <private/qevent_p.h> 291 296 292 QT_BEGIN_NAMESPACE 293 294 bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); 297 295 298 296 inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision … … 303 301 return INT_MAX; 304 302 return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1); 303 } 304 305 void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent) 306 { 307 QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints(); 308 for (int i = 0; i < touchPoints.count(); ++i) { 309 QTouchEvent::TouchPoint &touchPoint = touchPoints[i]; 310 // the scene will set the item local pos, startPos, lastPos, and rect before delivering to 311 // an item, but for now those functions are returning the view's local coordinates 312 touchPoint.setSceneRect(d->mapToScene(touchPoint.rect())); 313 touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos())); 314 touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos())); 315 316 // screenPos, startScreenPos, lastScreenPos, and screenRect are already set 317 } 318 319 touchEvent->setTouchPoints(touchPoints); 305 320 } 306 321 … … 339 354 lastDragDropEvent(0), 340 355 fullUpdatePending(true), 341 dirtyRectCount(0),342 updatingLater(false),343 356 updateSceneSlotReimplementedChecked(false) 344 357 { … … 401 414 int right = q_round_bound(viewRect.right() - width); 402 415 if (left >= right) { 403 q->horizontalScrollBar()->setRange(0, 0);416 hbar->setRange(0, 0); 404 417 405 418 switch (alignment & Qt::AlignHorizontal_Mask) { … … 416 429 } 417 430 } else { 418 q->horizontalScrollBar()->setRange(left, right);419 q->horizontalScrollBar()->setPageStep(width);420 q->horizontalScrollBar()->setSingleStep(width / 20);431 hbar->setRange(left, right); 432 hbar->setPageStep(width); 433 hbar->setSingleStep(width / 20); 421 434 leftIndent = 0; 422 435 } … … 427 440 int bottom = q_round_bound(viewRect.bottom() - height); 428 441 if (top >= bottom) { 429 q->verticalScrollBar()->setRange(0, 0);442 vbar->setRange(0, 0); 430 443 431 444 switch (alignment & Qt::AlignVertical_Mask) { … … 442 455 } 443 456 } else { 444 q->verticalScrollBar()->setRange(top, bottom);445 q->verticalScrollBar()->setPageStep(height);446 q->verticalScrollBar()->setSingleStep(height / 20);457 vbar->setRange(top, bottom); 458 vbar->setPageStep(height); 459 vbar->setSingleStep(height / 20); 447 460 topIndent = 0; 448 461 } … … 456 469 if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) { 457 470 dirtyScroll = true; 458 q->viewport()->update();471 updateAll(); 459 472 } else if (q->isRightToLeft() && !leftIndent) { 460 473 // In reverse mode, the horizontal scroll always changes after the content … … 482 495 // Last scene pos: lastMouseMoveScenePoint 483 496 // Current mouse pos: 484 QPointF transformationDiff = q->mapToScene( q->viewport()->rect().center())485 - q->mapToScene( q->mapFromGlobal(QCursor::pos()));486 q->centerOn(lastMouseMoveScenePoint + transformationDiff); ;497 QPointF transformationDiff = q->mapToScene(viewport->rect().center()) 498 - q->mapToScene(viewport->mapFromGlobal(QCursor::pos())); 499 q->centerOn(lastMouseMoveScenePoint + transformationDiff); 487 500 } else { 488 501 q->centerOn(lastCenterPoint); … … 504 517 { 505 518 Q_Q(QGraphicsView); 506 lastCenterPoint = q->mapToScene( q->viewport()->rect().center());519 lastCenterPoint = q->mapToScene(viewport->rect().center()); 507 520 } 508 521 … … 531 544 const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); 532 545 return scrollY; 546 } 547 548 /*! 549 \internal 550 551 Maps the given rectangle to the scene using QTransform::mapRect() 552 */ 553 QRectF QGraphicsViewPrivate::mapRectToScene(const QRect &rect) const 554 { 555 if (dirtyScroll) 556 const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); 557 QRectF scrolled = QRectF(rect.translated(scrollX, scrollY)); 558 return identityMatrix ? scrolled : matrix.inverted().mapRect(scrolled); 559 } 560 561 562 /*! 563 \internal 564 565 Maps the given rectangle from the scene using QTransform::mapRect() 566 */ 567 QRectF QGraphicsViewPrivate::mapRectFromScene(const QRectF &rect) const 568 { 569 if (dirtyScroll) 570 const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); 571 return (identityMatrix ? rect : matrix.mapRect(rect)).translated(-scrollX, -scrollY); 533 572 } 534 573 … … 542 581 if (q->isRightToLeft()) { 543 582 if (!leftIndent) { 544 scrollX += q->horizontalScrollBar()->minimum();545 scrollX += q->horizontalScrollBar()->maximum();546 scrollX -= q->horizontalScrollBar()->value();583 scrollX += hbar->minimum(); 584 scrollX += hbar->maximum(); 585 scrollX -= hbar->value(); 547 586 } 548 587 } else { 549 scrollX += q->horizontalScrollBar()->value();550 } 551 552 scrollY = qint64( q->verticalScrollBar()->value() - topIndent);588 scrollX += hbar->value(); 589 } 590 591 scrollY = qint64(vbar->value() - topIndent); 553 592 554 593 dirtyScroll = false; … … 590 629 591 630 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove); 592 mouseEvent.setWidget( q->viewport());631 mouseEvent.setWidget(viewport); 593 632 mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint); 594 633 mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint); … … 603 642 lastMouseMoveScreenPoint = mouseEvent.screenPos(); 604 643 mouseEvent.setAccepted(false); 605 QApplication::sendEvent(scene, &mouseEvent); 644 if (event->spontaneous()) 645 qt_sendSpontaneousEvent(scene, &mouseEvent); 646 else 647 QApplication::sendEvent(scene, &mouseEvent); 606 648 607 649 // Remember whether the last event was accepted or not. … … 615 657 616 658 #ifndef QT_NO_CURSOR 659 // If all the items ignore hover events, we don't look-up any items 660 // in QGraphicsScenePrivate::dispatchHoverEvent, hence the 661 // cachedItemsUnderMouse list will be empty. We therefore do the look-up 662 // for cursor items here if not all items use the default cursor. 663 if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor 664 && scene->d_func()->cachedItemsUnderMouse.isEmpty()) { 665 scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(), 666 mouseEvent.scenePos(), 667 mouseEvent.widget()); 668 } 617 669 // Find the topmost item under the mouse with a cursor. 618 670 foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) { … … 627 679 // Restore the original viewport cursor. 628 680 hasStoredOriginalCursor = false; 629 q->viewport()->setCursor(originalCursor);681 viewport->setCursor(originalCursor); 630 682 } 631 683 #endif … … 659 711 void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor) 660 712 { 661 Q_Q(QGraphicsView);662 QWidget *viewport = q->viewport();663 713 if (!hasStoredOriginalCursor) { 664 714 hasStoredOriginalCursor = true; … … 686 736 hasStoredOriginalCursor = false; 687 737 if (dragMode == QGraphicsView::ScrollHandDrag) 688 q->viewport()->setCursor(Qt::OpenHandCursor);738 viewport->setCursor(Qt::OpenHandCursor); 689 739 else 690 q->viewport()->setCursor(originalCursor);740 viewport->setCursor(originalCursor); 691 741 } 692 742 #endif … … 727 777 dest->setDropAction(source->dropAction()); 728 778 dest->setMimeData(source->mimeData()); 729 dest->setWidget( q->viewport());779 dest->setWidget(viewport); 730 780 dest->setSource(source->source()); 731 781 #else … … 750 800 751 801 // Translate-only 802 // COMBINE 752 803 QPointF offset; 753 804 const QGraphicsItem *parentItem = item; 754 805 const QGraphicsItemPrivate *itemd; 755 806 do { 756 itemd = parentItem->d_ptr ;757 if (itemd-> hasTransform)807 itemd = parentItem->d_ptr.data(); 808 if (itemd->transformData) 758 809 break; 759 810 offset += itemd->pos; … … 787 838 788 839 // Accurate bounding region 789 QTransform itv = item-> sceneTransform() * q->viewportTransform();840 QTransform itv = item->deviceTransform(q->viewportTransform()); 790 841 return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect(); 791 842 } 792 843 793 // QRectF::intersects() returns false always if either the source or target794 // rectangle's width or height are 0. This works around that problem.795 static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)796 {797 Q_ASSERT(item);798 QRectF boundingRect(item->boundingRect());799 if (!boundingRect.width())800 boundingRect.adjust(-0.00001, 0, 0.00001, 0);801 if (!boundingRect.height())802 boundingRect.adjust(0, -0.00001, 0, 0.00001);803 return boundingRect;804 }805 806 844 /*! 807 845 \internal 808 846 */ 809 void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) 810 { 811 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate) 812 return; 813 if (item->d_ptr->dirty) 814 updateLater(); 815 816 QRectF updateRect = rect; 817 if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) { 818 updateRect &= adjustedItemBoundingRect(item); 819 if (updateRect.isEmpty()) 820 return; 821 } 822 823 QGraphicsItem *clipItem = item; 824 if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { 825 // Minimize unnecessary redraw. 826 QGraphicsItem *parent = item; 827 while ((parent = parent->d_ptr->parent)) { 828 if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) { 829 // Map update rect to the current parent and itersect with its bounding rect. 830 updateRect = clipItem->itemTransform(parent).mapRect(updateRect) 831 & adjustedItemBoundingRect(parent); 832 if (updateRect.isEmpty()) 833 return; 834 clipItem = parent; 835 } 836 837 if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) 838 break; 839 } 840 } 841 842 // Map update rect from clipItem coordinates to view coordinates. 843 Q_ASSERT(clipItem); 844 if (!item->d_ptr->hasBoundingRegionGranularity) 845 this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect()); 846 else 847 updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect()); 848 } 849 850 void QGraphicsViewPrivate::updateLater() 851 { 852 Q_Q(QGraphicsView); 853 if (updatingLater) 854 return; 855 updatingLater = true; 856 QMetaObject::invokeMethod(q, "_q_updateLaterSlot", Qt::QueuedConnection); 857 } 858 859 void QGraphicsViewPrivate::_q_updateLaterSlot() 860 { 861 Q_Q(QGraphicsView); 847 void QGraphicsViewPrivate::processPendingUpdates() 848 { 862 849 if (!scene) 863 850 return; 864 851 865 QRect vr = viewport->rect(); 866 QTransform viewTransform = q->viewportTransform(); 867 const QList<QGraphicsItem *> &dirtyItems = scene->d_func()->dirtyItems; 868 for (int i = 0; i < dirtyItems.size(); ++i) { 869 const QGraphicsItem *item = dirtyItems.at(i); 870 if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false, 871 /*ignoreVisibleBit=*/false, 872 /*ignoreDirtyBit=*/true)) { 873 continue; 874 } 875 QTransform x = item->sceneTransform() * viewTransform; 876 updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr); 877 } 878 879 dirtyRectCount += dirtyRects.size(); 880 881 bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate; 882 if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) { 883 if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate 884 || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate 885 && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) { 886 if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) { 887 viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); 888 } else { 889 viewport->update(dirtyBoundingRect); 890 } 891 } else { 892 // ### Improve this block, which is very slow for complex regions. We 893 // need to strike the balance between having an accurate update 894 // region, and running fast. The below approach is the simplest way to 895 // create a region from a bunch of rects, but we might want to use 896 // other approaches; e.g., a grid of a fixed size representing 897 // quadrants of the viewport, which we mark as dirty depending on the 898 // rectangles in the list. Perhaps this should go into a 899 // QRegion::fromRects(rects, how) function. 900 QRegion region; 901 if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) { 902 for (int i = 0; i < dirtyRegions.size(); ++i) { 903 QVector<QRect> rects = dirtyRegions.at(i).rects(); 904 for (int j = 0; j < rects.size(); ++j) 905 region += rects.at(j).adjusted(-2, -2, 2, 2); 906 } 907 for (int i = 0; i < dirtyRects.size(); ++i) 908 region += dirtyRects.at(i).adjusted(-2, -2, 2, 2); 909 } else { 910 for (int i = 0; i < dirtyRegions.size(); ++i) 911 region += dirtyRegions.at(i); 912 for (int i = 0; i < dirtyRects.size(); ++i) 913 region += dirtyRects.at(i); 914 } 915 916 viewport->update(region); 917 } 918 } 919 920 dirtyRegions.clear(); 921 dirtyRects.clear(); 922 dirtyRectCount = 0; 852 if (fullUpdatePending) { 853 viewport->update(); 854 } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { 855 if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) 856 viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1)); 857 else 858 viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); 859 } else { 860 viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. 861 } 862 923 863 dirtyBoundingRect = QRect(); 924 updatingLater = false; 925 } 926 927 void QGraphicsViewPrivate::updateAll() 928 { 929 Q_Q(QGraphicsView); 930 q->viewport()->update(); 931 fullUpdatePending = true; 932 dirtyRectCount = 0; 933 dirtyBoundingRect = QRect(); 934 updatingLater = false; 935 } 936 937 void QGraphicsViewPrivate::updateRegion(const QRegion &r) 938 { 939 if (r.isEmpty()) 940 return; 941 942 Q_Q(QGraphicsView); 943 944 // Rect intersects viewport - update everything? 864 dirtyRegion = QRegion(); 865 } 866 867 static inline bool intersectsViewport(const QRect &r, int width, int height) 868 { return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); } 869 870 static inline bool containsViewport(const QRect &r, int width, int height) 871 { return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; } 872 873 static inline void QRect_unite(QRect *rect, const QRect &other) 874 { 875 if (rect->isEmpty()) { 876 *rect = other; 877 } else { 878 rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()), 879 qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom())); 880 } 881 } 882 883 bool QGraphicsViewPrivate::updateRegion(const QRegion &r) 884 { 885 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty()) 886 return false; 887 888 const QRect boundingRect = r.boundingRect(); 889 if (!intersectsViewport(boundingRect, viewport->width(), viewport->height())) 890 return false; // Update region outside viewport. 891 945 892 switch (viewportUpdateMode) { 946 893 case QGraphicsView::FullViewportUpdate: 947 894 fullUpdatePending = true; 948 q->viewport()->update();895 viewport->update(); 949 896 break; 950 897 case QGraphicsView::BoundingRectViewportUpdate: 951 dirtyBoundingRect |= r.boundingRect();952 if ( dirtyBoundingRect == q->viewport()->rect()) {898 QRect_unite(&dirtyBoundingRect, boundingRect); 899 if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) { 953 900 fullUpdatePending = true; 954 q->viewport()->update(); 955 } else { 956 updateLater(); 901 viewport->update(); 957 902 } 958 903 break; 959 case QGraphicsView::SmartViewportUpdate: 960 dirtyBoundingRect |= r.boundingRect(); 961 if ((dirtyRectCount + r.numRects()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD) 962 dirtyRegions << r; 963 dirtyRectCount += r.numRects(); 964 updateLater(); 904 case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE 905 case QGraphicsView::MinimalViewportUpdate: 906 { 907 const QVector<QRect> &rects = r.rects(); 908 for (int i = 0; i < rects.size(); ++i) { 909 if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) 910 dirtyRegion += rects.at(i).adjusted(-1, -1, 1, 1); 911 else 912 dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2); 913 } 965 914 break; 966 case QGraphicsView::MinimalViewportUpdate: 967 dirtyRegions << r; 968 dirtyRectCount += r.numRects(); 969 updateLater(); 915 } 916 default: 970 917 break; 971 case QGraphicsView::NoViewportUpdate: 972 // Unreachable 973 break; 974 } 975 976 // Compress the regions... 977 if (dirtyRectCount > QGRAPHICSVIEW_REGION_RECT_THRESHOLD && dirtyRegions.size() > 1) { 978 QRegion masterRegion; 979 for (int i=0; i<dirtyRegions.size(); ++i) { 980 masterRegion |= dirtyRegions.at(i); 981 } 982 dirtyRectCount = masterRegion.numRects(); 983 dirtyRegions.clear(); 984 dirtyRegions << masterRegion; 985 } 986 } 987 988 void QGraphicsViewPrivate::updateRect(const QRect &r) 989 { 990 if (r.isEmpty()) 991 return; 992 993 Q_Q(QGraphicsView); 994 995 // Rect intersects viewport - update everything? 918 } 919 920 return true; 921 } 922 923 bool QGraphicsViewPrivate::updateRect(const QRect &r) 924 { 925 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate 926 || !intersectsViewport(r, viewport->width(), viewport->height())) { 927 return false; 928 } 929 996 930 switch (viewportUpdateMode) { 997 931 case QGraphicsView::FullViewportUpdate: 998 932 fullUpdatePending = true; 999 q->viewport()->update();933 viewport->update(); 1000 934 break; 1001 935 case QGraphicsView::BoundingRectViewportUpdate: 1002 dirtyBoundingRect |= r;1003 if ( dirtyBoundingRect == q->viewport()->rect()) {936 QRect_unite(&dirtyBoundingRect, r); 937 if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) { 1004 938 fullUpdatePending = true; 1005 q->viewport()->update(); 1006 } else { 1007 updateLater(); 939 viewport->update(); 1008 940 } 1009 941 break; 1010 case QGraphicsView::SmartViewportUpdate: 1011 dirtyBoundingRect |= r; 1012 if ((dirtyRectCount + dirtyRects.size()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD) 1013 dirtyRects << r; 1014 updateLater(); 942 case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE 943 case QGraphicsView::MinimalViewportUpdate: 944 if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) 945 dirtyRegion += r.adjusted(-1, -1, 1, 1); 946 else 947 dirtyRegion += r.adjusted(-2, -2, 2, 2); 1015 948 break; 1016 case QGraphicsView::MinimalViewportUpdate: 1017 dirtyRects << r; 1018 updateLater(); 949 default: 1019 950 break; 1020 case QGraphicsView::NoViewportUpdate: 1021 // Unreachable 1022 break; 1023 } 951 } 952 953 return true; 1024 954 } 1025 955 … … 1047 977 extern QPainterPath qt_regionToPath(const QRegion ®ion); 1048 978 1049 QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const 979 /*! 980 ### Adjustments in findItems: mapToScene(QRect) forces us to adjust the 981 input rectangle by (0, 0, 1, 1), because it uses QRect::bottomRight() 982 (etc) when mapping the rectangle to a polygon (which is _wrong_). In 983 addition, as QGraphicsItem::boundingRect() is defined in logical space, 984 but the default pen for QPainter is cosmetic with a width of 0, QPainter 985 is at risk of painting 1 pixel outside the bounding rect. Therefore we 986 must search for items with an adjustment of (-1, -1, 1, 1). 987 */ 988 QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems, 989 const QTransform &viewTransform) const 1050 990 { 1051 991 Q_Q(const QGraphicsView); 1052 const QPainterPath exposedPath(qt_regionToPath(exposedRegion)); 1053 const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); 1054 1055 if (exposedScenePath.contains(scene->d_func()->growingItemsBoundingRect)) { 992 993 // Step 1) If all items are contained within the expose region, then 994 // return a list of all visible items. ### the scene's growing bounding 995 // rect does not take into account untransformable items. 996 const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1)) 997 .boundingRect(); 998 if (exposedRegionSceneBounds.contains(scene->sceneRect())) { 1056 999 Q_ASSERT(allItems); 1057 1000 *allItems = true; 1058 1001 1059 // All items are guaranteed within the exposed region, don't bother using the index. 1060 QList<QGraphicsItem *> itemList(scene->items()); 1061 int i = 0; 1062 while (i < itemList.size()) { 1063 // But we only want to include items that are visible 1064 if (!itemList.at(i)->isVisible()) 1065 itemList.removeAt(i); 1066 else 1067 ++i; 1068 } 1069 1070 // Sort the items. 1071 QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled); 1072 return itemList; 1073 } 1074 1075 if (scene->d_func()->largestUntransformableItem.isNull()) { 1076 if (exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale) { 1077 return scene->d_func()->items_helper(exposedScenePath.controlPointRect(), 1078 Qt::IntersectsItemBoundingRect, 1079 Qt::DescendingOrder); 1080 } 1081 return scene->d_func()->items_helper(exposedScenePath, 1082 Qt::IntersectsItemBoundingRect, 1083 Qt::DescendingOrder); 1084 } 1085 1086 // NB! Path must be in viewport coordinates. 1087 return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); 1088 } 1089 1090 void QGraphicsViewPrivate::generateStyleOptions(const QList<QGraphicsItem *> &itemList, 1091 QGraphicsItem **itemArray, 1092 QStyleOptionGraphicsItem *styleOptionArray, 1093 const QTransform &worldTransform, 1094 bool allItems, 1095 const QRegion &exposedRegion) const 1096 { 1097 // Two unit vectors. 1098 QLineF v1(0, 0, 1, 0); 1099 QLineF v2(0, 0, 0, 1); 1100 QTransform itemToViewportTransform; 1101 QRectF brect; 1102 QTransform reverseMap; 1103 1104 for (int i = 0; i < itemList.size(); ++i) { 1105 QGraphicsItem *item = itemArray[i] = itemList[i]; 1106 1107 QStyleOptionGraphicsItem &option = styleOptionArray[i]; 1108 brect = item->boundingRect(); 1109 option.state = QStyle::State_None; 1110 option.rect = brect.toRect(); 1111 option.exposedRect = QRectF(); 1112 if (item->d_ptr->selected) 1113 option.state |= QStyle::State_Selected; 1114 if (item->d_ptr->enabled) 1115 option.state |= QStyle::State_Enabled; 1116 if (item->hasFocus()) 1117 option.state |= QStyle::State_HasFocus; 1118 if (scene->d_func()->hoverItems.contains(item)) 1119 option.state |= QStyle::State_MouseOver; 1120 if (item == scene->mouseGrabberItem()) 1121 option.state |= QStyle::State_Sunken; 1122 1123 // Calculate a simple level-of-detail metric. 1124 // ### almost identical code in QGraphicsScene::render() 1125 // and QGraphicsView::render() - consider refactoring 1126 if (item->d_ptr->itemIsUntransformable()) { 1127 itemToViewportTransform = item->deviceTransform(worldTransform); 1128 } else { 1129 itemToViewportTransform = item->sceneTransform() * worldTransform; 1130 } 1131 1132 if (itemToViewportTransform.type() <= QTransform::TxTranslate) { 1133 // Translation and rotation only? The LOD is 1. 1134 option.levelOfDetail = 1; 1135 } else { 1136 // LOD is the transformed area of a 1x1 rectangle. 1137 option.levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length()); 1138 } 1139 option.matrix = itemToViewportTransform.toAffine(); //### discards perspective 1140 1141 if (!allItems) { 1142 // Determine the item's exposed area 1143 reverseMap = itemToViewportTransform.inverted(); 1144 foreach (const QRect &rect, exposedRegion.rects()) { 1145 option.exposedRect |= reverseMap.mapRect(QRectF(rect.adjusted(-1, -1, 1, 1))); 1146 if (option.exposedRect.contains(brect)) 1147 break; 1148 } 1149 option.exposedRect &= brect; 1150 } else { 1151 // The whole item is exposed 1152 option.exposedRect = brect; 1153 } 1154 } 1002 // All items are guaranteed within the exposed region. 1003 return scene->items(Qt::AscendingOrder); 1004 } 1005 1006 // Step 2) If the expose region is a simple rect and the view is only 1007 // translated or scaled, search for items using 1008 // QGraphicsScene::items(QRectF). 1009 bool simpleRectLookup = exposedRegion.rectCount() == 1 && matrix.type() <= QTransform::TxScale; 1010 if (simpleRectLookup) { 1011 return scene->items(exposedRegionSceneBounds, 1012 Qt::IntersectsItemBoundingRect, 1013 Qt::AscendingOrder, viewTransform); 1014 } 1015 1016 // If the region is complex or the view has a complex transform, adjust 1017 // the expose region, convert it to a path, and then search for items 1018 // using QGraphicsScene::items(QPainterPath); 1019 QRegion adjustedRegion; 1020 foreach (const QRect &r, exposedRegion.rects()) 1021 adjustedRegion += r.adjusted(-1, -1, 1, 1); 1022 1023 const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion))); 1024 return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect, 1025 Qt::AscendingOrder, viewTransform); 1026 } 1027 1028 /*! 1029 \internal 1030 1031 Enables input methods for the view if and only if the current focus item of 1032 the scene accepts input methods. Call function whenever that condition has 1033 potentially changed. 1034 */ 1035 void QGraphicsViewPrivate::updateInputMethodSensitivity() 1036 { 1037 Q_Q(QGraphicsView); 1038 bool enabled = scene && scene->focusItem() 1039 && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod); 1040 q->setAttribute(Qt::WA_InputMethodEnabled, enabled); 1041 q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled); 1155 1042 } 1156 1043 … … 1164 1051 setAcceptDrops(true); 1165 1052 setBackgroundRole(QPalette::Base); 1166 1167 // ### Ideally this would be enabled/disabled depending on whether any 1168 // widgets in the current scene enabled input methods. We could do that 1169 // using a simple reference count. The same goes for acceptDrops and mouse 1170 // tracking. 1053 // Investigate leaving these disabled by default. 1171 1054 setAttribute(Qt::WA_InputMethodEnabled); 1055 viewport()->setAttribute(Qt::WA_InputMethodEnabled); 1172 1056 } 1173 1057 … … 1183 1067 setAcceptDrops(true); 1184 1068 setBackgroundRole(QPalette::Base); 1069 // Investigate leaving these disabled by default. 1185 1070 setAttribute(Qt::WA_InputMethodEnabled); 1071 viewport()->setAttribute(Qt::WA_InputMethodEnabled); 1186 1072 } 1187 1073 … … 1195 1081 setAcceptDrops(true); 1196 1082 setBackgroundRole(QPalette::Base); 1083 // Investigate leaving these disabled by default. 1197 1084 setAttribute(Qt::WA_InputMethodEnabled); 1085 viewport()->setAttribute(Qt::WA_InputMethodEnabled); 1198 1086 } 1199 1087 … … 1249 1137 return; 1250 1138 d->renderHints = hints; 1251 viewport()->update();1139 d->updateAll(); 1252 1140 } 1253 1141 … … 1267 1155 d->renderHints &= ~hint; 1268 1156 if (oldHints != d->renderHints) 1269 viewport()->update();1157 d->updateAll(); 1270 1158 } 1271 1159 … … 1323 1211 Q_D(QGraphicsView); 1324 1212 d->transformationAnchor = anchor; 1213 1214 // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse 1215 // in order to have up-to-date information for centering the view. 1216 if (d->transformationAnchor == AnchorUnderMouse) 1217 d->viewport->setMouseTracking(true); 1325 1218 } 1326 1219 … … 1350 1243 Q_D(QGraphicsView); 1351 1244 d->resizeAnchor = anchor; 1245 1246 // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse 1247 // in order to have up-to-date information for centering the view. 1248 if (d->resizeAnchor == AnchorUnderMouse) 1249 d->viewport->setMouseTracking(true); 1352 1250 } 1353 1251 … … 1554 1452 // Background caching is enabled. 1555 1453 d->mustResizeBackgroundPixmap = true; 1556 viewport()->update();1454 d->updateAll(); 1557 1455 } else if (d->mustResizeBackgroundPixmap) { 1558 1456 // Background caching is disabled. … … 1643 1541 1644 1542 // Always update the viewport when the scene changes. 1645 viewport()->update();1543 d->updateAll(); 1646 1544 1647 1545 // Remove the previously assigned scene. … … 1651 1549 disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)), 1652 1550 this, SLOT(updateSceneRect(QRectF))); 1653 d->scene->d_func()->views.removeAll(this); 1551 d->scene->d_func()->removeView(this); 1552 d->connectedToScene = false; 1553 1554 if (isActiveWindow() && isVisible()) { 1555 QEvent windowDeactivate(QEvent::WindowDeactivate); 1556 QApplication::sendEvent(d->scene, &windowDeactivate); 1557 } 1558 if(hasFocus()) 1559 d->scene->clearFocus(); 1654 1560 } 1655 1561 … … 1659 1565 this, SLOT(updateSceneRect(QRectF))); 1660 1566 d->updateSceneSlotReimplementedChecked = false; 1661 d->scene->d_func()-> views << this;1567 d->scene->d_func()->addView(this); 1662 1568 d->recalculateContentSize(); 1663 1569 d->lastCenterPoint = sceneRect().center(); 1664 1570 d->keepLastCenterPoint = true; 1571 // We are only interested in mouse tracking if items accept 1572 // hover events or use non-default cursors. 1573 if (!d->scene->d_func()->allItemsIgnoreHoverEvents 1574 || !d->scene->d_func()->allItemsUseDefaultCursor) { 1575 d->viewport->setMouseTracking(true); 1576 } 1577 1578 // enable touch events if any items is interested in them 1579 if (!d->scene->d_func()->allItemsIgnoreTouchEvents) 1580 d->viewport->setAttribute(Qt::WA_AcceptTouchEvents); 1581 1582 if (isActiveWindow() && isVisible()) { 1583 QEvent windowActivate(QEvent::WindowActivate); 1584 QApplication::sendEvent(d->scene, &windowActivate); 1585 } 1665 1586 } else { 1666 1587 d->recalculateContentSize(); 1667 1588 } 1589 1590 d->updateInputMethodSensitivity(); 1591 1592 if (d->scene && hasFocus()) 1593 d->scene->setFocus(); 1668 1594 } 1669 1595 … … 1712 1638 transformation is set, the identity matrix is returned. 1713 1639 1714 \sa setMatrix(), rotate(), scale(), shear(), translate()1640 \sa setMatrix(), transform(), rotate(), scale(), shear(), translate() 1715 1641 */ 1716 1642 QMatrix QGraphicsView::matrix() const … … 1744 1670 to map from floating point scene coordinates to view coordinates. 1745 1671 1746 \sa matrix(), rotate(), scale(), shear(), translate()1672 \sa matrix(), setTransform(), rotate(), scale(), shear(), translate() 1747 1673 */ 1748 1674 void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine) … … 1753 1679 /*! 1754 1680 Resets the view transformation matrix to the identity matrix. 1681 1682 \sa resetTransform() 1755 1683 */ 1756 1684 void QGraphicsView::resetMatrix() … … 1762 1690 Rotates the current view transformation \a angle degrees clockwise. 1763 1691 1764 \sa set Matrix(), matrix(), scale(), shear(), translate()1692 \sa setTransform(), transform(), scale(), shear(), translate() 1765 1693 */ 1766 1694 void QGraphicsView::rotate(qreal angle) … … 1775 1703 Scales the current view transformation by (\a sx, \a sy). 1776 1704 1777 \sa set Matrix(), matrix(), rotate(), shear(), translate()1705 \sa setTransform(), transform(), rotate(), shear(), translate() 1778 1706 */ 1779 1707 void QGraphicsView::scale(qreal sx, qreal sy) … … 1788 1716 Shears the current view transformation by (\a sh, \a sv). 1789 1717 1790 \sa set Matrix(), matrix(), rotate(), scale(), translate()1718 \sa setTransform(), transform(), rotate(), scale(), translate() 1791 1719 */ 1792 1720 void QGraphicsView::shear(qreal sh, qreal sv) … … 1801 1729 Translates the current view transformation by (\a dx, \a dy). 1802 1730 1803 \sa set Matrix(), matrix(), rotate(), shear()1731 \sa setTransform(), transform(), rotate(), shear() 1804 1732 */ 1805 1733 void QGraphicsView::translate(qreal dx, qreal dy) … … 1959 1887 function will do nothing. 1960 1888 1961 \sa set Matrix(), ensureVisible(), centerOn()1889 \sa setTransform(), ensureVisible(), centerOn() 1962 1890 */ 1963 1891 void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode) … … 2024 1952 { 2025 1953 QPainterPath path = item->isClipped() ? item->clipPath() : item->shape(); 2026 fitInView(item->sceneTransform().map(path).boundingRect(), aspectRatioMode); 1954 if (item->d_ptr->hasTranslateOnlySceneTransform()) { 1955 path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy()); 1956 fitInView(path.boundingRect(), aspectRatioMode); 1957 } else { 1958 fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode); 1959 } 2027 1960 } 2028 1961 … … 2050 1983 Qt::AspectRatioMode aspectRatioMode) 2051 1984 { 1985 // ### Switch to using the recursive rendering algorithm instead. 1986 2052 1987 Q_D(QGraphicsView); 2053 1988 if (!d->scene || !(painter && painter->isActive())) … … 2096 2031 2097 2032 // Setup painter matrix. 2098 QTransform moveMatrix; 2099 moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll()); 2033 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); 2100 2034 QTransform painterMatrix = d->matrix * moveMatrix; 2101 2035 painterMatrix *= QTransform() … … 2104 2038 .translate(-sourceRect.left(), -sourceRect.top()); 2105 2039 2106 // Two unit vectors.2107 QLineF v1(0, 0, 1, 0);2108 QLineF v2(0, 0, 0, 1);2109 2110 2040 // Generate the style options 2111 2041 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); 2112 QStyleOptionGraphicsItem* option = styleOptionArray; 2113 for (int i = 0; i < numItems; ++i, ++option) { 2114 QGraphicsItem *item = itemArray[i]; 2115 2116 option->state = QStyle::State_None; 2117 option->rect = item->boundingRect().toRect(); 2118 if (item->isSelected()) 2119 option->state |= QStyle::State_Selected; 2120 if (item->isEnabled()) 2121 option->state |= QStyle::State_Enabled; 2122 if (item->hasFocus()) 2123 option->state |= QStyle::State_HasFocus; 2124 if (d->scene->d_func()->hoverItems.contains(item)) 2125 option->state |= QStyle::State_MouseOver; 2126 if (item == d->scene->mouseGrabberItem()) 2127 option->state |= QStyle::State_Sunken; 2128 2129 // Calculate a simple level-of-detail metric. 2130 // ### almost identical code in QGraphicsScene::render() 2131 // and QGraphicsView::paintEvent() - consider refactoring 2132 QTransform itemToViewportTransform; 2133 if (item->d_ptr->itemIsUntransformable()) { 2134 itemToViewportTransform = item->deviceTransform(painterMatrix); 2135 } else { 2136 itemToViewportTransform = item->sceneTransform() * painterMatrix; 2137 } 2138 2139 option->levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length()); 2140 option->matrix = itemToViewportTransform.toAffine(); 2141 2142 option->exposedRect = item->boundingRect(); 2143 option->exposedRect &= itemToViewportTransform.inverted().mapRect(targetRect); 2144 } 2042 for (int i = 0; i < numItems; ++i) 2043 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect()); 2145 2044 2146 2045 painter->save(); … … 2169 2068 2170 2069 /*! 2171 Returns a list of all the items in the associated scene. 2172 2173 \sa QGraphicsScene::items() 2070 Returns a list of all the items in the associated scene, in descending 2071 stacking order (i.e., the first item in the returned list is the uppermost 2072 item). 2073 2074 \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} 2174 2075 */ 2175 2076 QList<QGraphicsItem *> QGraphicsView::items() const … … 2182 2083 2183 2084 /*! 2184 Returns all items in the area \a path, which is in viewport coordinates,2185 also taking untransformable items into consideration. This function is2186 considerably slower than just checking the scene directly. There is2187 certainly room for improvement.2188 */2189 QList<QGraphicsItem *> QGraphicsViewPrivate::itemsInArea(const QPainterPath &path,2190 Qt::ItemSelectionMode mode,2191 Qt::SortOrder order) const2192 {2193 Q_Q(const QGraphicsView);2194 2195 // Determine the size of the largest untransformable subtree of children2196 // mapped to scene coordinates.2197 QRectF untr = scene->d_func()->largestUntransformableItem;2198 QRectF ltri = matrix.inverted().mapRect(untr);2199 ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());2200 2201 QRectF rect = path.controlPointRect();2202 2203 // Find all possible items in the relevant area.2204 // ### Improve this algorithm; it might be searching a too large area.2205 QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect();2206 adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());2207 2208 // First build a (potentially large) list of all items in the vicinity2209 // that might be untransformable.2210 QList<QGraphicsItem *> allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect);2211 2212 // Then find the minimal list of items that are inside \a path, and2213 // convert it to a set.2214 QList<QGraphicsItem *> regularCandidates = scene->items(q->mapToScene(path), mode);2215 QSet<QGraphicsItem *> candSet = QSet<QGraphicsItem *>::fromList(regularCandidates);2216 2217 QTransform viewMatrix = q->viewportTransform();2218 2219 QList<QGraphicsItem *> result;2220 2221 // Run through all candidates and keep all items that are in candSet, or2222 // are untransformable and collide with \a path. ### We can improve this2223 // algorithm.2224 QList<QGraphicsItem *>::Iterator it = allCandidates.begin();2225 while (it != allCandidates.end()) {2226 QGraphicsItem *item = *it;2227 if (item->d_ptr->itemIsUntransformable()) {2228 // Check if this untransformable item collides with the2229 // original selection rect.2230 QTransform itemTransform = item->deviceTransform(viewMatrix);2231 if (QGraphicsScenePrivate::itemCollidesWithPath(item, itemTransform.inverted().map(path), mode))2232 result << item;2233 } else {2234 if (candSet.contains(item))2235 result << item;2236 }2237 ++it;2238 }2239 2240 // ### Insertion sort would be faster.2241 if (order != Qt::SortOrder(-1))2242 QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled);2243 return result;2244 }2245 2246 /*!2247 2085 Returns a list of all the items at the position \a pos in the view. The 2248 items are listed in descending Z order (i.e., the first item in the list2249 is the top-most item, and the last item is the bottom-most item). \a pos2250 is in viewport coordinates.2086 items are listed in descending stacking order (i.e., the first item in the 2087 list is the uppermost item, and the last item is the lowermost item). \a 2088 pos is in viewport coordinates. 2251 2089 2252 2090 This function is most commonly called from within mouse event handlers in … … 2256 2094 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5 2257 2095 2258 \sa QGraphicsScene::items(), QGraphicsItem::zValue()2096 \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} 2259 2097 */ 2260 2098 QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const … … 2263 2101 if (!d->scene) 2264 2102 return QList<QGraphicsItem *>(); 2265 if (d->scene->d_func()->largestUntransformableItem.isNull()) { 2266 if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { 2267 QTransform xinv = viewportTransform().inverted(); 2268 return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1))); 2269 } 2270 return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2)); 2271 } 2272 2273 QPainterPath path; 2274 path.addRect(QRectF(pos.x(), pos.y(), 1, 1)); 2275 return d->itemsInArea(path); 2103 // ### Unify these two, and use the items(QPointF) version in 2104 // QGraphicsScene instead. The scene items function could use the viewport 2105 // transform to map the point to a rect/polygon. 2106 if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { 2107 // Use the rect version 2108 QTransform xinv = viewportTransform().inverted(); 2109 return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)), 2110 Qt::IntersectsItemShape, 2111 Qt::DescendingOrder, 2112 viewportTransform()); 2113 } 2114 // Use the polygon version 2115 return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1), 2116 Qt::IntersectsItemShape, 2117 Qt::DescendingOrder, 2118 viewportTransform()); 2276 2119 } 2277 2120 … … 2293 2136 exact shape intersects with or is contained by \a rect are returned. 2294 2137 2295 \sa itemAt(), items(), mapToScene() 2138 The items are sorted in descending stacking order (i.e., the first item in 2139 the returned list is the uppermost item). 2140 2141 \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} 2296 2142 */ 2297 2143 QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const … … 2300 2146 if (!d->scene) 2301 2147 return QList<QGraphicsItem *>(); 2302 if (d->scene->d_func()->largestUntransformableItem.isNull()) 2303 return d->scene->items(mapToScene(rect), mode); 2304 2305 QPainterPath path; 2306 path.addRect(rect); 2307 return d->itemsInArea(path); 2148 return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform()); 2308 2149 } 2309 2150 … … 2326 2167 exact shape intersects with or is contained by \a polygon are returned. 2327 2168 2328 \sa itemAt(), items(), mapToScene() 2169 The items are sorted by descending stacking order (i.e., the first item in 2170 the returned list is the uppermost item). 2171 2172 \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} 2329 2173 */ 2330 2174 QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const … … 2333 2177 if (!d->scene) 2334 2178 return QList<QGraphicsItem *>(); 2335 if (d->scene->d_func()->largestUntransformableItem.isNull()) 2336 return d->scene->items(mapToScene(polygon), mode); 2337 2338 QPainterPath path; 2339 path.addPolygon(polygon); 2340 path.closeSubpath(); 2341 return d->itemsInArea(path); 2179 return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform()); 2342 2180 } 2343 2181 … … 2352 2190 exact shape intersects with or is contained by \a path are returned. 2353 2191 2354 \sa itemAt(), items(), mapToScene() 2192 \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} 2355 2193 */ 2356 2194 QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const … … 2359 2197 if (!d->scene) 2360 2198 return QList<QGraphicsItem *>(); 2361 if (d->scene->d_func()->largestUntransformableItem.isNull()) 2362 return d->scene->items(mapToScene(path), mode); 2363 return d->itemsInArea(path); 2199 return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform()); 2364 2200 } 2365 2201 … … 2373 2209 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6 2374 2210 2375 \sa items() 2211 \sa items(), {QGraphicsItem#Sorting}{Sorting} 2376 2212 */ 2377 2213 QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const … … 2430 2266 2431 2267 QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll()); 2432 Q PointF tl = scrollOffset + rect.topLeft();2433 QPointF t r = scrollOffset + rect.topRight();2434 QPointF br = scrollOffset + rect.bottomRight();2435 QPointF b l = scrollOffset + rect.bottomLeft();2436 2437 QPolygonF poly; 2438 poly.resize(4);2268 QRect r = rect.adjusted(0, 0, 1, 1); 2269 QPointF tl = scrollOffset + r.topLeft(); 2270 QPointF tr = scrollOffset + r.topRight(); 2271 QPointF br = scrollOffset + r.bottomRight(); 2272 QPointF bl = scrollOffset + r.bottomLeft(); 2273 2274 QPolygonF poly(4); 2439 2275 if (!d->identityMatrix) { 2440 2276 QTransform x = d->matrix.inverted(); … … 2482 2318 { 2483 2319 Q_D(const QGraphicsView); 2484 QTransform m oveMatrix;2485 m oveMatrix.translate(d->horizontalScroll(), d->verticalScroll());2486 return (moveMatrix * d->matrix.inverted()).map(path);2320 QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll()); 2321 matrix *= d->matrix.inverted(); 2322 return matrix.map(path); 2487 2323 } 2488 2324 … … 2539 2375 bl -= scrollOffset; 2540 2376 2541 QPolygon poly; 2542 poly.resize(4); 2377 QPolygon poly(4); 2543 2378 poly[0] = tl.toPoint(); 2544 2379 poly[1] = tr.toPoint(); … … 2578 2413 { 2579 2414 Q_D(const QGraphicsView); 2580 QTransform m oveMatrix;2581 m oveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());2582 return (d->matrix * moveMatrix).map(path);2415 QTransform matrix = d->matrix; 2416 matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); 2417 return matrix.map(path); 2583 2418 } 2584 2419 … … 2626 2461 Q_D(QGraphicsView); 2627 2462 d->backgroundBrush = brush; 2628 viewport()->update();2463 d->updateAll(); 2629 2464 2630 2465 if (d->cacheMode & CacheBackground) { … … 2656 2491 Q_D(QGraphicsView); 2657 2492 d->foregroundBrush = brush; 2658 viewport()->update();2493 d->updateAll(); 2659 2494 } 2660 2495 … … 2677 2512 // Extract and reset dirty scene rect info. 2678 2513 QVector<QRect> dirtyViewportRects; 2679 for (int i = 0; i < d->dirtyRegions.size(); ++i) 2680 dirtyViewportRects += d->dirtyRegions.at(i).rects(); 2681 d->dirtyRegions.clear(); 2514 const QVector<QRect> &dirtyRects = d->dirtyRegion.rects(); 2515 for (int i = 0; i < dirtyRects.size(); ++i) 2516 dirtyViewportRects += dirtyRects.at(i); 2517 d->dirtyRegion = QRegion(); 2518 d->dirtyBoundingRect = QRect(); 2682 2519 2683 2520 bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate; … … 2763 2600 const bool isGLWidget = widget->inherits("QGLWidget"); 2764 2601 2765 d->accelerateScrolling = !(isGLWidget 2766 || widget->testAttribute(Qt::WA_MSWindowsUseDirect3D) 2767 || qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)); 2602 d->accelerateScrolling = !(isGLWidget); 2768 2603 2769 2604 widget->setFocusPolicy(Qt::StrongFocus); … … 2774 2609 } 2775 2610 2776 widget->setMouseTracking(true); 2611 // We are only interested in mouse tracking if items 2612 // accept hover events or use non-default cursors or if 2613 // AnchorUnderMouse is used as transformation or resize anchor. 2614 if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents 2615 || !d->scene->d_func()->allItemsUseDefaultCursor)) 2616 || d->transformationAnchor == AnchorUnderMouse 2617 || d->resizeAnchor == AnchorUnderMouse) { 2618 widget->setMouseTracking(true); 2619 } 2620 2621 // enable touch events if any items is interested in them 2622 if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents) 2623 widget->setAttribute(Qt::WA_AcceptTouchEvents); 2624 2777 2625 widget->setAcceptDrops(acceptDrops()); 2778 2626 } … … 2825 2673 { 2826 2674 Q_D(QGraphicsView); 2827 2828 2675 if (!d->scene) 2829 2676 return QAbstractScrollArea::viewportEvent(event); … … 2844 2691 d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first()); 2845 2692 QApplication::sendEvent(d->scene, event); 2693 break; 2694 case QEvent::Show: 2695 if (d->scene && isActiveWindow()) { 2696 QEvent windowActivate(QEvent::WindowActivate); 2697 QApplication::sendEvent(d->scene, &windowActivate); 2698 } 2699 break; 2700 case QEvent::Hide: 2701 // spontaneous event will generate a WindowDeactivate. 2702 if (!event->spontaneous() && d->scene && isActiveWindow()) { 2703 QEvent windowDeactivate(QEvent::WindowDeactivate); 2704 QApplication::sendEvent(d->scene, &windowDeactivate); 2705 } 2846 2706 break; 2847 2707 case QEvent::Leave: … … 2873 2733 // Reset full update 2874 2734 d->fullUpdatePending = false; 2735 d->dirtyScrollOffset = QPoint(); 2875 2736 if (d->scene) { 2876 2737 // Check if this view reimplements the updateScene slot; if it … … 2891 2752 } 2892 2753 break; 2754 case QEvent::TouchBegin: 2755 case QEvent::TouchUpdate: 2756 case QEvent::TouchEnd: 2757 { 2758 if (!isEnabled()) 2759 return false; 2760 2761 if (d->scene && d->sceneInteractionAllowed) { 2762 // Convert and deliver the touch event to the scene. 2763 QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); 2764 touchEvent->setWidget(viewport()); 2765 QGraphicsViewPrivate::translateTouchEvent(d, touchEvent); 2766 (void) QApplication::sendEvent(d->scene, touchEvent); 2767 } 2768 2769 return true; 2770 } 2771 case QEvent::Gesture: 2772 case QEvent::GestureOverride: 2773 { 2774 if (!isEnabled()) 2775 return false; 2776 2777 if (d->scene && d->sceneInteractionAllowed) { 2778 QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event); 2779 gestureEvent->setWidget(viewport()); 2780 (void) QApplication::sendEvent(d->scene, gestureEvent); 2781 } 2782 return true; 2783 } 2893 2784 default: 2894 2785 break; … … 3064 2955 { 3065 2956 Q_D(QGraphicsView); 2957 d->updateInputMethodSensitivity(); 3066 2958 QAbstractScrollArea::focusInEvent(event); 3067 2959 if (d->scene) … … 3149 3041 mouseEvent.setButton(event->button()); 3150 3042 mouseEvent.setModifiers(event->modifiers()); 3151 QApplication::sendEvent(d->scene, &mouseEvent); 3043 if (event->spontaneous()) 3044 qt_sendSpontaneousEvent(d->scene, &mouseEvent); 3045 else 3046 QApplication::sendEvent(d->scene, &mouseEvent); 3152 3047 } 3153 3048 … … 3188 3083 mouseEvent.setModifiers(event->modifiers()); 3189 3084 mouseEvent.setAccepted(false); 3190 QApplication::sendEvent(d->scene, &mouseEvent); 3085 if (event->spontaneous()) 3086 qt_sendSpontaneousEvent(d->scene, &mouseEvent); 3087 else 3088 QApplication::sendEvent(d->scene, &mouseEvent); 3191 3089 3192 3090 // Update the original mouse event accepted state. … … 3249 3147 viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); 3250 3148 else 3251 viewport()->update();3149 d->updateAll(); 3252 3150 } 3253 3151 … … 3271 3169 viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); 3272 3170 else 3273 viewport()->update();3171 d->updateAll(); 3274 3172 } 3275 3173 // Set the new selection area … … 3278 3176 selectionArea.closeSubpath(); 3279 3177 if (d->scene) 3280 d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode); 3178 d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode, 3179 viewportTransform()); 3281 3180 return; 3282 3181 } … … 3314 3213 viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); 3315 3214 else 3316 viewport()->update();3215 d->updateAll(); 3317 3216 } 3318 3217 d->rubberBanding = false; … … 3321 3220 } else 3322 3221 #endif 3323 if (d->dragMode == QGraphicsView::ScrollHandDrag ) {3222 if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) { 3324 3223 #ifndef QT_NO_CURSOR 3325 3224 // Restore the open hand cursor. ### There might be items … … 3358 3257 mouseEvent.setModifiers(event->modifiers()); 3359 3258 mouseEvent.setAccepted(false); 3360 QApplication::sendEvent(d->scene, &mouseEvent); 3259 if (event->spontaneous()) 3260 qt_sendSpontaneousEvent(d->scene, &mouseEvent); 3261 else 3262 QApplication::sendEvent(d->scene, &mouseEvent); 3361 3263 3362 3264 // Update the last mouse event selected state. … … 3416 3318 3417 3319 // Determine the exposed region 3418 QRegion exposedRegion = event->region(); 3419 if (!d->accelerateScrolling) 3420 exposedRegion = viewport()->rect(); 3421 else if (d->viewportUpdateMode == BoundingRectViewportUpdate) 3422 exposedRegion = event->rect(); 3423 QRectF exposedSceneRect = mapToScene(exposedRegion.boundingRect().adjusted(0, 0, 1, 1)).boundingRect(); 3320 d->exposedRegion = event->region(); 3321 QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); 3424 3322 3425 3323 // Set up the painter 3426 3324 QPainter painter(viewport()); 3427 QTransform original = painter.worldTransform();3428 3325 #ifndef QT_NO_RUBBERBAND 3429 3326 if (d->rubberBanding && !d->rubberBandRect.isEmpty()) … … 3435 3332 3436 3333 // Set up viewport transform 3437 const QTransform viewTransform = viewportTransform(); 3438 painter.setTransform(viewTransform, true); 3439 3440 #ifdef QGRAPHICSVIEW_DEBUG 3441 QTime stopWatch; 3442 stopWatch.start(); 3443 qDebug() << "QGraphicsView::paintEvent(" << exposedRegion << ")"; 3444 #endif 3445 3446 // Find all exposed items 3447 bool allItems = false; 3448 QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems); 3449 3450 #ifdef QGRAPHICSVIEW_DEBUG 3451 int exposedTime = stopWatch.elapsed(); 3452 #endif 3453 3334 const bool viewTransformed = isTransformed(); 3335 if (viewTransformed) 3336 painter.setWorldTransform(viewportTransform()); 3337 const QTransform viewTransform = painter.worldTransform(); 3338 3339 // Draw background 3454 3340 if ((d->cacheMode & CacheBackground) 3455 3341 #ifdef Q_WS_X11 … … 3474 3360 QPainter backgroundPainter(&d->backgroundPixmap); 3475 3361 backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); 3476 backgroundPainter.setTransform(viewportTransform()); 3477 drawBackground(&backgroundPainter, exposedSceneRect); 3362 if (viewTransformed) 3363 backgroundPainter.setTransform(viewTransform); 3364 #ifdef Q_WS_X11 3365 #undef X11 3366 if (backgroundPainter.paintEngine()->type() != QPaintEngine::X11) 3367 #define X11 qt_x11Data 3368 #endif 3369 backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); 3370 QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect(); 3371 drawBackground(&backgroundPainter, backgroundExposedSceneRect); 3478 3372 d->backgroundPixmapExposed = QRegion(); 3479 3373 } 3480 3374 3481 3375 // Blit the background from the background pixmap 3482 QTransform oldMatrix = painter.worldTransform(); 3483 painter.setWorldTransform(original); 3484 painter.drawPixmap(QPoint(), d->backgroundPixmap); 3485 painter.setWorldTransform(oldMatrix); 3376 if (viewTransformed) { 3377 painter.setWorldTransform(QTransform()); 3378 painter.drawPixmap(QPoint(), d->backgroundPixmap); 3379 painter.setWorldTransform(viewTransform); 3380 } else { 3381 painter.drawPixmap(QPoint(), d->backgroundPixmap); 3382 } 3486 3383 } else { 3487 3384 if (!(d->optimizationFlags & DontSavePainterState)) … … 3492 3389 } 3493 3390 3494 #ifdef QGRAPHICSVIEW_DEBUG3495 int backgroundTime = stopWatch.elapsed() - exposedTime;3496 #endif3497 3498 // Generate the style options3499 QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];3500 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(itemList.size());3501 3502 d->generateStyleOptions(itemList, itemArray, styleOptionArray, viewTransform,3503 allItems, exposedRegion);3504 3505 3391 // Items 3506 drawItems(&painter, itemList.size(), itemArray, styleOptionArray); 3507 3508 #ifdef QGRAPHICSVIEW_DEBUG 3509 int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime; 3510 #endif 3392 if (!(d->optimizationFlags & IndirectPainting)) { 3393 d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0, 3394 &d->exposedRegion, viewport()); 3395 // Make sure the painter's world transform is restored correctly when 3396 // drawing without painter state protection (DontSavePainterState). 3397 // We only change the worldTransform() so there's no need to do a full-blown 3398 // save() and restore(). Also note that we don't have to do this in case of 3399 // IndirectPainting (the else branch), because in that case we always save() 3400 // and restore() in QGraphicsScene::drawItems(). 3401 if (!d->scene->d_func()->painterStateProtection) 3402 painter.setWorldTransform(viewTransform); 3403 } else { 3404 // Find all exposed items 3405 bool allItems = false; 3406 QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform); 3407 if (!itemList.isEmpty()) { 3408 // Generate the style options. 3409 const int numItems = itemList.size(); 3410 QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. 3411 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); 3412 for (int i = 0; i < numItems; ++i) { 3413 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, 3414 d->exposedRegion, allItems); 3415 } 3416 // Draw the items. 3417 drawItems(&painter, numItems, itemArray, styleOptionArray); 3418 d->freeStyleOptionsArray(styleOptionArray); 3419 } 3420 } 3511 3421 3512 3422 // Foreground 3513 3423 drawForeground(&painter, exposedSceneRect); 3514 3515 delete [] itemArray;3516 d->freeStyleOptionsArray(styleOptionArray);3517 3518 #ifdef QGRAPHICSVIEW_DEBUG3519 int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;3520 #endif3521 3424 3522 3425 #ifndef QT_NO_RUBBERBAND … … 3541 3444 painter.end(); 3542 3445 3543 #ifdef QGRAPHICSVIEW_DEBUG3544 qDebug() << "\tItem discovery....... " << exposedTime << "msecs (" << itemList.size() << "items,"3545 << (exposedTime > 0 ? (itemList.size() * 1000.0 / exposedTime) : -1) << "/ sec )";3546 qDebug() << "\tDrawing background... " << backgroundTime << "msecs (" << exposedRegion.numRects() << "segments )";3547 qDebug() << "\tDrawing items........ " << itemsTime << "msecs ("3548 << (itemsTime > 0 ? (itemList.size() * 1000.0 / itemsTime) : -1) << "/ sec )";3549 qDebug() << "\tDrawing foreground... " << foregroundTime << "msecs (" << exposedRegion.numRects() << "segments )";3550 qDebug() << "\tTotal rendering time: " << stopWatch.elapsed() << "msecs ("3551 << (stopWatch.elapsed() > 0 ? (1000.0 / stopWatch.elapsed()) : -1.0) << "fps )";3552 #endif3553 3554 3446 // Restore painter state protection. 3555 3447 d->scene->d_func()->painterStateProtection = true; … … 3598 3490 if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) { 3599 3491 if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) { 3600 for (int i = 0; i < d->dirtyRects.size(); ++i)3601 d->dirtyRects[i].translate(dx, dy);3602 for (int i = 0; i < d->dirtyRegions.size(); ++i)3603 d->dirtyRegions[i].translate(dx, dy);3604 3492 if (d->accelerateScrolling) { 3605 3493 #ifndef QT_NO_RUBBERBAND … … 3611 3499 } 3612 3500 #endif 3501 d->dirtyScrollOffset.rx() += dx; 3502 d->dirtyScrollOffset.ry() += dy; 3503 d->dirtyRegion.translate(dx, dy); 3613 3504 viewport()->scroll(dx, dy); 3614 3505 } else { 3615 viewport()->update();3506 d->updateAll(); 3616 3507 } 3617 3508 } else { 3618 viewport()->update();3509 d->updateAll(); 3619 3510 } 3620 3511 } … … 3627 3518 #endif 3628 3519 ) { 3520 // Scroll the background pixmap 3521 QRegion exposed; 3522 if (!d->backgroundPixmap.isNull()) 3523 d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed); 3524 3629 3525 // Invalidate the background pixmap 3630 d->backgroundPixmapExposed.translate(dx, 0); 3631 if (dx > 0) { 3632 d->backgroundPixmapExposed += QRect(0, 0, dx, viewport()->height()); 3633 } else if (dx < 0) { 3634 d->backgroundPixmapExposed += QRect(viewport()->width() + dx, 0, 3635 -dx, viewport()->height()); 3636 } 3637 d->backgroundPixmapExposed.translate(0, dy); 3638 if (dy > 0) { 3639 d->backgroundPixmapExposed += QRect(0, 0, viewport()->width(), dy); 3640 } else if (dy < 0) { 3641 d->backgroundPixmapExposed += QRect(0, viewport()->height() + dy, 3642 viewport()->width(), -dy); 3643 } 3644 3645 // Scroll the background pixmap 3646 if (!d->backgroundPixmap.isNull()) { 3647 QPixmap tmp = d->backgroundPixmap.copy(); 3648 QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole()); 3649 if (!bgBrush.isOpaque()) 3650 d->backgroundPixmap.fill(Qt::transparent); 3651 QPainter painter(&d->backgroundPixmap); 3652 painter.drawPixmap(dx, dy, tmp); 3653 } 3526 d->backgroundPixmapExposed.translate(dx, dy); 3527 d->backgroundPixmapExposed += exposed; 3654 3528 } 3655 3529 … … 3745 3619 The default implementation calls the scene's drawItems() function. 3746 3620 3621 \obsolete Since Qt 4.6, this function is not called anymore unless 3622 the QGraphicsView::IndirectPainting flag is given as an Optimization 3623 flag. 3624 3747 3625 \sa drawForeground(), drawBackground(), QGraphicsScene::drawItems() 3748 3626 */ … … 3752 3630 { 3753 3631 Q_D(QGraphicsView); 3754 if (d->scene) 3755 d->scene->drawItems(painter, numItems, items, options, viewport()); 3632 if (d->scene) { 3633 QWidget *widget = painter->device() == viewport() ? viewport() : 0; 3634 d->scene->drawItems(painter, numItems, items, options, widget); 3635 } 3756 3636 } 3757 3637 … … 3776 3656 { 3777 3657 Q_D(const QGraphicsView); 3778 QTransform moveMatrix; 3779 moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll()); 3658 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); 3780 3659 return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix; 3660 } 3661 3662 /*! 3663 \since 4.6 3664 3665 Returns true if the view is transformed (i.e., a non-identity transform 3666 has been assigned, or the scrollbars are adjusted). 3667 3668 \sa setTransform(), horizontalScrollBar(), verticalScrollBar() 3669 */ 3670 bool QGraphicsView::isTransformed() const 3671 { 3672 Q_D(const QGraphicsView); 3673 return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll(); 3781 3674 } 3782 3675 … … 3832 3725 3833 3726 // Any matrix operation requires a full update. 3834 viewport()->update();3727 d->updateAll(); 3835 3728 } 3836 3729 … … 3845 3738 } 3846 3739 3740 QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const 3741 { 3742 QPointF p = point; 3743 p.rx() += horizontalScroll(); 3744 p.ry() += verticalScroll(); 3745 return identityMatrix ? p : matrix.inverted().map(p); 3746 } 3747 3748 QRectF QGraphicsViewPrivate::mapToScene(const QRectF &rect) const 3749 { 3750 QPointF scrollOffset(horizontalScroll(), verticalScroll()); 3751 QPointF tl = scrollOffset + rect.topLeft(); 3752 QPointF tr = scrollOffset + rect.topRight(); 3753 QPointF br = scrollOffset + rect.bottomRight(); 3754 QPointF bl = scrollOffset + rect.bottomLeft(); 3755 3756 QPolygonF poly(4); 3757 if (!identityMatrix) { 3758 QTransform x = matrix.inverted(); 3759 poly[0] = x.map(tl); 3760 poly[1] = x.map(tr); 3761 poly[2] = x.map(br); 3762 poly[3] = x.map(bl); 3763 } else { 3764 poly[0] = tl; 3765 poly[1] = tr; 3766 poly[2] = br; 3767 poly[3] = bl; 3768 } 3769 return poly.boundingRect(); 3770 } 3771 3847 3772 QT_END_NAMESPACE 3848 3773 -
trunk/src/gui/graphicsview/qgraphicsview.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 111 111 112 112 enum OptimizationFlag { 113 DontClipPainter = 0x1, 113 DontClipPainter = 0x1, // obsolete 114 114 DontSavePainterState = 0x2, 115 DontAdjustForAntialiasing = 0x4 115 DontAdjustForAntialiasing = 0x4, 116 IndirectPainting = 0x8 116 117 }; 117 118 Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag) … … 170 171 QTransform transform() const; 171 172 QTransform viewportTransform() const; 173 bool isTransformed() const; 172 174 void setTransform(const QTransform &matrix, bool combine = false); 173 175 void resetTransform(); … … 274 276 Q_PRIVATE_SLOT(d_func(), void _q_unsetViewportCursor()) 275 277 #endif 276 Q_PRIVATE_SLOT(d_func(), void _q_updateLaterSlot())277 278 friend class QGraphicsSceneWidget; 278 279 friend class QGraphicsScene; 279 280 friend class QGraphicsScenePrivate; 281 friend class QGraphicsItemPrivate; 280 282 }; 281 283 -
trunk/src/gui/graphicsview/qgraphicsview_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 // 49 49 // This file is not part of the Qt API. It exists for the convenience 50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header51 // file may change from version toversion without notice, or even be removed.50 // of other Qt classes. This header file may change from version to 51 // version without notice, or even be removed. 52 52 // 53 53 // We mean it. … … 59 59 60 60 #include <QtGui/qevent.h> 61 #include <QtCore/qcoreapplication.h> 61 62 #include "qgraphicssceneevent.h" 63 #include <QtGui/qstyleoption.h> 62 64 #include <private/qabstractscrollarea_p.h> 63 65 64 66 QT_BEGIN_NAMESPACE 65 67 66 class Q_ GUI_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate68 class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate 67 69 { 68 70 Q_DECLARE_PUBLIC(QGraphicsView) … … 85 87 qint64 verticalScroll() const; 86 88 87 QList<QGraphicsItem *> itemsInArea(const QPainterPath &path, 88 Qt::ItemSelectionMode mode = Qt::IntersectsItemShape, 89 Qt::SortOrder = Qt::AscendingOrder) const; 89 QRectF mapRectToScene(const QRect &rect) const; 90 QRectF mapRectFromScene(const QRectF &rect) const; 90 91 91 92 QPointF mousePressItemPoint; … … 95 96 QPointF lastMouseMoveScenePoint; 96 97 QPoint lastMouseMoveScreenPoint; 98 QPoint dirtyScrollOffset; 97 99 Qt::MouseButton mousePressButton; 98 100 QTransform matrix; … … 160 162 QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const; 161 163 QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const; 162 void itemUpdated(QGraphicsItem *item, const QRectF &rect);163 164 bool fullUpdatePending; 164 QList<QRect> dirtyRects; 165 QList<QRegion> dirtyRegions; 166 int dirtyRectCount; 165 QRegion dirtyRegion; 167 166 QRect dirtyBoundingRect; 168 void updateLater(); 169 bool updatingLater; 170 void _q_updateLaterSlot(); 171 void updateAll(); 172 void updateRect(const QRect &rect); 173 void updateRegion(const QRegion ®ion); 167 void processPendingUpdates(); 168 inline void updateAll() 169 { 170 viewport->update(); 171 fullUpdatePending = true; 172 dirtyBoundingRect = QRect(); 173 dirtyRegion = QRegion(); 174 } 175 176 inline void dispatchPendingUpdateRequests() 177 { 178 #ifndef Q_WS_MAC 179 // QWidget::update() works slightly different on the Mac; it's not part of 180 // our backing store so it needs special threatment. 181 if (qt_widget_private(viewport)->paintOnScreen()) 182 QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); 183 else 184 QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); 185 #else 186 QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::ExcludeSocketNotifiers 187 | QEventLoop::ExcludeUserInputEvents); 188 #endif 189 } 190 191 bool updateRect(const QRect &rect); 192 bool updateRegion(const QRegion ®ion); 174 193 bool updateSceneSlotReimplementedChecked; 175 176 QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const; 177 178 void generateStyleOptions(const QList<QGraphicsItem *> &itemList,179 QGraphicsItem **itemArray, 180 QStyleOptionGraphicsItem *styleOptionArray, 181 const QTransform &worldTransform, 182 bool allItems, 183 const QRegion &exposedRegion) const;194 QRegion exposedRegion; 195 196 QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems, 197 const QTransform &viewTransform) const; 198 199 QPointF mapToScene(const QPointF &point) const; 200 QRectF mapToScene(const QRectF &rect) const; 201 static void translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent); 202 void updateInputMethodSensitivity(); 184 203 }; 185 204 -
trunk/src/gui/graphicsview/qgraphicswidget.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 75 75 items in a QGraphicsScene. 76 76 \since 4.4 77 \ingroup multimedia78 77 \ingroup graphicsview-api 79 78 … … 171 170 172 171 /*! 173 \property QGraphicsWidget::enabled174 \brief whether the item is enabled or not175 176 This property is declared in QGraphicsItem.177 178 By default, this property is true.179 180 \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()181 */182 183 /*!184 \property QGraphicsWidget::visible185 \brief whether the item is visible or not186 187 This property is declared in QGraphicsItem.188 189 By default, this property is true.190 191 \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), show(),192 hide()193 */194 195 /*!196 \property QGraphicsWidget::opacity197 \brief the opacity of the widget198 */199 200 /*!201 \property QGraphicsWidget::pos202 \brief the position of the widget203 */204 205 /*!206 172 Constructs a QGraphicsWidget instance. The optional \a parent argument is 207 173 passed to QGraphicsItem's constructor. The optional \a wFlags argument … … 210 176 */ 211 177 QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) 212 : QGraphics Item(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false)178 : QGraphicsObject(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false) 213 179 { 214 180 Q_D(QGraphicsWidget); … … 222 188 */ 223 189 QGraphicsWidget::QGraphicsWidget(QGraphicsWidgetPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene, Qt::WindowFlags wFlags) 224 : QGraphics Item(dd, 0, scene), QGraphicsLayoutItem(0, false)190 : QGraphicsObject(dd, 0, scene), QGraphicsLayoutItem(0, false) 225 191 { 226 192 Q_D(QGraphicsWidget); … … 292 258 //we check if we have a layout previously 293 259 if (d->layout) { 294 deleted->layout;260 QGraphicsLayout *temp = d->layout; 295 261 foreach (QGraphicsItem * item, childItems()) { 296 262 // In case of a custom layout which doesn't remove and delete items, we ensure that … … 303 269 } 304 270 } 271 d->layout = 0; 272 delete temp; 305 273 } 306 274 … … 351 319 352 320 /*! 321 \property QGraphicsWidget::sizePolicy 322 \brief the size policy for the widget 323 \sa sizePolicy(), setSizePolicy(), QWidget::sizePolicy() 324 */ 325 326 /*! 353 327 \property QGraphicsWidget::geometry 354 328 \brief the geometry of the widget … … 367 341 { 368 342 QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func(); 369 QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr ;343 QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr.data(); 370 344 QRectF newGeom; 371 345 QPointF oldPos = d->geom.topLeft(); … … 380 354 // setPos triggers ItemPositionChange, which can adjust position 381 355 wd->inSetGeometry = 1; 382 wd->setPosHelper(newGeom.topLeft());356 setPos(newGeom.topLeft()); 383 357 wd->inSetGeometry = 0; 384 358 newGeom.moveTopLeft(pos()); … … 441 415 442 416 /*! 417 \property QGraphicsWidget::minimumSize 418 \brief the minimum size of the widget 419 420 \sa setMinimumSize(), minimumSize(), preferredSize, maximumSize 421 */ 422 423 /*! 424 \property QGraphicsWidget::preferredSize 425 \brief the preferred size of the widget 426 427 \sa setPreferredSize(), preferredSize(), minimumSize, maximumSize 428 */ 429 430 /*! 431 \property QGraphicsWidget::maximumSize 432 \brief the maximum size of the widget 433 434 \sa setMaximumSize(), maximumSize(), minimumSize, preferredSize 435 */ 436 437 /*! 443 438 Sets the widget's contents margins to \a left, \a top, \a right and \a 444 439 bottom. … … 460 455 Q_D(QGraphicsWidget); 461 456 462 if (left == d->leftMargin 463 && top == d->topMargin 464 && right == d->rightMargin 465 && bottom == d->bottomMargin) { 457 if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0) 466 458 return; 467 } 468 469 d->leftMargin = left; 470 d->topMargin = top; 471 d->rightMargin = right; 472 d->bottomMargin = bottom; 459 d->ensureMargins(); 460 if (left == d->margins[d->Left] 461 && top == d->margins[d->Top] 462 && right == d->margins[d->Right] 463 && bottom == d->margins[d->Bottom]) 464 return; 465 466 d->margins[d->Left] = left; 467 d->margins[d->Top] = top; 468 d->margins[d->Right] = right; 469 d->margins[d->Bottom] = bottom; 473 470 474 471 if (QGraphicsLayout *l = d->layout) … … 491 488 { 492 489 Q_D(const QGraphicsWidget); 490 if (left || top || right || bottom) 491 d->ensureMargins(); 493 492 if (left) 494 *left = d-> leftMargin;493 *left = d->margins[d->Left]; 495 494 if (top) 496 *top = d-> topMargin;495 *top = d->margins[d->Top]; 497 496 if (right) 498 *right = d-> rightMargin;497 *right = d->margins[d->Right]; 499 498 if (bottom) 500 *bottom = d-> bottomMargin;499 *bottom = d->margins[d->Bottom]; 501 500 } 502 501 … … 514 513 { 515 514 Q_D(QGraphicsWidget); 516 bool unchanged = left == d->leftWindowFrameMargin && top == d->topWindowFrameMargin 517 && right == d->rightWindowFrameMargin && bottom == d->bottomWindowFrameMargin; 515 516 if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0) 517 return; 518 d->ensureWindowFrameMargins(); 519 bool unchanged = 520 d->windowFrameMargins[d->Left] == left 521 && d->windowFrameMargins[d->Top] == top 522 && d->windowFrameMargins[d->Right] == right 523 && d->windowFrameMargins[d->Bottom] == bottom; 518 524 if (d->setWindowFrameMargins && unchanged) 519 525 return; 520 526 if (!unchanged) 521 527 prepareGeometryChange(); 522 d-> leftWindowFrameMargin= left;523 d-> topWindowFrameMargin= top;524 d-> rightWindowFrameMargin= right;525 d-> bottomWindowFrameMargin= bottom;528 d->windowFrameMargins[d->Left] = left; 529 d->windowFrameMargins[d->Top] = top; 530 d->windowFrameMargins[d->Right] = right; 531 d->windowFrameMargins[d->Bottom] = bottom; 526 532 d->setWindowFrameMargins = true; 527 533 } … … 537 543 { 538 544 Q_D(const QGraphicsWidget); 545 if (left || top || right || bottom) 546 d->ensureWindowFrameMargins(); 539 547 if (left) 540 *left = d-> leftWindowFrameMargin;548 *left = d->windowFrameMargins[d->Left]; 541 549 if (top) 542 *top = d-> topWindowFrameMargin;550 *top = d->windowFrameMargins[d->Top]; 543 551 if (right) 544 *right = d-> rightWindowFrameMargin;552 *right = d->windowFrameMargins[d->Right]; 545 553 if (bottom) 546 *bottom = d-> bottomWindowFrameMargin;554 *bottom = d->windowFrameMargins[d->Bottom]; 547 555 } 548 556 … … 578 586 { 579 587 Q_D(const QGraphicsWidget); 580 return geometry().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin, 581 d->rightWindowFrameMargin, d->bottomWindowFrameMargin); 588 return d->windowFrameMargins 589 ? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top], 590 d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom]) 591 : geometry(); 582 592 } 583 593 … … 590 600 { 591 601 Q_D(const QGraphicsWidget); 592 return rect().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin, 593 d->rightWindowFrameMargin, d->bottomWindowFrameMargin); 602 return d->windowFrameMargins 603 ? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top], 604 d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom]) 605 : rect(); 594 606 } 595 607 … … 699 711 QSizeF sh; 700 712 if (d->layout) { 701 sh = d->layout->effectiveSizeHint(which, constraint); 702 sh += QSizeF(d->leftMargin + d->rightMargin, d->topMargin + d->bottomMargin); 713 QSizeF marginSize(0,0); 714 if (d->margins) { 715 marginSize = QSizeF(d->margins[d->Left] + d->margins[d->Right], 716 d->margins[d->Top] + d->margins[d->Bottom]); 717 } 718 sh = d->layout->effectiveSizeHint(which, constraint - marginSize); 719 sh += marginSize; 703 720 } else { 704 721 switch (which) { … … 985 1002 very important that subclasses call the base implementation. 986 1003 987 For example, QGraphicsWidget uses ItemVisibleChange to deliver \l Show and 988 \l Hide events, ItemPositionHasChanged to deliver \l Move events, and 989 ItemParentChange both to deliver \l ParentChange events, and for managing 990 the focus chain. 991 992 \sa propertyChange() 1004 \a change specifies the type of change, and \a value is the new value. 1005 1006 For example, QGraphicsWidget uses ItemVisibleChange to deliver 1007 \l{QEvent::Show} {Show} and \l{QEvent::Hide}{Hide} events, 1008 ItemPositionHasChanged to deliver \l{QEvent::Move}{Move} events, 1009 and ItemParentChange both to deliver \l{QEvent::ParentChange} 1010 {ParentChange} events, and for managing the focus chain. 1011 1012 QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in 1013 order to track position changes. 1014 1015 \sa QGraphicsItem::itemChange() 993 1016 */ 994 1017 QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value) … … 1032 1055 case ItemParentChange: { 1033 1056 QGraphicsItem *parent = qVariantValue<QGraphicsItem *>(value); 1034 d->fixFocusChainBeforeReparenting((parent && parent->isWidget()) ? static_cast<QGraphicsWidget *>(parent) : 0 );1057 d->fixFocusChainBeforeReparenting((parent && parent->isWidget()) ? static_cast<QGraphicsWidget *>(parent) : 0, scene()); 1035 1058 1036 1059 // Deliver ParentAboutToChange. … … 1040 1063 } 1041 1064 case ItemParentHasChanged: { 1042 // reset window type on parent change in order to automagically remove decorations etc.1043 Qt::WindowFlags wflags = d->windowFlags & ~Qt::WindowType_Mask;1044 d->adjustWindowFlags(&wflags);1045 setWindowFlags(wflags);1046 1065 // Deliver ParentChange. 1047 1066 QEvent event(QEvent::ParentChange); … … 1108 1127 bool QGraphicsWidget::sceneEvent(QEvent *event) 1109 1128 { 1110 return Q CoreApplication::sendEvent(this, event) || QGraphicsItem::sceneEvent(event);1129 return QGraphicsItem::sceneEvent(event); 1111 1130 } 1112 1131 … … 1132 1151 break; 1133 1152 case QEvent::GraphicsSceneMouseMove: 1134 if (d->grabbedSection != Qt::NoSection) { 1153 d->ensureWindowData(); 1154 if (d->windowData->grabbedSection != Qt::NoSection) { 1135 1155 d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); 1136 1156 event->accept(); … … 1187 1207 const qreal cornerMargin = 20; 1188 1208 //### Not sure of this one, it should be the same value for all edges. 1189 const qreal windowFrameWidth = d->leftWindowFrameMargin; 1209 const qreal windowFrameWidth = d->windowFrameMargins 1210 ? d->windowFrameMargins[d->Left] : 0; 1190 1211 1191 1212 Qt::WindowFrameSection s = Qt::NoSection; … … 1213 1234 if (s == Qt::NoSection) { 1214 1235 QRectF r1 = r; 1215 r1.setHeight(d->topWindowFrameMargin); 1236 r1.setHeight(d->windowFrameMargins 1237 ? d->windowFrameMargins[d->Top] : 0); 1216 1238 if (r1.contains(pos)) 1217 1239 s = Qt::TitleBarArea; … … 1223 1245 \reimp 1224 1246 1225 QGraphicsWidget handles the following events: 1247 Handles the \a event. QGraphicsWidget handles the following 1248 events: 1226 1249 1227 1250 \table \o Event \o Usage … … 1279 1302 polishEvent(); 1280 1303 d->polished = true; 1281 d->updateFont(d->font); 1304 if (!d->font.isCopyOf(QApplication::font())) 1305 d->updateFont(d->font); 1282 1306 break; 1283 1307 case QEvent::WindowActivate: 1284 1308 case QEvent::WindowDeactivate: 1285 1309 update(); 1286 foreach (QGraphicsItem *child, childItems()) {1287 if (child->isWidget())1288 QApplication::sendEvent(static_cast<QGraphicsWidget *>(child), event);1289 }1290 1310 break; 1291 1311 // Taken from QWidget::event … … 1321 1341 case QEvent::GraphicsSceneMouseRelease: 1322 1342 case QEvent::GraphicsSceneMouseDoubleClick: 1323 if (d->hasDecoration() && d->grabbedSection != Qt::NoSection) 1343 d->ensureWindowData(); 1344 if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection) 1324 1345 return windowFrameEvent(event); 1325 1346 break; … … 1358 1379 // ### Don't unset if the margins are explicitly set. 1359 1380 unsetWindowFrameMargins(); 1381 if (d->layout) 1382 d->layout->invalidate(); 1360 1383 case QEvent::FontChange: 1361 1384 update(); … … 1596 1619 /*! 1597 1620 Returns the widgets window type. 1621 1622 \sa windowFlags(), isWindow(), isPanel() 1598 1623 */ 1599 1624 Qt::WindowType QGraphicsWidget::windowType() const … … 1611 1636 1612 1637 By default, this property contains no window flags. 1638 1639 Windows are panels. If you set the Qt::Window flag, the ItemIsPanel flag 1640 will be set automatically. If you clear the Qt::Window flag, the 1641 ItemIsPanel flag is also cleared. Note that the ItemIsPanel flag can be 1642 set independently of Qt::Window. 1643 1644 \sa isWindow(), isPanel() 1613 1645 */ 1614 1646 Qt::WindowFlags QGraphicsWidget::windowFlags() const … … 1624 1656 bool wasPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup; 1625 1657 1658 d->adjustWindowFlags(&wFlags); 1626 1659 d->windowFlags = wFlags; 1627 1660 if (!d->setWindowFrameMargins) 1628 1661 unsetWindowFrameMargins(); 1662 1663 setFlag(ItemIsPanel, d->windowFlags & Qt::Window); 1629 1664 1630 1665 bool isPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup; … … 1636 1671 d->scene->d_func()->addPopup(this); 1637 1672 } 1673 1674 if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) { 1675 d->scene->d_func()->allItemsIgnoreHoverEvents = false; 1676 d->scene->d_func()->enableMouseTrackingOnViews(); 1677 } 1638 1678 } 1639 1679 … … 1646 1686 currently has input focus, or that itself has input focus. 1647 1687 1648 \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow() 1688 \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow(), isActive() 1649 1689 */ 1650 1690 bool QGraphicsWidget::isActiveWindow() const 1651 1691 { 1652 Q_D(const QGraphicsWidget); 1653 if (!d->scene) 1654 return false; 1655 const QGraphicsWidget *w = window(); 1656 return (!w && d->scene->d_func()->activationRefCount) || (w && d->scene->activeWindow() == w); 1692 return isActive(); 1657 1693 } 1658 1694 … … 1663 1699 This property is only used for windows. 1664 1700 1665 By default, if no title has been set, this property contains an empty string. 1701 By default, if no title has been set, this property contains an 1702 empty string. 1666 1703 */ 1667 1704 void QGraphicsWidget::setWindowTitle(const QString &title) 1668 1705 { 1669 1706 Q_D(QGraphicsWidget); 1670 d->windowTitle = title; 1707 d->ensureWindowData(); 1708 d->windowData->windowTitle = title; 1671 1709 } 1672 1710 QString QGraphicsWidget::windowTitle() const 1673 1711 { 1674 1712 Q_D(const QGraphicsWidget); 1675 return d->window Title;1713 return d->windowData ? d->windowData->windowTitle : QString(); 1676 1714 } 1677 1715 … … 1715 1753 If this widget, a child or descendant of this widget currently has input 1716 1754 focus, this function will return a pointer to that widget. If 1717 no descendant has input focus, 0 is returned.1718 1719 \sa Q Widget::focusWidget()1755 no descendant widget has input focus, 0 is returned. 1756 1757 \sa QGraphicsItem::focusItem(), QWidget::focusWidget() 1720 1758 */ 1721 1759 QGraphicsWidget *QGraphicsWidget::focusWidget() const 1722 1760 { 1723 1761 Q_D(const QGraphicsWidget); 1724 return d->focusChild; 1725 } 1726 1762 if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget) 1763 return static_cast<QGraphicsWidget *>(d->subFocusItem); 1764 return 0; 1765 } 1727 1766 1728 1767 #ifndef QT_NO_SHORTCUT … … 1888 1927 d->actions.insert(pos, action); 1889 1928 1890 QActionPrivate *apriv = action->d_func(); 1891 apriv->graphicsWidgets.append(this); 1929 if (index == -1) { 1930 QActionPrivate *apriv = action->d_func(); 1931 apriv->graphicsWidgets.append(this); 1932 } 1892 1933 1893 1934 QActionEvent e(QEvent::ActionAdded, action, before); … … 2109 2150 bar.QStyleOption::operator=(*option); 2110 2151 d->initStyleOptionTitleBar(&bar); // this clear flags in bar.state 2111 if (d->buttonMouseOver) 2152 d->ensureWindowData(); 2153 if (d->windowData->buttonMouseOver) 2112 2154 bar.state |= QStyle::State_MouseOver; 2113 2155 else 2114 2156 bar.state &= ~QStyle::State_MouseOver; 2115 if (d-> buttonSunken)2157 if (d->windowData->buttonSunken) 2116 2158 bar.state |= QStyle::State_Sunken; 2117 2159 else … … 2248 2290 /*! 2249 2291 \fn const QObjectList &QGraphicsWidget::children() const 2292 \internal 2250 2293 2251 2294 This function returns the same value as QObject::children(). It's … … 2268 2311 break; 2269 2312 } 2270 qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? "1" : "0") << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0);2313 qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? '1' : '0') << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0); 2271 2314 if (visited.contains(next)) { 2272 2315 qWarning("Already visited this node. However, I expected to dump until I found myself."); -
trunk/src/gui/graphicsview/qgraphicswidget.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 67 67 class QGraphicsWidgetPrivate; 68 68 69 class Q_GUI_EXPORT QGraphicsWidget : public Q Object, public QGraphicsItem, public QGraphicsLayoutItem69 class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLayoutItem 70 70 { 71 71 Q_OBJECT 72 Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem) 72 73 Q_PROPERTY(QPalette palette READ palette WRITE setPalette) 73 74 Q_PROPERTY(QFont font READ font WRITE setFont) 74 75 Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection) 75 76 Q_PROPERTY(QSizeF size READ size WRITE resize) 77 Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize) 78 Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize) 79 Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize) 80 Q_PROPERTY(QSizePolicy sizePolicy READ sizePolicy WRITE setSizePolicy) 76 81 Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy) 77 Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)78 Q_PROPERTY(bool visible READ isVisible WRITE setVisible)79 82 Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags) 80 83 Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) 81 Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)82 Q_PROPERTY(QPointF pos READ pos WRITE setPos)83 84 Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry) 84 85 85 public: 86 86 QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); … … 226 226 private: 227 227 Q_DISABLE_COPY(QGraphicsWidget) 228 Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr , QGraphicsWidget)228 Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsWidget) 229 229 friend class QGraphicsScene; 230 230 friend class QGraphicsScenePrivate; -
trunk/src/gui/graphicsview/qgraphicswidget_p.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 67 67 focusNext = focusPrev = q; 68 68 focusPolicy = Qt::NoFocus; 69 70 adjustWindowFlags(&wFlags); 71 windowFlags = wFlags; 72 69 73 q->setParentItem(parentItem); 70 74 q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType)); … … 72 76 73 77 resolveLayoutDirection(); 74 75 if (!parentItem)76 adjustWindowFlags(&wFlags);77 windowFlags = wFlags;78 78 q->unsetWindowFrameMargins(); 79 } 79 q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); 80 q->setFlag(QGraphicsItem::ItemSendsGeometryChanges); 81 } 82 80 83 qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const 81 84 { … … 90 93 } 91 94 92 void QGraphicsWidgetPrivate::getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const 93 { 94 if (left) 95 *left = leftLayoutItemMargin; 96 if (top) 97 *top = topLayoutItemMargin; 98 if (right) 99 *right = rightLayoutItemMargin; 100 if (bottom) 101 *bottom = bottomLayoutItemMargin; 102 } 103 104 void QGraphicsWidgetPrivate::setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom) 105 { 106 if (leftLayoutItemMargin == left 107 && topLayoutItemMargin == top 108 && rightLayoutItemMargin == right 109 && bottomLayoutItemMargin == bottom) 110 return; 111 112 Q_Q(QGraphicsWidget); 113 leftLayoutItemMargin = left; 114 topLayoutItemMargin = top; 115 rightLayoutItemMargin = right; 116 bottomLayoutItemMargin = bottom; 117 q->updateGeometry(); 118 } 119 120 void QGraphicsWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt) 121 { 122 Q_Q(QGraphicsWidget); 123 QStyleOption myOpt; 124 if (!opt) { 125 q->initStyleOption(&myOpt); 126 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary 127 opt = &myOpt; 128 } 129 130 QRect liRect = q->style()->subElementRect(element, opt, /* q */ 0); 131 if (liRect.isValid()) { 132 leftLayoutItemMargin = (opt->rect.left() - liRect.left()); 133 topLayoutItemMargin = (opt->rect.top() - liRect.top()); 134 rightLayoutItemMargin = (liRect.right() - opt->rect.right()); 135 bottomLayoutItemMargin = (liRect.bottom() - opt->rect.bottom()); 136 } else { 137 leftLayoutItemMargin = 0; 138 topLayoutItemMargin = 0; 139 rightLayoutItemMargin = 0; 140 bottomLayoutItemMargin = 0; 141 } 95 /*! 96 \internal 97 */ 98 QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate() 99 { 100 // Remove any lazily allocated data 101 delete[] margins; 102 delete[] windowFrameMargins; 103 delete windowData; 104 } 105 106 /*! 107 \internal 108 109 Ensures that margins is allocated. 110 This function must be called before any dereferencing. 111 */ 112 void QGraphicsWidgetPrivate::ensureMargins() const 113 { 114 if (!margins) { 115 margins = new qreal[4]; 116 for (int i = 0; i < 4; ++i) 117 margins[i] = 0; 118 } 119 } 120 121 /*! 122 \internal 123 124 Ensures that windowFrameMargins is allocated. 125 This function must be called before any dereferencing. 126 */ 127 void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const 128 { 129 if (!windowFrameMargins) { 130 windowFrameMargins = new qreal[4]; 131 for (int i = 0; i < 4; ++i) 132 windowFrameMargins[i] = 0; 133 } 134 } 135 136 /*! 137 \internal 138 139 Ensures that windowData is allocated. 140 This function must be called before any dereferencing. 141 */ 142 void QGraphicsWidgetPrivate::ensureWindowData() 143 { 144 if (!windowData) 145 windowData = new WindowData; 142 146 } 143 147 … … 298 302 { 299 303 Q_Q(QGraphicsWidget); 304 ensureWindowData(); 300 305 q->initStyleOption(option); 301 306 option->rect.setHeight(titleBarHeight(*option)); 302 307 option->titleBarFlags = windowFlags; 303 308 option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu; 304 option->activeSubControls = hoveredSubControl;309 option->activeSubControls = windowData->hoveredSubControl; 305 310 bool isActive = q->isActiveWindow(); 306 311 if (isActive) { … … 314 319 QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar"); 315 320 QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0); 316 option->text = QFontMetrics(windowTitleFont).elidedText(windowTitle, Qt::ElideRight, textRect.width()); 321 option->text = QFontMetrics(windowTitleFont).elidedText( 322 windowData->windowTitle, Qt::ElideRight, textRect.width()); 317 323 } 318 324 … … 342 348 { 343 349 Q_Q(QGraphicsWidget); 344 if (grabbedSection != Qt::NoSection) { 345 if (grabbedSection == Qt::TitleBarArea) { 346 buttonSunken = false; 350 ensureWindowData(); 351 if (windowData->grabbedSection != Qt::NoSection) { 352 if (windowData->grabbedSection == Qt::TitleBarArea) { 353 windowData->buttonSunken = false; 347 354 QStyleOptionTitleBar bar; 348 355 initStyleOptionTitleBar(&bar); … … 352 359 bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar)); 353 360 QPointF pos = event->pos(); 354 pos.rx() += leftWindowFrameMargin; 355 pos.ry() += topWindowFrameMargin; 361 if (windowFrameMargins) { 362 pos.rx() += windowFrameMargins[Left]; 363 pos.ry() += windowFrameMargins[Top]; 364 } 356 365 bar.subControls = QStyle::SC_TitleBarCloseButton; 357 366 if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar, … … 362 371 } 363 372 if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons())) 364 grabbedSection = Qt::NoSection;373 windowData->grabbedSection = Qt::NoSection; 365 374 event->accept(); 366 375 } … … 373 382 return; 374 383 375 startGeometry = q->geometry(); 376 grabbedSection = q->windowFrameSectionAt(event->pos()); 377 switch (grabbedSection) { 378 case Qt::LeftSection: 379 case Qt::TopLeftSection: 380 mouseDelta = event->pos() - q->rect().topLeft(); 381 break; 382 case Qt::TopSection: 383 case Qt::TopRightSection: 384 mouseDelta = event->pos() - q->rect().topRight(); 385 break; 386 case Qt::RightSection: 387 case Qt::BottomRightSection: 388 mouseDelta = event->pos() - q->rect().bottomRight(); 389 break; 390 case Qt::BottomSection: 391 case Qt::BottomLeftSection: 392 mouseDelta = event->pos() - q->rect().bottomLeft(); 393 break; 394 case Qt::TitleBarArea: 395 if (hoveredSubControl == QStyle::SC_TitleBarCloseButton) { 396 buttonSunken = true; 397 q->update(); 398 } 399 break; 400 case Qt::NoSection: 401 break; 402 } 403 event->setAccepted(grabbedSection != Qt::NoSection); 384 ensureWindowData(); 385 windowData->startGeometry = q->geometry(); 386 windowData->grabbedSection = q->windowFrameSectionAt(event->pos()); 387 ensureWindowData(); 388 if (windowData->grabbedSection == Qt::TitleBarArea 389 && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) { 390 windowData->buttonSunken = true; 391 q->update(); 392 } 393 event->setAccepted(windowData->grabbedSection != Qt::NoSection); 394 } 395 396 /*! 397 Used to calculate the 398 Precondition: 399 \a widget should support either hfw or wfh 400 401 If \a heightForWidth is set to false, this function will query the width for height 402 instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted 403 as minimum width and maximum width. 404 */ 405 static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh, 406 const QGraphicsWidget *widget, 407 bool heightForWidth = true) 408 { 409 qreal minimumHeightForWidth = -1; 410 const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy(); 411 const bool hasHFW = sp.hasHeightForWidth(); 412 if (hasHFW == heightForWidth) { 413 minimumHeightForWidth = hasHFW 414 ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height() 415 : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width(); //"width" is here height! 416 } else { 417 // widthForHeight 418 const qreal constraint = width; 419 while (maxh - minh > 0.1) { 420 qreal middle = minh + (maxh - minh)/2; 421 // ### really bad, if we are a widget with a layout it will call 422 // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call 423 // sizeHint three times because of how the cache works 424 qreal hfw = hasHFW 425 ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height() 426 : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width(); 427 if (hfw > constraint) { 428 minh = middle; 429 } else if (hfw <= constraint) { 430 maxh = middle; 431 } 432 } 433 minimumHeightForWidth = maxh; 434 } 435 return minimumHeightForWidth; 436 } 437 438 static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw, 439 const QGraphicsWidget *widget) 440 { 441 return minimumHeightForWidth(height, minw, maxw, widget, false); 442 } 443 444 static QSizeF closestAcceptableSize(const QSizeF &proposed, 445 const QGraphicsWidget *widget) 446 { 447 const QSizeF current = widget->size(); 448 449 qreal minw = proposed.width(); 450 qreal maxw = current.width(); 451 qreal minh = proposed.height(); 452 qreal maxh = current.height(); 453 454 qreal middlew = maxw; 455 qreal middleh = maxh; 456 qreal min_hfw; 457 min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget); 458 459 do { 460 if (maxw - minw < 0.1) { 461 // we still havent found anything, cut off binary search 462 minw = maxw; 463 minh = maxh; 464 } 465 middlew = minw + (maxw - minw)/2.0; 466 middleh = minh + (maxh - minh)/2.0; 467 468 min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget); 469 470 if (min_hfw > middleh) { 471 minw = middlew; 472 minh = middleh; 473 } else if (min_hfw <= middleh) { 474 maxw = middlew; 475 maxh = middleh; 476 } 477 } while (maxw != minw); 478 479 min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget); 480 481 QSizeF result; 482 if (min_hfw < maxh) { 483 result = QSizeF(middlew, min_hfw); 484 } else { 485 // Needed because of the cut-off we do above. 486 result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh); 487 } 488 return result; 404 489 } 405 490 406 491 static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry, 407 492 QRectF *rect, Qt::WindowFrameSection section, 408 const QSizeF &min, const QSizeF &max) 409 { 410 int height; 411 int width; 493 const QSizeF &min, const QSizeF &max, 494 const QGraphicsWidget *widget) 495 { 496 const QRectF proposedRect = *rect; 497 qreal width = qBound(min.width(), proposedRect.width(), max.width()); 498 qreal height = qBound(min.height(), proposedRect.height(), max.height()); 499 500 QSizePolicy sp = widget->sizePolicy(); 501 if (const QGraphicsLayout *l = widget->layout()) { 502 sp = l->sizePolicy(); 503 } 504 const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight(); 505 506 const bool widthChanged = proposedRect.width() < widget->size().width(); 507 const bool heightChanged = proposedRect.height() < widget->size().height(); 508 509 if (hasHFW) { 510 if (widthChanged || heightChanged) { 511 const qreal minh = min.height(); 512 const qreal maxh = max.height(); 513 const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget); 514 if (proposedHFW > proposedRect.height()) { 515 QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget); 516 width = effectiveSize.width(); 517 height = effectiveSize.height(); 518 } 519 } 520 } 521 412 522 switch (section) { 413 523 case Qt::LeftSection: 414 width = qRound(qBound(min.width(), rect->width(), max.width())); 415 rect->setRect(startGeometry.right() - width, startGeometry.top(), 416 width, startGeometry.height()); 524 rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(), 525 qRound(width), startGeometry.height()); 417 526 break; 418 527 case Qt::TopLeftSection: 419 width = qRound(qBound(min.width(), rect->width(), max.width())); 420 height = qRound(qBound(min.height(), rect->height(), max.height())); 421 rect->setRect(startGeometry.right() - width, startGeometry.bottom() - height, 422 width, height); 528 rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height), 529 qRound(width), qRound(height)); 423 530 break; 424 531 case Qt::TopSection: 425 height = qRound(qBound(min.height(), rect->height(), max.height())); 426 rect->setRect(startGeometry.left(), startGeometry.bottom() - height, 427 startGeometry.width(), height); 532 rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height), 533 startGeometry.width(), qRound(height)); 428 534 break; 429 535 case Qt::TopRightSection: 430 height = qRound(qBound(min.height(), rect->height(), max.height())); 431 rect->setTop(rect->bottom() - height); 432 rect->setWidth(qBound(min.width(), rect->width(), max.width())); 536 rect->setTop(rect->bottom() - qRound(height)); 537 rect->setWidth(qRound(width)); 433 538 break; 434 539 case Qt::RightSection: 435 rect->setWidth(q Bound(min.width(), rect->width(), max.width()));540 rect->setWidth(qRound(width)); 436 541 break; 437 542 case Qt::BottomRightSection: 438 rect->setWidth(q Bound(min.width(), rect->width(), max.width()));439 rect->setHeight(q Bound(min.height(), rect->height(), max.height()));543 rect->setWidth(qRound(width)); 544 rect->setHeight(qRound(height)); 440 545 break; 441 546 case Qt::BottomSection: 442 rect->setHeight(q Bound(min.height(), rect->height(), max.height()));547 rect->setHeight(qRound(height)); 443 548 break; 444 549 case Qt::BottomLeftSection: 445 height = qRound(qBound(min.height(), rect->height(), max.height())); 446 width = qRound(qBound(min.width(), rect->width(), max.width())); 447 rect->setRect(startGeometry.right() - width, startGeometry.top(), 448 width, height); 550 rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(), 551 qRound(width), qRound(height)); 449 552 break; 450 553 default: … … 456 559 { 457 560 Q_Q(QGraphicsWidget); 458 if (!(event->buttons() & Qt::LeftButton) || hoveredSubControl != QStyle::SC_TitleBarLabel) 561 ensureWindowData(); 562 if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel) 459 563 return; 460 564 … … 465 569 466 570 QRectF newGeometry; 467 switch ( grabbedSection) {571 switch (windowData->grabbedSection) { 468 572 case Qt::LeftSection: 469 newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()), 470 startGeometry.size() - QSizeF(delta.dx(), delta.dy())); 573 newGeometry = QRectF(windowData->startGeometry.topLeft() 574 + QPointF(parentXDelta.dx(), parentXDelta.dy()), 575 windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy())); 471 576 break; 472 577 case Qt::TopLeftSection: 473 newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()), 474 startGeometry.size() - QSizeF(delta.dx(), delta.dy())); 578 newGeometry = QRectF(windowData->startGeometry.topLeft() 579 + QPointF(parentDelta.dx(), parentDelta.dy()), 580 windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy())); 475 581 break; 476 582 case Qt::TopSection: 477 newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()), 478 startGeometry.size() - QSizeF(0, delta.dy())); 583 newGeometry = QRectF(windowData->startGeometry.topLeft() 584 + QPointF(parentYDelta.dx(), parentYDelta.dy()), 585 windowData->startGeometry.size() - QSizeF(0, delta.dy())); 479 586 break; 480 587 case Qt::TopRightSection: 481 newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()), 482 startGeometry.size() - QSizeF(-delta.dx(), delta.dy())); 588 newGeometry = QRectF(windowData->startGeometry.topLeft() 589 + QPointF(parentYDelta.dx(), parentYDelta.dy()), 590 windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy())); 483 591 break; 484 592 case Qt::RightSection: 485 newGeometry = QRectF( startGeometry.topLeft(),486 startGeometry.size() + QSizeF(delta.dx(), 0));593 newGeometry = QRectF(windowData->startGeometry.topLeft(), 594 windowData->startGeometry.size() + QSizeF(delta.dx(), 0)); 487 595 break; 488 596 case Qt::BottomRightSection: 489 newGeometry = QRectF( startGeometry.topLeft(),490 startGeometry.size() + QSizeF(delta.dx(), delta.dy()));597 newGeometry = QRectF(windowData->startGeometry.topLeft(), 598 windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy())); 491 599 break; 492 600 case Qt::BottomSection: 493 newGeometry = QRectF( startGeometry.topLeft(),494 startGeometry.size() + QSizeF(0, delta.dy()));601 newGeometry = QRectF(windowData->startGeometry.topLeft(), 602 windowData->startGeometry.size() + QSizeF(0, delta.dy())); 495 603 break; 496 604 case Qt::BottomLeftSection: 497 newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()), 498 startGeometry.size() - QSizeF(delta.dx(), -delta.dy())); 605 newGeometry = QRectF(windowData->startGeometry.topLeft() 606 + QPointF(parentXDelta.dx(), parentXDelta.dy()), 607 windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy())); 499 608 break; 500 609 case Qt::TitleBarArea: 501 newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()), 502 startGeometry.size()); 610 newGeometry = QRectF(windowData->startGeometry.topLeft() 611 + QPointF(parentDelta.dx(), parentDelta.dy()), 612 windowData->startGeometry.size()); 503 613 break; 504 614 case Qt::NoSection: … … 506 616 } 507 617 508 if (grabbedSection != Qt::NoSection) { 509 _q_boundGeometryToSizeConstraints(startGeometry, &newGeometry, grabbedSection, 618 if (windowData->grabbedSection != Qt::NoSection) { 619 _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry, 620 windowData->grabbedSection, 510 621 q->effectiveSizeHint(Qt::MinimumSize), 511 q->effectiveSizeHint(Qt::MaximumSize)); 622 q->effectiveSizeHint(Qt::MaximumSize), 623 q); 512 624 q->setGeometry(newGeometry); 513 625 } … … 520 632 return; 521 633 634 ensureWindowData(); 635 522 636 if (q->rect().contains(event->pos())) { 523 if ( buttonMouseOver ||hoveredSubControl != QStyle::SC_None)637 if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None) 524 638 windowFrameHoverLeaveEvent(event); 525 639 return; 526 640 } 527 641 528 bool wasMouseOver = buttonMouseOver;529 QRect oldButtonRect = buttonRect;530 buttonRect = QRect();531 buttonMouseOver = false;642 bool wasMouseOver = windowData->buttonMouseOver; 643 QRect oldButtonRect = windowData->buttonRect; 644 windowData->buttonRect = QRect(); 645 windowData->buttonMouseOver = false; 532 646 QPointF pos = event->pos(); 533 647 QStyleOptionTitleBar bar; 534 648 // make sure that the coordinates (rect and pos) we send to the style are positive. 535 pos.rx() += leftWindowFrameMargin; 536 pos.ry() += topWindowFrameMargin; 649 if (windowFrameMargins) { 650 pos.rx() += windowFrameMargins[Left]; 651 pos.ry() += windowFrameMargins[Top]; 652 } 537 653 initStyleOptionTitleBar(&bar); 538 654 bar.rect = q->windowFrameRect().toRect(); … … 560 676 break; 561 677 case Qt::TitleBarArea: 562 buttonRect = q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0); 678 windowData->buttonRect = q->style()->subControlRect( 679 QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0); 563 680 #ifdef Q_WS_MAC 564 681 // On mac we should hover if we are in the 'area' of the buttons 565 buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0); 566 buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0); 682 windowData->buttonRect |= q->style()->subControlRect( 683 QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0); 684 windowData->buttonRect |= q->style()->subControlRect( 685 QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0); 567 686 #endif 568 if ( buttonRect.contains(pos.toPoint()))569 buttonMouseOver = true;687 if (windowData->buttonRect.contains(pos.toPoint())) 688 windowData->buttonMouseOver = true; 570 689 event->ignore(); 571 690 break; … … 579 698 #endif 580 699 // update buttons if we hover over them 581 hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);582 if ( hoveredSubControl != QStyle::SC_TitleBarCloseButton)583 hoveredSubControl = QStyle::SC_TitleBarLabel;584 585 if ( buttonMouseOver != wasMouseOver) {700 windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0); 701 if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton) 702 windowData->hoveredSubControl = QStyle::SC_TitleBarLabel; 703 704 if (windowData->buttonMouseOver != wasMouseOver) { 586 705 if (!oldButtonRect.isNull()) 587 706 q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft())); 588 if (! buttonRect.isNull())589 q->update(QRectF( buttonRect).translated(q->windowFrameRect().topLeft()));707 if (!windowData->buttonRect.isNull()) 708 q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft())); 590 709 } 591 710 } … … 601 720 #endif 602 721 722 ensureWindowData(); 723 603 724 bool needsUpdate = false; 604 if (hoveredSubControl == QStyle::SC_TitleBarCloseButton || buttonMouseOver) 725 if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton 726 || windowData->buttonMouseOver) 605 727 needsUpdate = true; 606 728 607 729 // update the hover state (of buttons etc...) 608 hoveredSubControl = QStyle::SC_None;609 buttonMouseOver = false;610 buttonRect = QRect();730 windowData->hoveredSubControl = QStyle::SC_None; 731 windowData->buttonMouseOver = false; 732 windowData->buttonRect = QRect(); 611 733 if (needsUpdate) 612 q->update( buttonRect);734 q->update(windowData->buttonRect); 613 735 } 614 736 } … … 617 739 { 618 740 return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint); 619 }620 621 /*!622 \internal623 */624 void QGraphicsWidgetPrivate::setFocusWidget()625 {626 // Update focus child chain.627 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);628 QGraphicsWidget *parent = widget;629 bool hidden = !visible;630 do {631 parent->d_func()->focusChild = widget;632 } while (!parent->isWindow() && (parent = parent->parentWidget()) && (!hidden || !parent->d_func()->visible));633 }634 635 /*!636 \internal637 */638 void QGraphicsWidgetPrivate::clearFocusWidget()639 {640 // Reset focus child chain.641 QGraphicsWidget *parent = static_cast<QGraphicsWidget *>(q_ptr);642 do {643 if (parent->d_func()->focusChild != q_ptr)644 break;645 parent->d_func()->focusChild = 0;646 } while (!parent->isWindow() && (parent = parent->parentWidget()));647 741 } 648 742 … … 650 744 * is called after a reparent has taken place to fix up the focus chain(s) 651 745 */ 652 void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene * newScene)746 void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene) 653 747 { 654 748 Q_Q(QGraphicsWidget); … … 663 757 QGraphicsWidget *firstOld = 0; 664 758 bool wasPreviousNew = true; 665 666 if (focusChild) {667 // Ensure that the current focus child doesn't leave pointers around668 // before reparenting.669 focusChild->clearFocus();670 }671 759 672 760 while (w != q) { … … 702 790 if (newParent) 703 791 newScene = newParent->scene(); 704 QGraphicsScene *oldScene = q->scene(); 792 705 793 if (oldScene && newScene != oldScene) 706 794 oldScene->d_func()->tabFocusFirst = firstOld; -
trunk/src/gui/graphicsview/qgraphicswidget_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 // 49 49 // This file is not part of the Qt API. It exists for the convenience 50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header51 // file may change from version toversion without notice, or even be removed.50 // of other Qt classes. This header file may change from version to 51 // version without notice, or even be removed. 52 52 // 53 53 // We mean it. … … 69 69 #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW 70 70 71 class Q _GUI_EXPORT QGraphicsWidgetPrivate : public QGraphicsItemPrivate71 class QGraphicsWidgetPrivate : public QGraphicsItemPrivate 72 72 { 73 73 Q_DECLARE_PUBLIC(QGraphicsWidget) 74 74 public: 75 75 QGraphicsWidgetPrivate() 76 : leftMargin(0), 77 topMargin(0), 78 rightMargin(0), 79 bottomMargin(0), 80 leftLayoutItemMargin(0), 81 topLayoutItemMargin(0), 82 rightLayoutItemMargin(0), 83 bottomLayoutItemMargin(0), 76 : margins(0), 84 77 layout(0), 85 78 inheritedPaletteResolveMask(0), … … 91 84 focusNext(0), 92 85 focusPrev(0), 93 focusChild(0),94 86 windowFlags(0), 95 hoveredSubControl(QStyle::SC_None), 96 grabbedSection(Qt::NoSection), 97 buttonMouseOver(false), 98 buttonSunken(false), 87 windowData(0), 99 88 setWindowFrameMargins(false), 100 leftWindowFrameMargin(0), 101 topWindowFrameMargin(0), 102 rightWindowFrameMargin(0), 103 bottomWindowFrameMargin(0) 89 windowFrameMargins(0) 104 90 { } 91 virtual ~QGraphicsWidgetPrivate(); 105 92 106 93 void init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags); … … 108 95 109 96 // Margins 110 qreal leftMargin; 111 qreal topMargin; 112 qreal rightMargin; 113 qreal bottomMargin; 114 QRectF contentsRect; 115 116 // Layout item margins 117 void getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const; 118 void setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom); 119 void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0); 120 121 void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene = 0); 97 enum {Left, Top, Right, Bottom}; 98 mutable qreal *margins; 99 void ensureMargins() const; 100 101 void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene = 0); 122 102 void setLayout_helper(QGraphicsLayout *l); 123 124 qreal leftLayoutItemMargin;125 qreal topLayoutItemMargin;126 qreal rightLayoutItemMargin;127 qreal bottomLayoutItemMargin;128 103 129 104 // Layouts … … 203 178 QGraphicsWidget *focusNext; 204 179 QGraphicsWidget *focusPrev; 205 QGraphicsWidget *focusChild;206 void setFocusWidget();207 void clearFocusWidget();208 180 209 181 // Windows 210 182 Qt::WindowFlags windowFlags; 211 QString windowTitle; 212 QStyle::SubControl hoveredSubControl; 213 Qt::WindowFrameSection grabbedSection; 214 uint buttonMouseOver : 1; 215 uint buttonSunken : 1; 216 QPointF mouseDelta; // to compensate for small error when interactively resizing 217 QRectF startGeometry; 218 QRect buttonRect; 183 struct WindowData { 184 QString windowTitle; 185 QStyle::SubControl hoveredSubControl; 186 Qt::WindowFrameSection grabbedSection; 187 uint buttonMouseOver : 1; 188 uint buttonSunken : 1; 189 QRectF startGeometry; 190 QRect buttonRect; 191 WindowData() 192 : hoveredSubControl(QStyle::SC_None) 193 , grabbedSection(Qt::NoSection) 194 , buttonMouseOver(false) 195 , buttonSunken(false) 196 {} 197 } *windowData; 198 void ensureWindowData(); 219 199 220 200 bool setWindowFrameMargins; 221 qreal leftWindowFrameMargin; 222 qreal topWindowFrameMargin; 223 qreal rightWindowFrameMargin; 224 qreal bottomWindowFrameMargin; 201 mutable qreal *windowFrameMargins; 202 void ensureWindowFrameMargins() const; 225 203 226 204 #ifndef QT_NO_ACTION -
trunk/src/gui/graphicsview/qgridlayoutengine.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 52 52 53 53 #include <QtDebug> 54 #include <QtCore/qmath.h> 54 55 55 56 QT_BEGIN_NAMESPACE … … 71 72 { 72 73 Q_ASSERT(sumDesired != 0.0); 73 return desired * ::pow(sumAvailable / sumDesired, desired / sumDesired);74 return desired * qPow(sumAvailable / sumDesired, desired / sumDesired); 74 75 } 75 76 … … 276 277 factors[i] = (stretch < 0) ? 1.0 : 0.0; 277 278 } else { 278 factors[i] = (stretch < 0) ? sizes[i] : 0.0; 279 factors[i] = (stretch < 0) ? sizes[i] : 0.0; 279 280 } 280 281 } else if (stretch == sumStretches) { … … 462 463 QGridLayoutItem::QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem, 463 464 int row, int column, int rowSpan, int columnSpan, 464 Qt::Alignment alignment )465 Qt::Alignment alignment, int itemAtIndex) 465 466 : q_engine(engine), q_layoutItem(layoutItem), q_alignment(alignment) 466 467 { … … 472 473 q_stretches[Ver] = -1; 473 474 474 q_engine-> addItem(this);475 q_engine->insertItem(this, itemAtIndex); 475 476 } 476 477 … … 616 617 width = size.width(); 617 618 height = size.height(); 618 619 619 620 Qt::Alignment align = q_engine->effectiveAlignment(this); 620 621 switch (align & Qt::AlignHorizontal_Mask) { … … 718 719 { 719 720 count += delta; 720 721 721 722 insertOrRemoveItems(stretches, row, delta); 722 723 insertOrRemoveItems(spacings, row, delta); … … 938 939 } 939 940 940 void QGridLayoutEngine::addItem(QGridLayoutItem *item) 941 /*! 942 \internal 943 The \a index is only used by QGraphicsLinearLayout to ensure that itemAt() reflects the order 944 of visual arrangement. Strictly speaking it does not have to, but most people expect it to. 945 (And if it didn't we would have to add itemArrangedAt(int index) or something..) 946 */ 947 void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index) 941 948 { 942 949 maybeExpandGrid(item->lastRow(), item->lastColumn()); 943 950 944 q_items.append(item); 951 if (index == -1) 952 q_items.append(item); 953 else 954 q_items.insert(index, item); 945 955 946 956 for (int i = item->firstRow(); i <= item->lastRow(); ++i) { … … 951 961 } 952 962 } 963 } 964 965 void QGridLayoutEngine::addItem(QGridLayoutItem *item) 966 { 967 insertItem(item, -1); 953 968 } 954 969 … … 1077 1092 } 1078 1093 return QSizeF(); 1079 } 1094 } 1080 1095 1081 1096 QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const … … 1132 1147 for (int column = 0; column < internalGridColumnCount(); ++column) { 1133 1148 message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3); 1134 message += QLatin1 String(" ");1135 } 1136 message += QLatin1 String("]");1149 message += QLatin1Char(' '); 1150 } 1151 message += QLatin1Char(']'); 1137 1152 qDebug("%*s %s", indent, "", qPrintable(message)); 1138 1153 } … … 1151 1166 1152 1167 qDebug("%*s Geometries output", indent, ""); 1168 QVector<qreal> *cellPos = &q_yy; 1153 1169 for (int pass = 0; pass < 2; ++pass) { 1154 QVector<qreal> &cellPos = q_yy;1155 1170 QString message; 1156 for (i = 0; i < cellPos .count(); ++i) {1171 for (i = 0; i < cellPos->count(); ++i) { 1157 1172 message += QLatin1String((message.isEmpty() ? "[" : ", ")); 1158 message += QString::number(cellPos .at(i));1159 } 1160 message += QLatin1 String("]");1173 message += QString::number(cellPos->at(i)); 1174 } 1175 message += QLatin1Char(']'); 1161 1176 qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message)); 1162 cellPos = q_xx;1177 cellPos = &q_xx; 1163 1178 } 1164 1179 } … … 1539 1554 1540 1555 QT_END_NAMESPACE 1541 1556 1542 1557 #endif //QT_NO_GRAPHICSVIEW -
trunk/src/gui/graphicsview/qgridlayoutengine_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 60 60 #include "qpair.h" 61 61 #include "qvector.h" 62 62 #include "qgraphicslayout_p.h" 63 63 #include <float.h> 64 64 … … 129 129 }; 130 130 131 class QLayoutStyleInfo132 {133 public:134 inline QLayoutStyleInfo() { invalidate(); }135 inline QLayoutStyleInfo(QStyle *style, QWidget *widget)136 : q_valid(true), q_style(style), q_widget(widget) {}137 138 inline void invalidate() { q_valid = false; q_style = 0; q_widget = 0; }139 140 inline QStyle *style() const { return q_style; }141 inline QWidget *widget() const { return q_widget; }142 143 inline bool operator==(const QLayoutStyleInfo &other)144 { return q_style == other.q_style && q_widget == other.q_widget; }145 inline bool operator!=(const QLayoutStyleInfo &other)146 { return !(*this == other); }147 148 private:149 bool q_valid;150 QStyle *q_style;151 QWidget *q_widget;152 };153 154 131 class QGridLayoutBox 155 132 { … … 268 245 public: 269 246 QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem, int row, int column, 270 int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0); 247 int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0, 248 int itemAtIndex = -1); 271 249 272 250 inline int firstRow() const { return q_firstRows[Ver]; } … … 379 357 380 358 359 void insertItem(QGridLayoutItem *item, int index); 381 360 void addItem(QGridLayoutItem *item); 382 361 void removeItem(QGridLayoutItem *item);
Note:
See TracChangeset
for help on using the changeset viewer.