Changeset 561 for trunk/src/gui/graphicsview/qgraphicsitem.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
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/qgraphicsitem.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information ([email protected]) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation ([email protected]) 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 37 ** @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 \im 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 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 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 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 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 434 435 436 437 438 439 440 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 468 e 469 470 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 573 574 575 576 577 578 449 579 */ 450 580 … … 492 622 */ 493 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 494 640 #include "qgraphicsitem.h" 495 641 … … 502 648 #include "qgraphicswidget.h" 503 649 #include "qgraphicsproxywidget.h" 650 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 666 518 667 519 668 #include <private/qgraphicsitem_p.h> … … 522 671 #include <private/qtextdocumentlayout_p.h> 523 672 #include <private/qtextengine_p.h> 673 674 675 676 677 678 679 680 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 748 749 750 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 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 784 1248 Empty all cached pixmaps from the pixmap cache. 785 1249 */ … … 787 1251 { 788 1252 QPixmapCache::remove(key); 1253 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 1321 853 1322 */ 854 1323 QGraphicsItem::~QGraphicsItem() 855 1324 { 1325 1326 1327 1328 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(), child() 935 1424 */ 936 1425 QGraphicsItem *QGraphicsItem::parentItem() const … … 955 1444 956 1445 /*! 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 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 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 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 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 1615 1616 1617 1618 1619 1620 1621 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 1688 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 1697 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 ); 1701 bool fullUpdate = ( & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask); 1230 1702 if (fullUpdate) 1231 d_ptr-> fullUpdateHelper(false, true);1703 d_ptr->; 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 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1350 1925 #ifndef QT_NO_TOOLTIP 1351 1926 /*! … … 1416 1991 d_ptr->hasCursor = 1; 1417 1992 if (d_ptr->scene) { 1993 1418 1994 foreach (QGraphicsView *view, d_ptr->scene->views()) { 1995 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 2103 2104 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 2131 1548 2132 } 1549 2133 if (q_ptr->hasFocus() && scene) { 1550 // Hiding the closest non- windowancestor of the focus item2134 // Hiding the closest non- 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->is()) { 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->is()); 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 2173 2174 2175 2176 2177 2178 2179 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 2212 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- 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->is() && 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->is()); 1687 2309 } 1688 2310 if (clear) … … 1700 2322 // Schedule redraw. 1701 2323 if (update) 1702 updateHelper();2324 (); 1703 2325 1704 2326 foreach (QGraphicsItem *child, children) { … … 1709 2331 // Deliver post-change notification. 1710 2332 q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant); 2333 2334 2335 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 () 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, newOpacity); 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 2792 s 2793 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 2805 2050 2806 d_ptr->acceptsHover = quint32(enabled); 2807 2808 2809 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 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 3085 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(), 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 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 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(), (), {The Graphics View Coordinate System} 2313 3336 */ 2314 3337 QPointF QGraphicsItem::pos() const … … 2326 3349 2327 3350 /*! 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 2328 3367 \fn QGraphicsItem::y() const 2329 3368 … … 2332 3371 \sa x() 2333 3372 */ 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 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 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 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->) 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. 3804 3805 \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System} 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 3839 3840 3841 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 3929 3930 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 4022 4023 4024 4025 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 4065 4066 4067 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 (ransform == 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 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 4111 4112 4113 4114 4115 4116 4117 4118 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 4137 4138 4139 4140 4141 4142 4143 4144 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 4163 4164 4165 4166 4167 4168 4169 4170 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 4183 4184 4185 4186 4187 4188 4189 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 4228 sibling (neighboring) items. 2931 4229 2932 4230 The default Z-value is 0. 2933 4231 2934 \sa setZValue() 4232 \sa setZValue() 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() 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, )); 4256 qreal newZ = ); 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 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 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 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; 4460 if (itemd->) 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 4671 4672 4673 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 (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} 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 i 5052 5053 ); 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 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 5284 5285 5286 5287 3956 5288 if (CacheMode(d_ptr->cacheMode) != NoCache) { 5289 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->) 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 5857 if () 5858 ; 5859 return .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 6116 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 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 5052 6455 default: 5053 6456 return false; … … 5189 6592 ensureVisible(). 5190 6593 5191 \sa focusOutEvent(), sceneEvent() 6594 \sa focusOutEvent(), sceneEvent() 5192 6595 */ 5193 6596 void QGraphicsItem::focusInEvent(QFocusEvent *event) 5194 6597 { 5195 6598 Q_UNUSED(event); 6599 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() 5203 6607 */ 5204 6608 void QGraphicsItem::focusOutEvent(QFocusEvent *event) 5205 6609 { 5206 6610 Q_UNUSED(event); 6611 5207 6612 } 5208 6613 … … 5219 6624 { 5220 6625 Q_UNUSED(event); 5221 d_ptr->updateHelper();6626 (); 5222 6627 } 5223 6628 … … 5247 6652 { 5248 6653 Q_UNUSED(event); 5249 d_ptr->updateHelper();6654 (); 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 ( 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() 5587 6992 */ 5588 6993 QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const … … 5600 7005 5601 7006 /*! 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 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()->(this); 5698 7134 } 5699 7135 … … 5713 7149 void QGraphicsItem::prepareGeometryChange() 5714 7150 { 7151 7152 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 (qFuzzy)) 5743 7206 return; 5744 7207 … … 5790 7253 5791 7254 /*! 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 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 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) 7595 9310 { } 7596 9311 … … 7613 9328 bool tabChangesFocus; 7614 9329 9330 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 : QGraphicsparent, scene), dd(new QGraphicsTextItemPrivate) 7631 9349 { 7632 9350 dd->qq = this; … … 7635 9353 setAcceptDrops(true); 7636 9354 setAcceptHoverEvents(true); 9355 7637 9356 } 7638 9357 … … 7649 9368 #endif 7650 9369 ) 7651 : QGraphics Item(parent, scene), dd(new QGraphicsTextItemPrivate)9370 : QGraphicsparent, scene), dd(new QGraphicsTextItemPrivate) 7652 9371 { 7653 9372 dd->qq = this; 7654 9373 setAcceptDrops(true); 7655 9374 setAcceptHoverEvents(true); 9375 7656 9376 } 7657 9377 … … 7743 9463 QTextControl *c = dd->textControl(); 7744 9464 QPalette pal = c->palette(); 9465 7745 9466 pal.setColor(QPalette::Text, col); 7746 9467 c->setPalette(pal); 9468 9469 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 9737 9738 9739 9740 7973 9741 dd->sendControlEvent(event); 7974 9742 } … … 8022 9790 { 8023 9791 dd->sendControlEvent(event); 9792 9793 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. 10032 10033 . 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() & ~); 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 8768 10544 if (!item->pos().isNull()) 8769 10545 newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y()); 10546 10547 10548 10549 10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 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 10587 10588 10589 10590 10591 10592 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 10599 10600 10601 10602 10603 10604 10605 10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 8802 10618 item->d_func()->setIsMemberOfGroup(item->group() != 0); 8803 10619 … … 8856 10672 } 8857 10673 10674 10675 10676 10677 10678 10679 10680 10681 10682 10683 10684 10685 10686 10687 10688 10689 10690 10691 10692 10693 10694 10695 10696 10697 10698 10699 10700 10701 10702 10703 10704 10705 10706 10707 10708 10709 10710 10711 10712 10713 10714 10715 10716 10717 10718 10719 10720 10721 10722 10723 10724 10725 10726 10727 10728 10729 10730 10731 10732 10733 10734 10735 10736 10737 10738 10739 10740 10741 10742 10743 10744 10745 10746 10747 10748 10749 10750 10751 10752 10753 10754 10755 10756 10757 10758 10759 10760 10761 10762 10763 10764 10765 10766 10767 10768 10769 10770 10771 10772 10773 10774 10775 10776 10777 10778 10779 10780 10781 10782 10783 10784 10785 10786 10787 10788 10789 10790 10791 10792 10793 10794 10795 10796 10797 10798 10799 10800 10801 10802 10803 10804 10805 10806 10807 10808 10809 10810 10811 10812 10813 10814 10815 10816 10817 10818 10819 10820 10821 10822 10823 10824 10825 10826 10827 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 << )"; 8877 10846 return debug; 10847 10848 10849 10850 10851 10852 10853 10854 10855 10856 10857 10858 10859 10860 10861 10862 10863 8878 10864 } 8879 10865 … … 8963 10949 str = "ItemOpacityHasChanged"; 8964 10950 break; 10951 10952 10953 8965 10954 } 8966 10955 debug << str; … … 8999 10988 str = "ItemStacksBehindParent"; 9000 10989 break; 10990 10991 10992 10993 10994 10995 10996 10997 10998 10999 11000 11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 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 < ; ++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 }
Note:
See TracChangeset
for help on using the changeset viewer.