src/gui/graphicsview/qgraphicsitem.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    50     It provides a light-weight foundation for writing your own custom items.
    50     It provides a light-weight foundation for writing your own custom items.
    51     This includes defining the item's geometry, collision detection, its
    51     This includes defining the item's geometry, collision detection, its
    52     painting implementation and item interaction through its event handlers.
    52     painting implementation and item interaction through its event handlers.
    53     QGraphicsItem is part of \l{The Graphics View Framework}
    53     QGraphicsItem is part of \l{The Graphics View Framework}
    54 
    54 
    55     \img graphicsview-items.png
    55     \image graphicsview-items.png
    56 
    56 
    57     For convenience, Qt provides a set of standard graphics items for the most
    57     For convenience, Qt provides a set of standard graphics items for the most
    58     common shapes. These are:
    58     common shapes. These are:
    59 
    59 
    60     \list
    60     \list
   376 
   376 
   377     \value ItemNegativeZStacksBehindParent The item automatically stacks behind
   377     \value ItemNegativeZStacksBehindParent The item automatically stacks behind
   378     it's parent if it's z-value is negative. This flag enables setZValue() to
   378     it's parent if it's z-value is negative. This flag enables setZValue() to
   379     toggle ItemStacksBehindParent.
   379     toggle ItemStacksBehindParent.
   380 
   380 
   381     \value ItemIsPanel. The item is a panel. A panel provides activation and
   381     \value ItemIsPanel The item is a panel. A panel provides activation and
   382     contained focus handling. Only one panel can be active at a time (see
   382     contained focus handling. Only one panel can be active at a time (see
   383     QGraphicsItem::isActive()). When no panel is active, QGraphicsScene
   383     QGraphicsItem::isActive()). When no panel is active, QGraphicsScene
   384     activates all non-panel items. Window items (i.e.,
   384     activates all non-panel items. Window items (i.e.,
   385     QGraphicsItem::isWindow() returns true) are panels. This flag was
   385     QGraphicsItem::isWindow() returns true) are panels. This flag was
   386     introduced in Qt 4.6.
   386     introduced in Qt 4.6.
   387 
   387 
   388     \omitvalue ItemIsFocusScope Internal only (for now).
   388     \omitvalue ItemIsFocusScope \omit Internal only (for now). \endomit
       
   389 
       
   390     \value ItemSendsScenePositionChanges The item enables itemChange()
       
   391     notifications for ItemScenePositionHasChanged. For performance reasons,
       
   392     these notifications are disabled by default. You must enable this flag
       
   393     to receive notifications for scene position changes. This flag was
       
   394     introduced in Qt 4.6.
   389 */
   395 */
   390 
   396 
   391 /*!
   397 /*!
   392     \enum QGraphicsItem::GraphicsItemChange
   398     \enum QGraphicsItem::GraphicsItemChange
   393 
   399 
   560     from itemChange().
   566     from itemChange().
   561 
   567 
   562     \value ItemOpacityHasChanged The item's opacity has changed. The value
   568     \value ItemOpacityHasChanged The item's opacity has changed. The value
   563     argument is the new opacity (i.e., a double). Do not call setOpacity() as
   569     argument is the new opacity (i.e., a double). Do not call setOpacity() as
   564     this notification is delivered. The return value is ignored.
   570     this notification is delivered. The return value is ignored.
       
   571 
       
   572     \value ItemScenePositionHasChanged The item's scene position has changed.
       
   573     This notification is sent if the ItemSendsScenePositionChanges flag is
       
   574     enabled, and after the item's scene position has changed (i.e., the
       
   575     position or transformation of the item itself or the position or
       
   576     transformation of any ancestor has changed). The value argument is the
       
   577     new scene position (the same as scenePos()), and QGraphicsItem ignores
       
   578     the return value for this notification (i.e., a read-only notification).
   565 */
   579 */
   566 
   580 
   567 /*!
   581 /*!
   568     \enum QGraphicsItem::CacheMode
   582     \enum QGraphicsItem::CacheMode
   569     \since 4.4
   583     \since 4.4
   739             enabled = q->handlesChildEvents();
   753             enabled = q->handlesChildEvents();
   740             break;
   754             break;
   741         case QGraphicsItem::ItemClipsChildrenToShape:
   755         case QGraphicsItem::ItemClipsChildrenToShape:
   742             flag = AncestorClipsChildren;
   756             flag = AncestorClipsChildren;
   743             enabled = flags & QGraphicsItem::ItemClipsChildrenToShape;
   757             enabled = flags & QGraphicsItem::ItemClipsChildrenToShape;
   744             invalidateCachedClipPathRecursively(/*childrenOnly=*/true);
       
   745             break;
   758             break;
   746         case QGraphicsItem::ItemIgnoresTransformations:
   759         case QGraphicsItem::ItemIgnoresTransformations:
   747             flag = AncestorIgnoresTransformations;
   760             flag = AncestorIgnoresTransformations;
   748             enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
   761             enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
   749             break;
   762             break;
   988         return;
  1001         return;
   989 
  1002 
   990     if (scene) {
  1003     if (scene) {
   991         // Deliver the change to the index
  1004         // Deliver the change to the index
   992         scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant);
  1005         scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant);
       
  1006 
       
  1007         // Disable scene pos notifications for old ancestors
       
  1008         if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
       
  1009             scene->d_func()->setScenePosItemEnabled(q, false);
   993     }
  1010     }
   994 
  1011 
   995     if (subFocusItem && parent) {
  1012     if (subFocusItem && parent) {
   996         // Make sure none of the old parents point to this guy.
  1013         // Make sure none of the old parents point to this guy.
   997         subFocusItem->d_ptr->clearSubFocus(parent);
  1014         subFocusItem->d_ptr->clearSubFocus(parent);
  1037         }
  1054         }
  1038         p = p->d_ptr->parent;
  1055         p = p->d_ptr->parent;
  1039     }
  1056     }
  1040 
  1057 
  1041     // Update focus scope item ptr in new scope.
  1058     // Update focus scope item ptr in new scope.
  1042     if (newParent) {
  1059     QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
       
  1060     if (newFocusScopeItem && newParent) {
       
  1061         if (subFocusItem) {
       
  1062             // Find the subFocusItem's topmost focus scope.
       
  1063             QGraphicsItem *ancestorScope = 0;
       
  1064             QGraphicsItem *p = subFocusItem->d_ptr->parent;
       
  1065             while (p) {
       
  1066                 if (p->flags() & QGraphicsItem::ItemIsFocusScope)
       
  1067                     ancestorScope = p;
       
  1068                 if (p->isPanel())
       
  1069                     break;
       
  1070                 p = p->parentItem();
       
  1071             }
       
  1072             if (ancestorScope)
       
  1073                 newFocusScopeItem = ancestorScope;
       
  1074         }
       
  1075 
  1043         QGraphicsItem *p = newParent;
  1076         QGraphicsItem *p = newParent;
  1044         while (p) {
  1077         while (p) {
  1045             if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  1078             if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  1046                 p->d_ptr->focusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
  1079                 p->d_ptr->focusScopeItem = newFocusScopeItem;
  1047                 // ### The below line might not make sense...
  1080                 // Ensure the new item is no longer the subFocusItem. The
  1048                 if (subFocusItem)
  1081                 // only way to set focus on a child of a focus scope is
       
  1082                 // by setting focus on the scope itself.
       
  1083                 if (subFocusItem && !p->focusItem())
  1049                     subFocusItem->d_ptr->clearSubFocus();
  1084                     subFocusItem->d_ptr->clearSubFocus();
  1050                 break;
  1085                 break;
  1051             }
  1086             }
  1052             p = p->d_ptr->parent;
  1087             p = p->d_ptr->parent;
  1053         }
  1088         }
  1064             scene->removeItem(q);
  1099             scene->removeItem(q);
  1065         }
  1100         }
  1066 
  1101 
  1067         parent->d_ptr->addChild(q);
  1102         parent->d_ptr->addChild(q);
  1068         parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
  1103         parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
  1069         if (!implicitUpdate && scene) {
  1104         if (scene) {
  1070             scene->d_func()->markDirty(q_ptr, QRect(),
  1105             if (!implicitUpdate)
  1071                                        /*invalidateChildren=*/false,
  1106                 scene->d_func()->markDirty(q_ptr);
  1072                                        /*maybeDirtyClipPath=*/true);
  1107 
       
  1108             // Re-enable scene pos notifications for new ancestors
       
  1109             if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
       
  1110                 scene->d_func()->setScenePosItemEnabled(q, true);
  1073         }
  1111         }
  1074 
  1112 
  1075         // Inherit ancestor flags from the new parent.
  1113         // Inherit ancestor flags from the new parent.
  1076         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
  1114         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
  1077         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
  1115         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
  1104                 setVisibleHelper(true, /* explicit = */ false);
  1142                 setVisibleHelper(true, /* explicit = */ false);
  1105             if (!enabled && !explicitlyDisabled)
  1143             if (!enabled && !explicitlyDisabled)
  1106                 setEnabledHelper(true, /* explicit = */ false);
  1144                 setEnabledHelper(true, /* explicit = */ false);
  1107 
  1145 
  1108             // If the item is being deleted, the whole scene will be updated.
  1146             // If the item is being deleted, the whole scene will be updated.
  1109             if (scene) {
  1147             if (scene)
  1110                 scene->d_func()->markDirty(q_ptr, QRect(),
  1148                 scene->d_func()->markDirty(q_ptr);
  1111                                            /*invalidateChildren=*/false,
       
  1112                                            /*maybeDirtyClipPath=*/true);
       
  1113             }
       
  1114         }
  1149         }
  1115     }
  1150     }
  1116 
  1151 
  1117     // Resolve depth.
  1152     // Resolve depth.
  1118     invalidateDepthRecursively();
  1153     invalidateDepthRecursively();
  1197         // Determine the item's exposed area
  1232         // Determine the item's exposed area
  1198         option->exposedRect = QRectF();
  1233         option->exposedRect = QRectF();
  1199         const QTransform reverseMap = worldTransform.inverted();
  1234         const QTransform reverseMap = worldTransform.inverted();
  1200         const QVector<QRect> exposedRects(exposedRegion.rects());
  1235         const QVector<QRect> exposedRects(exposedRegion.rects());
  1201         for (int i = 0; i < exposedRects.size(); ++i) {
  1236         for (int i = 0; i < exposedRects.size(); ++i) {
  1202             option->exposedRect |= reverseMap.mapRect(exposedRects.at(i));
  1237             option->exposedRect |= reverseMap.mapRect(QRectF(exposedRects.at(i)));
  1203             if (option->exposedRect.contains(brect))
  1238             if (option->exposedRect.contains(brect))
  1204                 break;
  1239                 break;
  1205         }
  1240         }
  1206         option->exposedRect &= brect;
  1241         option->exposedRect &= brect;
  1207     }
  1242     }
  1226     allExposed = true;
  1261     allExposed = true;
  1227     exposed.clear();
  1262     exposed.clear();
  1228 }
  1263 }
  1229 
  1264 
  1230 /*!
  1265 /*!
  1231     Constructs a QGraphicsItem, passing \a item to QGraphicsItem's constructor. It does not modify \fn QObject::parent().
  1266     Constructs a QGraphicsItem with the given \a parent item.
       
  1267     It does not modify the parent object returned by QObject::parent().
  1232 
  1268 
  1233     If \a parent is 0, you can add the item to a scene by calling
  1269     If \a parent is 0, you can add the item to a scene by calling
  1234     QGraphicsScene::addItem(). The item will then become a top-level item.
  1270     QGraphicsScene::addItem(). The item will then become a top-level item.
  1235 
  1271 
  1236     \sa QGraphicsScene::addItem(), setParentItem()
  1272     \sa QGraphicsScene::addItem(), setParentItem()
  1284     \note It is more efficient to remove the item from the QGraphicsScene before
  1320     \note It is more efficient to remove the item from the QGraphicsScene before
  1285     destroying the item.
  1321     destroying the item.
  1286 */
  1322 */
  1287 QGraphicsItem::~QGraphicsItem()
  1323 QGraphicsItem::~QGraphicsItem()
  1288 {
  1324 {
       
  1325     if (d_ptr->isObject)
       
  1326         QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true;
  1289     d_ptr->inDestructor = 1;
  1327     d_ptr->inDestructor = 1;
  1290     d_ptr->removeExtraItemCache();
  1328     d_ptr->removeExtraItemCache();
  1291 
  1329 
  1292     clearFocus();
  1330     clearFocus();
  1293 
  1331 
  1301         }
  1339         }
  1302         p = p->d_ptr->parent;
  1340         p = p->d_ptr->parent;
  1303     }
  1341     }
  1304 
  1342 
  1305     if (!d_ptr->children.isEmpty()) {
  1343     if (!d_ptr->children.isEmpty()) {
  1306         QList<QGraphicsItem *> oldChildren = d_ptr->children;
  1344         while (!d_ptr->children.isEmpty())
  1307         qDeleteAll(oldChildren);
  1345             delete d_ptr->children.first();
  1308         Q_ASSERT(d_ptr->children.isEmpty());
  1346         Q_ASSERT(d_ptr->children.isEmpty());
  1309     }
  1347     }
  1310 
  1348 
  1311     if (d_ptr->scene) {
  1349     if (d_ptr->scene) {
  1312         d_ptr->scene->d_func()->removeItemHelper(this);
  1350         d_ptr->scene->d_func()->removeItemHelper(this);
  1313     } else {
  1351     } else {
  1314         d_ptr->resetFocusProxy();
  1352         d_ptr->resetFocusProxy();
  1315         d_ptr->setParentItemHelper(0);
  1353         d_ptr->setParentItemHelper(0);
  1316     }
  1354     }
  1317 
  1355 
       
  1356 #ifndef QT_NO_GRAPHICSEFFECT
  1318     delete d_ptr->graphicsEffect;
  1357     delete d_ptr->graphicsEffect;
       
  1358 #endif //QT_NO_GRAPHICSEFFECT
  1319     if (d_ptr->transformData) {
  1359     if (d_ptr->transformData) {
  1320         for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
  1360         for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
  1321             QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
  1361             QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
  1322             static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
  1362             static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
  1323             delete t;
  1363             delete t;
  1655         return;
  1695         return;
  1656     if (d_ptr->scene)
  1696     if (d_ptr->scene)
  1657         d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags));
  1697         d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags));
  1658 
  1698 
  1659     // Flags that alter the geometry of the item (or its children).
  1699     // Flags that alter the geometry of the item (or its children).
  1660     const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);
  1700     const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable);
  1661     bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
  1701     bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
  1662     if (fullUpdate)
  1702     if (fullUpdate)
  1663         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  1703         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  1664 
  1704 
  1665     // Keep the old flags to compare the diff.
  1705     // Keep the old flags to compare the diff.
  1683     if ((flags & ItemClipsChildrenToShape) != (oldFlags & ItemClipsChildrenToShape)) {
  1723     if ((flags & ItemClipsChildrenToShape) != (oldFlags & ItemClipsChildrenToShape)) {
  1684         // Item children clipping changes. Propagate the ancestor flag to
  1724         // Item children clipping changes. Propagate the ancestor flag to
  1685         // all children.
  1725         // all children.
  1686         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
  1726         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
  1687     }
  1727     }
  1688 
       
  1689     if ((flags & ItemClipsToShape) != (oldFlags & ItemClipsToShape))
       
  1690         d_ptr->invalidateCachedClipPath();
       
  1691 
  1728 
  1692     if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
  1729     if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
  1693         // Item children clipping changes. Propagate the ancestor flag to
  1730         // Item children clipping changes. Propagate the ancestor flag to
  1694         // all children.
  1731         // all children.
  1695         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
  1732         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
  1723         else
  1760         else
  1724             d_ptr->scene->d_func()->leaveModal(this);
  1761             d_ptr->scene->d_func()->leaveModal(this);
  1725     }
  1762     }
  1726 
  1763 
  1727     if (d_ptr->scene) {
  1764     if (d_ptr->scene) {
  1728         d_ptr->scene->d_func()->markDirty(this, QRectF(),
  1765         if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) {
  1729                                           /*invalidateChildren=*/true,
  1766             if (flags & ItemSendsScenePositionChanges)
  1730                                           /*maybeDirtyClipPath*/true);
  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);
  1731     }
  1772     }
  1732 
  1773 
  1733     // Notify change.
  1774     // Notify change.
  1734     itemChange(ItemFlagsHaveChanged, quint32(flags));
  1775     itemChange(ItemFlagsHaveChanged, quint32(flags));
  1735 }
  1776 }
  2073     // Schedule redrawing
  2114     // Schedule redrawing
  2074     if (update) {
  2115     if (update) {
  2075         QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
  2116         QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
  2076         if (c)
  2117         if (c)
  2077             c->purge();
  2118             c->purge();
  2078         if (scene) {
  2119         if (scene)
  2079             scene->d_func()->markDirty(q_ptr, QRectF(),
  2120             scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
  2080                                        /*invalidateChildren=*/false,
       
  2081                                        /*maybeDirtyClipPath=*/false,
       
  2082                                        /*force=*/true);
       
  2083         }
       
  2084     }
  2121     }
  2085 
  2122 
  2086     // Certain properties are dropped as an item becomes invisible.
  2123     // Certain properties are dropped as an item becomes invisible.
  2087     if (!newVisible) {
  2124     if (!newVisible) {
  2088         if (scene) {
  2125         if (scene) {
  2142                 scene->setActivePanel(parent);
  2179                 scene->setActivePanel(parent);
  2143         }
  2180         }
  2144     }
  2181     }
  2145 
  2182 
  2146     // Enable subfocus
  2183     // Enable subfocus
  2147     if (newVisible) {
  2184     if (scene && newVisible) {
  2148         QGraphicsItem *p = parent;
  2185         QGraphicsItem *p = parent;
  2149         bool done = false;
  2186         bool done = false;
  2150         while (p) {
  2187         while (p) {
  2151             if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  2188             if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  2152                 QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
  2189                 QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
  2483     // Notify change.
  2520     // Notify change.
  2484     itemChange(ItemOpacityHasChanged, newOpacityVariant);
  2521     itemChange(ItemOpacityHasChanged, newOpacityVariant);
  2485 
  2522 
  2486     // Update.
  2523     // Update.
  2487     if (d_ptr->scene) {
  2524     if (d_ptr->scene) {
       
  2525 #ifndef QT_NO_GRAPHICSEFFECT
  2488         d_ptr->invalidateGraphicsEffectsRecursively();
  2526         d_ptr->invalidateGraphicsEffectsRecursively();
       
  2527 #endif //QT_NO_GRAPHICSEFFECT
  2489         d_ptr->scene->d_func()->markDirty(this, QRectF(),
  2528         d_ptr->scene->d_func()->markDirty(this, QRectF(),
  2490                                           /*invalidateChildren=*/true,
  2529                                           /*invalidateChildren=*/true,
  2491                                           /*maybeDirtyClipPath=*/false,
       
  2492                                           /*force=*/false,
  2530                                           /*force=*/false,
  2493                                           /*ignoreOpacity=*/true);
  2531                                           /*ignoreOpacity=*/true);
  2494     }
  2532     }
  2495 
  2533 
  2496     if (d_ptr->isObject)
  2534     if (d_ptr->isObject)
  2500 /*!
  2538 /*!
  2501     Returns a pointer to this item's effect if it has one; otherwise 0.
  2539     Returns a pointer to this item's effect if it has one; otherwise 0.
  2502 
  2540 
  2503     \since 4.6
  2541     \since 4.6
  2504 */
  2542 */
       
  2543 #ifndef QT_NO_GRAPHICSEFFECT
  2505 QGraphicsEffect *QGraphicsItem::graphicsEffect() const
  2544 QGraphicsEffect *QGraphicsItem::graphicsEffect() const
  2506 {
  2545 {
  2507     return d_ptr->graphicsEffect;
  2546     return d_ptr->graphicsEffect;
  2508 }
  2547 }
  2509 
  2548 
  2513     the new \a effect.
  2552     the new \a effect.
  2514 
  2553 
  2515     If \a effect is the installed on a different item, setGraphicsEffect() will remove
  2554     If \a effect is the installed on a different item, setGraphicsEffect() will remove
  2516     the effect from the item and install it on this item.
  2555     the effect from the item and install it on this item.
  2517 
  2556 
       
  2557     QGraphicsItem takes ownership of \a effect.
       
  2558 
  2518     \note This function will apply the effect on itself and all its children.
  2559     \note This function will apply the effect on itself and all its children.
  2519 
  2560 
  2520     \since 4.6
  2561     \since 4.6
  2521 */
  2562 */
  2522 void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
  2563 void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
  2523 {
  2564 {
  2524     if (d_ptr->graphicsEffect == effect)
  2565     if (d_ptr->graphicsEffect == effect)
  2525         return;
  2566         return;
  2526 
  2567 
  2527     if (d_ptr->graphicsEffect && effect) {
  2568     if (d_ptr->graphicsEffect) {
  2528         delete d_ptr->graphicsEffect;
  2569         delete d_ptr->graphicsEffect;
  2529         d_ptr->graphicsEffect = 0;
  2570         d_ptr->graphicsEffect = 0;
  2530     }
  2571     }
  2531 
  2572 
  2532     if (!effect) {
  2573     if (effect) {
  2533         // Unset current effect.
       
  2534         QGraphicsEffectPrivate *oldEffectPrivate = d_ptr->graphicsEffect->d_func();
       
  2535         d_ptr->graphicsEffect = 0;
       
  2536         if (oldEffectPrivate) {
       
  2537             oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source.
       
  2538             if (d_ptr->scene) // Update the views directly.
       
  2539                 d_ptr->scene->d_func()->markDirty(this, QRectF(), false, false, false, false, true);
       
  2540         }
       
  2541     } else {
       
  2542         // Set new effect.
  2574         // Set new effect.
  2543         QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
  2575         QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
  2544         QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
  2576         QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
  2545         d_ptr->graphicsEffect = effect;
  2577         d_ptr->graphicsEffect = effect;
  2546         effect->d_func()->setGraphicsEffectSource(source);
  2578         effect->d_func()->setGraphicsEffectSource(source);
  2547     }
  2579         prepareGeometryChange();
  2548 
  2580     }
  2549     prepareGeometryChange();
  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;
  2550 }
  2611 }
  2551 
  2612 
  2552 /*!
  2613 /*!
  2553     \internal
  2614     \internal
  2554     \since 4.6
  2615     \since 4.6
  2559 
  2620 
  2560     \sa boundingRect()
  2621     \sa boundingRect()
  2561 */
  2622 */
  2562 QRectF QGraphicsItemPrivate::effectiveBoundingRect() const
  2623 QRectF QGraphicsItemPrivate::effectiveBoundingRect() const
  2563 {
  2624 {
  2564     QGraphicsEffect *effect = graphicsEffect;
  2625 #ifndef QT_NO_GRAPHICSEFFECT
  2565     QRectF brect = effect && effect->isEnabled() ? effect->boundingRect() : q_ptr->boundingRect();
  2626     Q_Q(const QGraphicsItem);
       
  2627     QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
  2566     if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
  2628     if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
  2567         return brect;
  2629         return brect;
  2568 
  2630 
  2569     const QGraphicsItem *effectParent = parent;
  2631     const QGraphicsItem *effectParent = parent;
  2570     while (effectParent) {
  2632     while (effectParent) {
  2571         effect = effectParent->d_ptr->graphicsEffect;
  2633         QGraphicsEffect *effect = effectParent->d_ptr->graphicsEffect;
  2572         if (effect && effect->isEnabled())
  2634         if (scene && effect && effect->isEnabled()) {
  2573             brect = effect->boundingRectFor(brect);
  2635             const QRectF brectInParentSpace = q->mapRectToItem(effectParent, brect);
       
  2636             const QRectF effectRectInParentSpace = effectParent->d_ptr->effectiveBoundingRect(brectInParentSpace);
       
  2637             brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
       
  2638         }
  2574         if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
  2639         if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
  2575             return brect;
  2640             return brect;
  2576         effectParent = effectParent->d_ptr->parent;
  2641         effectParent = effectParent->d_ptr->parent;
  2577     }
  2642     }
  2578 
  2643 
  2579     return brect;
  2644     return brect;
       
  2645 #else //QT_NO_GRAPHICSEFFECT
       
  2646     return q_ptr->boundingRect();
       
  2647 #endif //QT_NO_GRAPHICSEFFECT
       
  2648 
  2580 }
  2649 }
  2581 
  2650 
  2582 /*!
  2651 /*!
  2583     \internal
  2652     \internal
  2584     \since 4.6
  2653     \since 4.6
  2928 */
  2997 */
  2929 bool QGraphicsItem::hasFocus() const
  2998 bool QGraphicsItem::hasFocus() const
  2930 {
  2999 {
  2931     if (d_ptr->focusProxy)
  3000     if (d_ptr->focusProxy)
  2932         return d_ptr->focusProxy->hasFocus();
  3001         return d_ptr->focusProxy->hasFocus();
  2933     return (d_ptr->scene && d_ptr->scene->focusItem() == this);
  3002     return isActive() && (d_ptr->scene && d_ptr->scene->focusItem() == this);
  2934 }
  3003 }
  2935 
  3004 
  2936 /*!
  3005 /*!
  2937     Gives keyboard input focus to this item. The \a focusReason argument will
  3006     Gives keyboard input focus to this item. The \a focusReason argument will
  2938     be passed into any \l{QFocusEvent}{focus event} generated by this function;
  3007     be passed into any \l{QFocusEvent}{focus event} generated by this function;
  2979     // Update focus scope item ptr.
  3048     // Update focus scope item ptr.
  2980     QGraphicsItem *p = parent;
  3049     QGraphicsItem *p = parent;
  2981     while (p) {
  3050     while (p) {
  2982         if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  3051         if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  2983             p->d_ptr->focusScopeItem = q_ptr;
  3052             p->d_ptr->focusScopeItem = q_ptr;
  2984             if (!q_ptr->isActive() || !p->focusItem())
  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.
  2985                 return;
  3056                 return;
       
  3057             }
  2986             break;
  3058             break;
  2987         }
  3059         }
  2988         p = p->d_ptr->parent;
  3060         p = p->d_ptr->parent;
  2989     }
  3061     }
  2990 
  3062 
  3283 
  3355 
  3284     \sa x(), setPos()
  3356     \sa x(), setPos()
  3285 */
  3357 */
  3286 void QGraphicsItem::setX(qreal x)
  3358 void QGraphicsItem::setX(qreal x)
  3287 {
  3359 {
       
  3360     if (d_ptr->inDestructor)
       
  3361         return;
       
  3362 
  3288     d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
  3363     d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
  3289 }
  3364 }
  3290 
  3365 
  3291 /*!
  3366 /*!
  3292     \fn QGraphicsItem::y() const
  3367     \fn QGraphicsItem::y() const
  3304 
  3379 
  3305     \sa x(), setPos()
  3380     \sa x(), setPos()
  3306 */
  3381 */
  3307 void QGraphicsItem::setY(qreal y)
  3382 void QGraphicsItem::setY(qreal y)
  3308 {
  3383 {
       
  3384     if (d_ptr->inDestructor)
       
  3385         return;
       
  3386 
  3309     d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
  3387     d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
  3310 }
  3388 }
  3311 
  3389 
  3312 /*!
  3390 /*!
  3313     Returns the item's position in scene coordinates. This is
  3391     Returns the item's position in scene coordinates. This is
  3327 */
  3405 */
  3328 void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
  3406 void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
  3329 {
  3407 {
  3330     Q_Q(QGraphicsItem);
  3408     Q_Q(QGraphicsItem);
  3331     inSetPosHelper = 1;
  3409     inSetPosHelper = 1;
  3332     updateCachedClipPathFromSetPosHelper(pos);
       
  3333     if (scene)
  3410     if (scene)
  3334         q->prepareGeometryChange();
  3411         q->prepareGeometryChange();
  3335     QPointF oldPos = this->pos;
  3412     QPointF oldPos = this->pos;
  3336     this->pos = pos;
  3413     this->pos = pos;
  3337     dirtySceneTransform = 1;
  3414     dirtySceneTransform = 1;
  3369 void QGraphicsItem::setPos(const QPointF &pos)
  3446 void QGraphicsItem::setPos(const QPointF &pos)
  3370 {
  3447 {
  3371     if (d_ptr->pos == pos)
  3448     if (d_ptr->pos == pos)
  3372         return;
  3449         return;
  3373 
  3450 
       
  3451     if (d_ptr->inDestructor)
       
  3452         return;
       
  3453 
  3374     // Update and repositition.
  3454     // Update and repositition.
  3375     if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
  3455     if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
  3376         d_ptr->setPosHelper(pos);
  3456         d_ptr->setPosHelper(pos);
  3377         return;
  3457         return;
  3378     }
  3458     }
  3386     // Update and repositition.
  3466     // Update and repositition.
  3387     d_ptr->setPosHelper(newPos);
  3467     d_ptr->setPosHelper(newPos);
  3388 
  3468 
  3389     // Send post-notification.
  3469     // Send post-notification.
  3390     itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
  3470     itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
       
  3471     d_ptr->sendScenePosChange();
  3391 }
  3472 }
  3392 
  3473 
  3393 /*!
  3474 /*!
  3394     \fn void QGraphicsItem::setPos(qreal x, qreal y)
  3475     \fn void QGraphicsItem::setPos(qreal x, qreal y)
  3395     \overload
  3476     \overload
  3996     // Update and set the new transformation.
  4077     // Update and set the new transformation.
  3997     d_ptr->setTransformHelper(newTransform);
  4078     d_ptr->setTransformHelper(newTransform);
  3998 
  4079 
  3999     // Send post-notification.
  4080     // Send post-notification.
  4000     itemChange(ItemTransformHasChanged, newTransformVariant);
  4081     itemChange(ItemTransformHasChanged, newTransformVariant);
       
  4082     d_ptr->sendScenePosChange();
  4001 }
  4083 }
  4002 
  4084 
  4003 /*!
  4085 /*!
  4004     \obsolete
  4086     \obsolete
  4005 
  4087 
  4220             children[i]->d_ptr->siblingIndex = i;
  4302             children[i]->d_ptr->siblingIndex = i;
  4221     }
  4303     }
  4222 }
  4304 }
  4223 
  4305 
  4224 /*!
  4306 /*!
       
  4307     \internal
       
  4308 */
       
  4309 inline void QGraphicsItemPrivate::sendScenePosChange()
       
  4310 {
       
  4311     Q_Q(QGraphicsItem);
       
  4312     if (scene) {
       
  4313         if (flags & QGraphicsItem::ItemSendsScenePositionChanges)
       
  4314             q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos());
       
  4315         if (scenePosDescendants) {
       
  4316             foreach (QGraphicsItem *item, scene->d_func()->scenePosItems) {
       
  4317                 if (q->isAncestorOf(item))
       
  4318                     item->itemChange(QGraphicsItem::ItemScenePositionHasChanged, item->scenePos());
       
  4319             }
       
  4320         }
       
  4321     }
       
  4322 }
       
  4323 
       
  4324 /*!
  4225     \since 4.6
  4325     \since 4.6
  4226 
  4326 
  4227     Stacks this item before \a sibling, which must be a sibling item (i.e., the
  4327     Stacks this item before \a sibling, which must be a sibling item (i.e., the
  4228     two items must share the same parent item, or must both be toplevel items).
  4328     two items must share the same parent item, or must both be toplevel items).
  4229     The \a sibling must have the same Z value as this item, otherwise calling
  4329     The \a sibling must have the same Z value as this item, otherwise calling
  4261         d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes();
  4361         d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes();
  4262 
  4362 
  4263     // Only move items with the same Z value, and that need moving.
  4363     // Only move items with the same Z value, and that need moving.
  4264     int siblingIndex = sibling->d_ptr->siblingIndex;
  4364     int siblingIndex = sibling->d_ptr->siblingIndex;
  4265     int myIndex = d_ptr->siblingIndex;
  4365     int myIndex = d_ptr->siblingIndex;
  4266     if (myIndex >= siblingIndex && d_ptr->z == sibling->d_ptr->z) {
  4366     if (myIndex >= siblingIndex) {
  4267         siblings->move(myIndex, siblingIndex);
  4367         siblings->move(myIndex, siblingIndex);
  4268         // Fixup the insertion ordering.
  4368         // Fixup the insertion ordering.
  4269         for (int i = 0; i < siblings->size(); ++i) {
  4369         for (int i = 0; i < siblings->size(); ++i) {
  4270             int &index = siblings->at(i)->d_ptr->siblingIndex;
  4370             int &index = siblings->at(i)->d_ptr->siblingIndex;
  4271             if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
  4371             if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
  4272                 ++index;
  4372                 ++index;
  4273         }
  4373         }
  4274         d_ptr->siblingIndex = siblingIndex;
  4374         d_ptr->siblingIndex = siblingIndex;
       
  4375         for (int i = 0; i < siblings->size(); ++i) {
       
  4376             int &index = siblings->at(i)->d_ptr->siblingIndex;
       
  4377             if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
       
  4378                 siblings->at(i)->d_ptr->siblingOrderChange();
       
  4379         }
       
  4380         d_ptr->siblingOrderChange();
  4275     }
  4381     }
  4276 }
  4382 }
  4277 
  4383 
  4278 /*!
  4384 /*!
  4279     Returns the bounding rect of this item's descendants (i.e., its
  4385     Returns the bounding rect of this item's descendants (i.e., its
  4434     \sa isClipped(), shape(), setFlags()
  4540     \sa isClipped(), shape(), setFlags()
  4435 */
  4541 */
  4436 QPainterPath QGraphicsItem::clipPath() const
  4542 QPainterPath QGraphicsItem::clipPath() const
  4437 {
  4543 {
  4438     Q_D(const QGraphicsItem);
  4544     Q_D(const QGraphicsItem);
  4439     if (!d->dirtyClipPath)
  4545     if (!isClipped())
  4440         return d->emptyClipPath ? QPainterPath() : d->cachedClipPath;
  4546         return QPainterPath();
  4441 
       
  4442     if (!isClipped()) {
       
  4443         d_ptr->setCachedClipPath(QPainterPath());
       
  4444         return d->cachedClipPath;
       
  4445     }
       
  4446 
  4547 
  4447     const QRectF thisBoundingRect(boundingRect());
  4548     const QRectF thisBoundingRect(boundingRect());
  4448     if (thisBoundingRect.isEmpty()) {
  4549     if (thisBoundingRect.isEmpty())
  4449         if (d_ptr->flags & ItemClipsChildrenToShape)
       
  4450             d_ptr->setEmptyCachedClipPathRecursively();
       
  4451         else
       
  4452             d_ptr->setEmptyCachedClipPath();
       
  4453         return QPainterPath();
  4550         return QPainterPath();
  4454     }
       
  4455 
  4551 
  4456     QPainterPath clip;
  4552     QPainterPath clip;
  4457     // Start with the item's bounding rect.
  4553     // Start with the item's bounding rect.
  4458     clip.addRect(thisBoundingRect);
  4554     clip.addRect(thisBoundingRect);
  4459 
  4555 
  4460     if (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
  4556     if (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
  4461         const QGraphicsItem *parent = this;
  4557         const QGraphicsItem *parent = this;
  4462         const QGraphicsItem *lastParent = this;
  4558         const QGraphicsItem *lastParent = this;
  4463 
  4559 
  4464         // Intersect any in-between clips starting at the top and moving downwards.
  4560         // Intersect any in-between clips starting at the top and moving downwards.
  4465         bool foundValidClipPath = false;
       
  4466         while ((parent = parent->d_ptr->parent)) {
  4561         while ((parent = parent->d_ptr->parent)) {
  4467             if (parent->d_ptr->flags & ItemClipsChildrenToShape) {
  4562             if (parent->d_ptr->flags & ItemClipsChildrenToShape) {
  4468                 // Map clip to the current parent and intersect with its shape/clipPath
  4563                 // Map clip to the current parent and intersect with its shape/clipPath
  4469                 clip = lastParent->itemTransform(parent).map(clip);
  4564                 clip = lastParent->itemTransform(parent).map(clip);
  4470                 if ((foundValidClipPath = !parent->d_ptr->dirtyClipPath && parent->isClipped())) {
  4565                 clip = clip.intersected(parent->shape());
  4471                     if (parent->d_ptr->emptyClipPath) {
  4566                 if (clip.isEmpty())
  4472                         if (d_ptr->flags & ItemClipsChildrenToShape)
       
  4473                             d_ptr->setEmptyCachedClipPathRecursively();
       
  4474                         else
       
  4475                             d_ptr->setEmptyCachedClipPath();
       
  4476                         return QPainterPath();
       
  4477                     }
       
  4478                     clip = clip.intersected(parent->d_ptr->cachedClipPath);
       
  4479                     if (!(parent->d_ptr->flags & ItemClipsToShape))
       
  4480                         clip = clip.intersected(parent->shape());
       
  4481                 } else {
       
  4482                     clip = clip.intersected(parent->shape());
       
  4483                 }
       
  4484 
       
  4485                 if (clip.isEmpty()) {
       
  4486                     if (d_ptr->flags & ItemClipsChildrenToShape)
       
  4487                         d_ptr->setEmptyCachedClipPathRecursively();
       
  4488                     else
       
  4489                         d_ptr->setEmptyCachedClipPath();
       
  4490                     return clip;
  4567                     return clip;
  4491                 }
       
  4492                 lastParent = parent;
  4568                 lastParent = parent;
  4493             }
  4569             }
  4494 
  4570 
  4495             if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
  4571             if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
  4496                 || foundValidClipPath) {
       
  4497                 break;
  4572                 break;
  4498             }
       
  4499         }
  4573         }
  4500 
  4574 
  4501         if (lastParent != this) {
  4575         if (lastParent != this) {
  4502             // Map clip back to the item's transform.
  4576             // Map clip back to the item's transform.
  4503             // ### what if itemtransform fails
  4577             // ### what if itemtransform fails
  4506     }
  4580     }
  4507 
  4581 
  4508     if (d->flags & ItemClipsToShape)
  4582     if (d->flags & ItemClipsToShape)
  4509         clip = clip.intersected(shape());
  4583         clip = clip.intersected(shape());
  4510 
  4584 
  4511     d_ptr->setCachedClipPath(clip);
       
  4512     return clip;
  4585     return clip;
  4513 }
  4586 }
  4514 
  4587 
  4515 /*!
  4588 /*!
  4516     Returns true if this item contains \a point, which is in local
  4589     Returns true if this item contains \a point, which is in local
  4925 
  4998 
  4926 /*!
  4999 /*!
  4927     \internal
  5000     \internal
  4928     Returns true if we can discard an update request; otherwise false.
  5001     Returns true if we can discard an update request; otherwise false.
  4929 */
  5002 */
  4930 bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignoreVisibleBit,
  5003 bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreVisibleBit, bool ignoreDirtyBit,
  4931                                                 bool ignoreDirtyBit, bool ignoreOpacity) const
  5004                                                 bool ignoreOpacity) const
  4932 {
  5005 {
  4933     // No scene, or if the scene is updating everything, means we have nothing
  5006     // No scene, or if the scene is updating everything, means we have nothing
  4934     // to do. The only exception is if the scene tracks the growing scene rect.
  5007     // to do. The only exception is if the scene tracks the growing scene rect.
  4935     return !scene
  5008     return !scene
  4936            || (!visible && !ignoreVisibleBit && !this->ignoreVisible)
  5009            || (!visible && !ignoreVisibleBit && !this->ignoreVisible)
  4937            || (!ignoreDirtyBit && fullUpdatePending)
  5010            || (!ignoreDirtyBit && fullUpdatePending)
  4938            || (!ignoreClipping && (childrenClippedToShape() && isClippedAway()))
       
  4939            || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent());
  5011            || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent());
  4940 }
  5012 }
  4941 
  5013 
  4942 /*!
  5014 /*!
  4943     \internal
  5015     \internal
  4951 }
  5023 }
  4952 
  5024 
  4953 /*!
  5025 /*!
  4954     \internal
  5026     \internal
  4955 */
  5027 */
       
  5028 #ifndef QT_NO_GRAPHICSEFFECT
  4956 void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively()
  5029 void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively()
  4957 {
  5030 {
  4958     QGraphicsItemPrivate *itemPrivate = this;
  5031     QGraphicsItemPrivate *itemPrivate = this;
  4959     do {
  5032     do {
  4960         if (itemPrivate->graphicsEffect) {
  5033         if (itemPrivate->graphicsEffect) {
  4963             if (!itemPrivate->updateDueToGraphicsEffect)
  5036             if (!itemPrivate->updateDueToGraphicsEffect)
  4964                 static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
  5037                 static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
  4965         }
  5038         }
  4966     } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
  5039     } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
  4967 }
  5040 }
       
  5041 #endif //QT_NO_GRAPHICSEFFECT
  4968 
  5042 
  4969 /*!
  5043 /*!
  4970     \internal
  5044     \internal
  4971 */
  5045 */
  4972 void QGraphicsItemPrivate::invalidateDepthRecursively()
  5046 void QGraphicsItemPrivate::invalidateDepthRecursively()
  5064     if (c) {
  5138     if (c) {
  5065         c->purge();
  5139         c->purge();
  5066         delete c;
  5140         delete c;
  5067     }
  5141     }
  5068     unsetExtra(ExtraCacheData);
  5142     unsetExtra(ExtraCacheData);
  5069 }
       
  5070 
       
  5071 void QGraphicsItemPrivate::setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect)
       
  5072 {
       
  5073     setEmptyCachedClipPath();
       
  5074 
       
  5075     const bool checkRect = !emptyIfOutsideThisRect.isNull()
       
  5076                            && !(flags & QGraphicsItem::ItemClipsChildrenToShape);
       
  5077     for (int i = 0; i < children.size(); ++i) {
       
  5078         if (!checkRect) {
       
  5079             children.at(i)->d_ptr->setEmptyCachedClipPathRecursively();
       
  5080             continue;
       
  5081         }
       
  5082 
       
  5083         QGraphicsItem *child = children.at(i);
       
  5084         const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect);
       
  5085         if (rect.intersects(child->boundingRect()))
       
  5086             child->d_ptr->invalidateCachedClipPathRecursively(false, rect);
       
  5087         else
       
  5088             child->d_ptr->setEmptyCachedClipPathRecursively(rect);
       
  5089     }
       
  5090 }
       
  5091 
       
  5092 void QGraphicsItemPrivate::invalidateCachedClipPathRecursively(bool childrenOnly, const QRectF &emptyIfOutsideThisRect)
       
  5093 {
       
  5094     if (!childrenOnly)
       
  5095         invalidateCachedClipPath();
       
  5096 
       
  5097     const bool checkRect = !emptyIfOutsideThisRect.isNull();
       
  5098     for (int i = 0; i < children.size(); ++i) {
       
  5099         if (!checkRect) {
       
  5100             children.at(i)->d_ptr->invalidateCachedClipPathRecursively(false);
       
  5101             continue;
       
  5102         }
       
  5103 
       
  5104         QGraphicsItem *child = children.at(i);
       
  5105         const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect);
       
  5106         if (rect.intersects(child->boundingRect()))
       
  5107             child->d_ptr->invalidateCachedClipPathRecursively(false, rect);
       
  5108         else
       
  5109             child->d_ptr->setEmptyCachedClipPathRecursively(rect);
       
  5110     }
       
  5111 }
       
  5112 
       
  5113 void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &newPos)
       
  5114 {
       
  5115     Q_ASSERT(inSetPosHelper);
       
  5116 
       
  5117     if (inDestructor || !(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
       
  5118         return; // Not clipped by any ancestor.
       
  5119 
       
  5120     // Find closest clip ancestor and transform.
       
  5121     Q_Q(QGraphicsItem);
       
  5122     // COMBINE
       
  5123     QTransform thisToParentTransform = QTransform::fromTranslate(newPos.x(), newPos.y());
       
  5124     if (transformData)
       
  5125         thisToParentTransform = transformData->computedFullTransform(&thisToParentTransform);
       
  5126     QGraphicsItem *clipParent = parent;
       
  5127     while (clipParent && !clipParent->d_ptr->inDestructor && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) {
       
  5128         thisToParentTransform *= clipParent->d_ptr->transformToParent();
       
  5129         clipParent = clipParent->d_ptr->parent;
       
  5130     }
       
  5131 
       
  5132     // Ensure no parents are currently being deleted. This can only
       
  5133     // happen if the item is moved by a dying ancestor.
       
  5134     QGraphicsItem *p = clipParent;
       
  5135     while (p) {
       
  5136         if (p->d_ptr->inDestructor)
       
  5137             return;
       
  5138         p = p->d_ptr->parent;
       
  5139     }
       
  5140 
       
  5141     // From here everything is calculated in clip parent's coordinates.
       
  5142     const QRectF parentBoundingRect(clipParent->boundingRect());
       
  5143     const QRectF thisBoundingRect(thisToParentTransform.mapRect(q->boundingRect()));
       
  5144 
       
  5145     if (!parentBoundingRect.intersects(thisBoundingRect)) {
       
  5146         // Item is moved outside the clip parent's bounding rect,
       
  5147         // i.e. it is fully clipped and the clip path is empty.
       
  5148         if (flags & QGraphicsItem::ItemClipsChildrenToShape)
       
  5149             setEmptyCachedClipPathRecursively();
       
  5150         else
       
  5151             setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentBoundingRect));
       
  5152         return;
       
  5153     }
       
  5154 
       
  5155     const QPainterPath parentClip(clipParent->isClipped() ? clipParent->clipPath() : clipParent->shape());
       
  5156     if (parentClip.contains(thisBoundingRect))
       
  5157         return; // Item is inside the clip parent's shape. No update required.
       
  5158 
       
  5159     const QRectF parentClipRect(parentClip.controlPointRect());
       
  5160     if (!parentClipRect.intersects(thisBoundingRect)) {
       
  5161         // Item is moved outside the clip parent's shape,
       
  5162         // i.e. it is fully clipped and the clip path is empty.
       
  5163         if (flags & QGraphicsItem::ItemClipsChildrenToShape)
       
  5164             setEmptyCachedClipPathRecursively();
       
  5165         else
       
  5166             setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentClipRect));
       
  5167     } else {
       
  5168         // Item is partially inside the clip parent's shape,
       
  5169         // i.e. the cached clip path must be invalidated.
       
  5170         invalidateCachedClipPathRecursively(false, thisToParentTransform.inverted().mapRect(parentClipRect));
       
  5171     }
       
  5172 }
  5143 }
  5173 
  5144 
  5174 // Traverses all the ancestors up to the top-level and updates the pointer to
  5145 // Traverses all the ancestors up to the top-level and updates the pointer to
  5175 // always point to the top-most item that has a dirty scene transform.
  5146 // always point to the top-most item that has a dirty scene transform.
  5176 // It then backtracks to the top-most dirty item and start calculating the
  5147 // It then backtracks to the top-most dirty item and start calculating the
  5267 }
  5238 }
  5268 
  5239 
  5269 /*!
  5240 /*!
  5270     \internal
  5241     \internal
  5271 
  5242 
       
  5243     Subclasses can reimplement this function to be notified when its
       
  5244     siblingIndex order is changed.
       
  5245 */
       
  5246 void QGraphicsItemPrivate::siblingOrderChange()
       
  5247 {
       
  5248 }
       
  5249 
       
  5250 /*!
       
  5251     \internal
       
  5252 
  5272     Tells us if it is a proxy widget
  5253     Tells us if it is a proxy widget
  5273 */
  5254 */
  5274 bool QGraphicsItemPrivate::isProxyWidget() const
  5255 bool QGraphicsItemPrivate::isProxyWidget() const
  5275 {
  5256 {
  5276     return false;
  5257     return false;
  5298 {
  5279 {
  5299     if (rect.isEmpty() && !rect.isNull())
  5280     if (rect.isEmpty() && !rect.isNull())
  5300         return;
  5281         return;
  5301 
  5282 
  5302     // Make sure we notify effects about invalidated source.
  5283     // Make sure we notify effects about invalidated source.
       
  5284 #ifndef QT_NO_GRAPHICSEFFECT
  5303     d_ptr->invalidateGraphicsEffectsRecursively();
  5285     d_ptr->invalidateGraphicsEffectsRecursively();
       
  5286 #endif //QT_NO_GRAPHICSEFFECT
  5304 
  5287 
  5305     if (CacheMode(d_ptr->cacheMode) != NoCache) {
  5288     if (CacheMode(d_ptr->cacheMode) != NoCache) {
  5306         // Invalidate cache.
  5289         // Invalidate cache.
  5307         QGraphicsItemCache *cache = d_ptr->extraItemCache();
  5290         QGraphicsItemCache *cache = d_ptr->extraItemCache();
  5308         if (!cache->allExposed) {
  5291         if (!cache->allExposed) {
  7173         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  7156         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  7174         d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
  7157         d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
  7175 
  7158 
  7176         QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
  7159         QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
  7177         scenePrivate->index->prepareBoundingRectChange(this);
  7160         scenePrivate->index->prepareBoundingRectChange(this);
  7178         scenePrivate->markDirty(this, QRectF(),
  7161         scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true);
  7179                                 /*invalidateChildren=*/true,
       
  7180                                 /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
       
  7181 
  7162 
  7182         // For compatibility reasons, we have to update the item's old geometry
  7163         // For compatibility reasons, we have to update the item's old geometry
  7183         // if someone is connected to the changed signal or the scene has no views.
  7164         // if someone is connected to the changed signal or the scene has no views.
  7184         // Note that this has to be done *after* markDirty to ensure that
  7165         // Note that this has to be done *after* markDirty to ensure that
  7185         // _q_processDirtyItems is called before _q_emitUpdated.
  7166         // _q_processDirtyItems is called before _q_emitUpdated.
  7194         }
  7175         }
  7195     }
  7176     }
  7196 
  7177 
  7197     QGraphicsItem *parent = this;
  7178     QGraphicsItem *parent = this;
  7198     while ((parent = parent->d_ptr->parent)) {
  7179     while ((parent = parent->d_ptr->parent)) {
  7199         parent->d_ptr->dirtyChildrenBoundingRect = 1;
  7180         QGraphicsItemPrivate *parentp = parent->d_ptr.data();
       
  7181         parentp->dirtyChildrenBoundingRect = 1;
  7200         // ### Only do this if the parent's effect applies to the entire subtree.
  7182         // ### Only do this if the parent's effect applies to the entire subtree.
  7201         parent->d_ptr->notifyBoundingRectChanged = 1;
  7183         parentp->notifyBoundingRectChanged = 1;
  7202     }
  7184 #ifndef QT_NO_GRAPHICSEFFECT
  7203 
  7185         if (parentp->scene && parentp->graphicsEffect) {
  7204     if (d_ptr->inSetPosHelper)
  7186             parentp->notifyInvalidated = 1;
  7205         return;
  7187             static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()->source->d_func())->invalidateCache();
  7206 
  7188         }
  7207     if (d_ptr->flags & ItemClipsChildrenToShape
  7189 #endif
  7208         || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
       
  7209         d_ptr->invalidateCachedClipPathRecursively();
       
  7210     } else {
       
  7211         d_ptr->invalidateCachedClipPath();
       
  7212     }
  7190     }
  7213 }
  7191 }
  7214 
  7192 
  7215 /*!
  7193 /*!
  7216     \internal
  7194     \internal
  7281     \ingroup graphicsview-api
  7259     \ingroup graphicsview-api
  7282 
  7260 
  7283     The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms.
  7261     The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms.
  7284     It maps many of QGraphicsItem's basic setters and getters to properties and adds notification
  7262     It maps many of QGraphicsItem's basic setters and getters to properties and adds notification
  7285     signals for many of them.
  7263     signals for many of them.
       
  7264 
       
  7265     \section1 Parents and Children
       
  7266 
       
  7267     Each graphics object can be constructed with a parent item. This ensures that the
       
  7268     item will be destroyed when its parent item is destroyed. Although QGraphicsObject
       
  7269     inherits from both QObject and QGraphicsItem, you should use the functions provided
       
  7270     by QGraphicsItem, \e not QObject, to manage the relationships between parent and
       
  7271     child items.
       
  7272 
       
  7273     The relationships between items can be explored using the parentItem() and childItems()
       
  7274     functions. In the hierarchy of items in a scene, the parentObject() and parentWidget()
       
  7275     functions are the equivalent of the QWidget::parent() and QWidget::parentWidget()
       
  7276     functions for QWidget subclasses.
       
  7277 
       
  7278     \sa QGraphicsWidget
  7286 */
  7279 */
  7287 
  7280 
  7288 /*!
  7281 /*!
  7289     Constructs a QGraphicsObject with \a parent.
  7282     Constructs a QGraphicsObject with \a parent.
  7290 */
  7283 */
  7302 {
  7295 {
  7303     QGraphicsItem::d_ptr->isObject = true;
  7296     QGraphicsItem::d_ptr->isObject = true;
  7304 }
  7297 }
  7305 
  7298 
  7306 /*!
  7299 /*!
  7307     Subscribes the graphics object to the given \a gesture for the specified \a context.
  7300     Subscribes the graphics object to the given \a gesture with specific \a flags.
  7308 
  7301 
  7309     \sa QGestureEvent
  7302     \sa ungrabGesture(), QGestureEvent
  7310 */
  7303 */
  7311 
  7304 void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
  7312 void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureContext context)
       
  7313 {
  7305 {
  7314     QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
  7306     QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
  7315     d->gestureContext.insert(gesture, context);
  7307     d->gestureContext.insert(gesture, flags);
  7316     (void)QGestureManager::instance(); // create a gesture manager
  7308     (void)QGestureManager::instance(); // create a gesture manager
  7317 }
  7309 }
  7318 
  7310 
  7319 /*!
  7311 /*!
       
  7312     Unsubscribes the graphics object from the given \a gesture.
       
  7313 
       
  7314     \sa grabGesture(), QGestureEvent
       
  7315 */
       
  7316 void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
       
  7317 {
       
  7318     QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
       
  7319     if (d->gestureContext.remove(gesture)) {
       
  7320         QGestureManager *manager = QGestureManager::instance();
       
  7321         manager->cleanupCachedGestures(this, gesture);
       
  7322     }
       
  7323 }
       
  7324 
       
  7325 /*!
  7320   \property QGraphicsObject::parent
  7326   \property QGraphicsObject::parent
  7321   \brief the parent of the item. It is independent from \fn QObject::parent.
  7327   \brief the parent of the item
       
  7328 
       
  7329   \note The item's parent is set independently of the parent object returned
       
  7330   by QObject::parent().
  7322 
  7331 
  7323   \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject()
  7332   \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject()
  7324 */
       
  7325 
       
  7326 /*!
       
  7327   \property QGraphicsObject::id
       
  7328   \brief the id of of the item
       
  7329 
       
  7330   \sa QObject::objectName(), QObject::setObjectName()
       
  7331 */
  7333 */
  7332 
  7334 
  7333 /*!
  7335 /*!
  7334   \property QGraphicsObject::opacity
  7336   \property QGraphicsObject::opacity
  7335   \brief the opacity of the item
  7337   \brief the opacity of the item
  9136     \reimp
  9138     \reimp
  9137 */
  9139 */
  9138 QRectF QGraphicsPixmapItem::boundingRect() const
  9140 QRectF QGraphicsPixmapItem::boundingRect() const
  9139 {
  9141 {
  9140     Q_D(const QGraphicsPixmapItem);
  9142     Q_D(const QGraphicsPixmapItem);
  9141     qreal pw = 1.0;
       
  9142     if (d->pixmap.isNull())
  9143     if (d->pixmap.isNull())
  9143         return QRectF();
  9144         return QRectF();
  9144     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     }
  9145 }
  9151 }
  9146 
  9152 
  9147 /*!
  9153 /*!
  9148     \reimp
  9154     \reimp
  9149 */
  9155 */
  9454 */
  9460 */
  9455 void QGraphicsTextItem::setDefaultTextColor(const QColor &col)
  9461 void QGraphicsTextItem::setDefaultTextColor(const QColor &col)
  9456 {
  9462 {
  9457     QTextControl *c = dd->textControl();
  9463     QTextControl *c = dd->textControl();
  9458     QPalette pal = c->palette();
  9464     QPalette pal = c->palette();
       
  9465     QColor old = pal.color(QPalette::Text);
  9459     pal.setColor(QPalette::Text, col);
  9466     pal.setColor(QPalette::Text, col);
  9460     c->setPalette(pal);
  9467     c->setPalette(pal);
       
  9468     if (old != col)
       
  9469         update();
  9461 }
  9470 }
  9462 
  9471 
  9463 /*!
  9472 /*!
  9464     Returns the default text color that is used to for unformatted text.
  9473     Returns the default text color that is used to for unformatted text.
  9465 */
  9474 */
  9649     case QEvent::KeyPress:
  9658     case QEvent::KeyPress:
  9650     case QEvent::KeyRelease:
  9659     case QEvent::KeyRelease:
  9651         // Reset the focus widget's input context, regardless
  9660         // Reset the focus widget's input context, regardless
  9652         // of how this item gained or lost focus.
  9661         // of how this item gained or lost focus.
  9653         if (QWidget *fw = qApp->focusWidget()) {
  9662         if (QWidget *fw = qApp->focusWidget()) {
       
  9663 #ifndef QT_NO_IM
  9654             if (QInputContext *qic = fw->inputContext()) {
  9664             if (QInputContext *qic = fw->inputContext()) {
  9655                 if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)
  9665                 if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)
  9656                     qic->reset();
  9666                     qic->reset();
  9657                 else
  9667                 else
  9658                     qic->update();
  9668                     qic->update();
  9659             }
  9669             }
       
  9670 #endif //QT_NO_IM
  9660         }
  9671         }
  9661         break;
  9672         break;
  9662     default:
  9673     default:
  9663         break;
  9674         break;
  9664     }
  9675     }
  9721         }
  9732         }
  9722         return;
  9733         return;
  9723     }
  9734     }
  9724 
  9735 
  9725     QWidget *widget = event->widget();
  9736     QWidget *widget = event->widget();
  9726     if (widget) {
  9737     if (widget && (dd->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos())) {
  9727         qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus);
  9738         qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus);
  9728     }
  9739     }
  9729     dd->clickCausedFocus = 0;
  9740     dd->clickCausedFocus = 0;
  9730     dd->sendControlEvent(event);
  9741     dd->sendControlEvent(event);
  9731 }
  9742 }
 10025     set the Qt::TextEditable flag.
 10036     set the Qt::TextEditable flag.
 10026 */
 10037 */
 10027 void QGraphicsTextItem::setTextInteractionFlags(Qt::TextInteractionFlags flags)
 10038 void QGraphicsTextItem::setTextInteractionFlags(Qt::TextInteractionFlags flags)
 10028 {
 10039 {
 10029     if (flags == Qt::NoTextInteraction)
 10040     if (flags == Qt::NoTextInteraction)
 10030         setFlags(this->flags() & ~QGraphicsItem::ItemIsFocusable);
 10041         setFlags(this->flags() & ~(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod));
 10031     else
 10042     else
 10032         setFlags(this->flags() | QGraphicsItem::ItemIsFocusable);
 10043         setFlags(this->flags() | QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
       
 10044 
 10033     dd->textControl()->setTextInteractionFlags(flags);
 10045     dd->textControl()->setTextInteractionFlags(flags);
 10034 }
 10046 }
 10035 
 10047 
 10036 /*!
 10048 /*!
 10037     Returns the current text interaction flags.
 10049     Returns the current text interaction flags.
 10530 
 10542 
 10531     // removing position from translation component of the new transform
 10543     // removing position from translation component of the new transform
 10532     if (!item->pos().isNull())
 10544     if (!item->pos().isNull())
 10533         newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
 10545         newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
 10534 
 10546 
       
 10547     // removing additional transformations properties applied with itemTransform()
       
 10548     QPointF origin = item->transformOriginPoint();
       
 10549     QMatrix4x4 m;
       
 10550     QList<QGraphicsTransform*> transformList = item->transformations();
       
 10551     for (int i = 0; i < transformList.size(); ++i)
       
 10552         transformList.at(i)->applyTo(&m);
       
 10553     newItemTransform *= m.toTransform().inverted();
       
 10554     newItemTransform.translate(origin.x(), origin.y());
       
 10555     newItemTransform.rotate(-item->rotation());
       
 10556     newItemTransform.scale(1/item->scale(), 1/item->scale());
       
 10557     newItemTransform.translate(-origin.x(), -origin.y());
       
 10558 
       
 10559     // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
       
 10560 
 10535     item->setTransform(newItemTransform);
 10561     item->setTransform(newItemTransform);
 10536     item->d_func()->setIsMemberOfGroup(true);
 10562     item->d_func()->setIsMemberOfGroup(true);
 10537     prepareGeometryChange();
 10563     prepareGeometryChange();
 10538     d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect());
 10564     d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect());
 10539     update();
 10565     update();
 10554         qWarning("QGraphicsItemGroup::removeFromGroup: cannot remove null item");
 10580         qWarning("QGraphicsItemGroup::removeFromGroup: cannot remove null item");
 10555         return;
 10581         return;
 10556     }
 10582     }
 10557 
 10583 
 10558     QGraphicsItem *newParent = d_ptr->parent;
 10584     QGraphicsItem *newParent = d_ptr->parent;
       
 10585 
       
 10586     // COMBINE
       
 10587     bool ok;
       
 10588     QTransform itemTransform;
       
 10589     if (newParent)
       
 10590         itemTransform = item->itemTransform(newParent, &ok);
       
 10591     else
       
 10592         itemTransform = item->sceneTransform();
       
 10593 
 10559     QPointF oldPos = item->mapToItem(newParent, 0, 0);
 10594     QPointF oldPos = item->mapToItem(newParent, 0, 0);
 10560     item->setParentItem(newParent);
 10595     item->setParentItem(newParent);
 10561     // ### This function should remap the item's matrix to keep the item's
       
 10562     // transformation unchanged relative to the scene.
       
 10563     item->setPos(oldPos);
 10596     item->setPos(oldPos);
       
 10597 
       
 10598     // removing position from translation component of the new transform
       
 10599     if (!item->pos().isNull())
       
 10600         itemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
       
 10601 
       
 10602     // removing additional transformations properties applied
       
 10603     // with itemTransform() or sceneTransform()
       
 10604     QPointF origin = item->transformOriginPoint();
       
 10605     QMatrix4x4 m;
       
 10606     QList<QGraphicsTransform*> transformList = item->transformations();
       
 10607     for (int i = 0; i < transformList.size(); ++i)
       
 10608         transformList.at(i)->applyTo(&m);
       
 10609     itemTransform *= m.toTransform().inverted();
       
 10610     itemTransform.translate(origin.x(), origin.y());
       
 10611     itemTransform.rotate(-item->rotation());
       
 10612     itemTransform.scale(1 / item->scale(), 1 / item->scale());
       
 10613     itemTransform.translate(-origin.x(), -origin.y());
       
 10614 
       
 10615     // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
       
 10616 
       
 10617     item->setTransform(itemTransform);
 10564     item->d_func()->setIsMemberOfGroup(item->group() != 0);
 10618     item->d_func()->setIsMemberOfGroup(item->group() != 0);
 10565 
 10619 
 10566     // ### Quite expensive. But removeFromGroup() isn't called very often.
 10620     // ### Quite expensive. But removeFromGroup() isn't called very often.
 10567     prepareGeometryChange();
 10621     prepareGeometryChange();
 10568     d->itemsBoundingRect = childrenBoundingRect();
 10622     d->itemsBoundingRect = childrenBoundingRect();
 10615 int QGraphicsItemGroup::type() const
 10669 int QGraphicsItemGroup::type() const
 10616 {
 10670 {
 10617     return Type;
 10671     return Type;
 10618 }
 10672 }
 10619 
 10673 
       
 10674 #ifndef QT_NO_GRAPHICSEFFECT
 10620 QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
 10675 QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
 10621 {
 10676 {
 10622     const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
 10677     const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
 10623     if (!info && deviceCoordinates) {
 10678     if (!info && deviceCoordinates) {
 10624         // Device coordinates without info not yet supported.
 10679         // Device coordinates without info not yet supported.
 10658                      info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
 10713                      info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
 10659                      info->drawItem);
 10714                      info->drawItem);
 10660     }
 10715     }
 10661 }
 10716 }
 10662 
 10717 
 10663 QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
 10718 QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
       
 10719                                                  QGraphicsEffect::PixmapPadMode mode) const
 10664 {
 10720 {
 10665     const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
 10721     const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
 10666     if (!info && deviceCoordinates) {
 10722     if (!info && deviceCoordinates) {
 10667         // Device coordinates without info not yet supported.
 10723         // Device coordinates without info not yet supported.
 10668         qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
 10724         qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
 10669         return QPixmap();
 10725         return QPixmap();
 10670     }
 10726     }
 10671 
       
 10672     if (!item->d_ptr->scene)
 10727     if (!item->d_ptr->scene)
 10673         return QPixmap();
 10728         return QPixmap();
 10674     QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
 10729     QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
 10675 
 10730 
 10676     const QRectF sourceRect = boundingRect(system);
 10731     const QRectF sourceRect = boundingRect(system);
 10677     QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
 10732     QRectF effectRectF;
       
 10733 
       
 10734     bool unpadded = false;
       
 10735     if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) {
       
 10736         if (info) {
       
 10737             effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates));
       
 10738             unpadded = (effectRectF.size() == sourceRect.size());
       
 10739             if (info && system == Qt::LogicalCoordinates)
       
 10740                 effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF);
       
 10741         } else {
       
 10742             // no choice but to send a logical coordinate bounding rect to boundingRectFor
       
 10743             effectRectF = item->graphicsEffect()->boundingRectFor(sourceRect);
       
 10744         }
       
 10745     } else if (mode == QGraphicsEffect::PadToTransparentBorder) {
       
 10746         // adjust by 1.5 to account for cosmetic pens
       
 10747         effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5);
       
 10748     } else {
       
 10749         effectRectF = sourceRect;
       
 10750         unpadded = true;
       
 10751     }
       
 10752 
       
 10753     QRect effectRect = effectRectF.toAlignedRect();
       
 10754 
 10678     if (offset)
 10755     if (offset)
 10679         *offset = effectRect.topLeft();
 10756         *offset = effectRect.topLeft();
       
 10757 
       
 10758     bool untransformed = !deviceCoordinates
       
 10759             || info->painter->worldTransform().type() <= QTransform::TxTranslate;
       
 10760     if (untransformed && unpadded && isPixmap()) {
       
 10761         if (offset)
       
 10762             *offset = boundingRect(system).topLeft().toPoint();
       
 10763         return static_cast<QGraphicsPixmapItem *>(item)->pixmap();
       
 10764     }
 10680 
 10765 
 10681     if (deviceCoordinates) {
 10766     if (deviceCoordinates) {
 10682         // Clip to viewport rect.
 10767         // Clip to viewport rect.
 10683         int left, top, right, bottom;
 10768         int left, top, right, bottom;
 10684         effectRect.getCoords(&left, &top, &right, &bottom);
 10769         effectRect.getCoords(&left, &top, &right, &bottom);
 10700             effectRect.setRight(deviceWidth - 1);
 10785             effectRect.setRight(deviceWidth - 1);
 10701         if (bottom + 1 > deviceHeight)
 10786         if (bottom + 1 > deviceHeight)
 10702             effectRect.setBottom(deviceHeight -1);
 10787             effectRect.setBottom(deviceHeight -1);
 10703 
 10788 
 10704     }
 10789     }
 10705 
       
 10706     if (effectRect.isEmpty())
 10790     if (effectRect.isEmpty())
 10707         return QPixmap();
 10791         return QPixmap();
 10708 
 10792 
 10709     QPixmap pixmap(effectRect.size());
 10793     QPixmap pixmap(effectRect.size());
 10710     pixmap.fill(Qt::transparent);
 10794     pixmap.fill(Qt::transparent);
 10738 
 10822 
 10739     pixmapPainter.end();
 10823     pixmapPainter.end();
 10740 
 10824 
 10741     return pixmap;
 10825     return pixmap;
 10742 }
 10826 }
       
 10827 #endif //QT_NO_GRAPHICSEFFECT
 10743 
 10828 
 10744 #ifndef QT_NO_DEBUG_STREAM
 10829 #ifndef QT_NO_DEBUG_STREAM
 10745 QDebug operator<<(QDebug debug, QGraphicsItem *item)
 10830 QDebug operator<<(QDebug debug, QGraphicsItem *item)
 10746 {
 10831 {
 10747     if (!item) {
 10832     if (!item) {
 10748         debug << "QGraphicsItem(0)";
 10833         debug << "QGraphicsItem(0)";
 10749         return debug;
 10834         return debug;
 10750     }
 10835     }
 10751 
 10836 
 10752     debug << "QGraphicsItem(this =" << ((void*)item)
 10837     if (QGraphicsObject *o = item->toGraphicsObject())
 10753           << ", parent =" << ((void*)item->parentItem())
 10838         debug << o->metaObject()->className();
       
 10839     else
       
 10840         debug << "QGraphicsItem";
       
 10841     debug << "(this =" << (void*)item
       
 10842           << ", parent =" << (void*)item->parentItem()
 10754           << ", pos =" << item->pos()
 10843           << ", pos =" << item->pos()
 10755           << ", z =" << item->zValue() << ", flags = "
 10844           << ", z =" << item->zValue() << ", flags = "
 10756           << item->flags() << ")";
 10845           << item->flags() << ")";
 10757     return debug;
 10846     return debug;
 10758 }
 10847 }
 10857         str = "ItemOpacityChange";
 10946         str = "ItemOpacityChange";
 10858         break;
 10947         break;
 10859     case QGraphicsItem::ItemOpacityHasChanged:
 10948     case QGraphicsItem::ItemOpacityHasChanged:
 10860         str = "ItemOpacityHasChanged";
 10949         str = "ItemOpacityHasChanged";
 10861         break;
 10950         break;
       
 10951     case QGraphicsItem::ItemScenePositionHasChanged:
       
 10952         str = "ItemScenePositionHasChanged";
       
 10953         break;
 10862     }
 10954     }
 10863     debug << str;
 10955     debug << str;
 10864     return debug;
 10956     return debug;
 10865 }
 10957 }
 10866 
 10958 
 10914         str = "ItemIsPanel";
 11006         str = "ItemIsPanel";
 10915         break;
 11007         break;
 10916     case QGraphicsItem::ItemIsFocusScope:
 11008     case QGraphicsItem::ItemIsFocusScope:
 10917         str = "ItemIsFocusScope";
 11009         str = "ItemIsFocusScope";
 10918         break;
 11010         break;
       
 11011     case QGraphicsItem::ItemSendsScenePositionChanges:
       
 11012         str = "ItemSendsScenePositionChanges";
       
 11013         break;
 10919     }
 11014     }
 10920     debug << str;
 11015     debug << str;
 10921     return debug;
 11016     return debug;
 10922 }
 11017 }
 10923 
 11018