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 …