src/gui/graphicsview/qgraphicsitem.cpp
branchRCL_3
changeset 5 d3bac044e0f0
parent 4 3b1da2848fc7
child 8 3f74d0d4af4c
equal deleted inserted replaced
4:3b1da2848fc7 5:d3bac044e0f0
   266 
   266 
   267     \sa QGraphicsScene, QGraphicsView, {The Graphics View Framework}
   267     \sa QGraphicsScene, QGraphicsView, {The Graphics View Framework}
   268 */
   268 */
   269 
   269 
   270 /*!
   270 /*!
       
   271     \variable QGraphicsItem::Type
       
   272 
       
   273     The type value returned by the virtual type() function in standard
       
   274     graphics item classes in Qt. All such standard graphics item
       
   275     classes in Qt are associated with a unique value for Type,
       
   276     e.g. the value returned by QGraphicsPathItem::type() is 2.
       
   277 
       
   278     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 18
       
   279 */
       
   280 
       
   281 /*!
   271     \variable QGraphicsItem::UserType
   282     \variable QGraphicsItem::UserType
   272 
   283 
   273     The lowest permitted type value for custom items (subclasses
   284     The lowest permitted type value for custom items (subclasses
   274     of QGraphicsItem or any of the standard items). This value is
   285     of QGraphicsItem or any of the standard items). This value is
   275     used in conjunction with a reimplementation of QGraphicsItem::type()
   286     used in conjunction with a reimplementation of QGraphicsItem::type()
   276     and declaring a Type enum value. Example:
   287     and declaring a Type enum value. Example:
   277 
   288 
   278     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 1
   289     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 1
       
   290 
       
   291     \note UserType = 65536
   279 */
   292 */
   280 
   293 
   281 /*!
   294 /*!
   282     \enum QGraphicsItem::GraphicsItemFlag
   295     \enum QGraphicsItem::GraphicsItemFlag
   283 
   296 
   796             || (int(childFlag) == -1 && handlesChildEvents)
   809             || (int(childFlag) == -1 && handlesChildEvents)
   797             || (int(childFlag) == -2 && filtersDescendantEvents))
   810             || (int(childFlag) == -2 && filtersDescendantEvents))
   798             return;
   811             return;
   799     }
   812     }
   800 
   813 
   801     foreach (QGraphicsItem *child, children)
   814     for (int i = 0; i < children.size(); ++i)
   802         child->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false);
   815         children.at(i)->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false);
       
   816 }
       
   817 
       
   818 void QGraphicsItemPrivate::updateAncestorFlags()
       
   819 {
       
   820     int flags = 0;
       
   821     if (parent) {
       
   822         // Inherit the parent's ancestor flags.
       
   823         QGraphicsItemPrivate *pd = parent->d_ptr.data();
       
   824         flags = pd->ancestorFlags;
       
   825 
       
   826         // Add in flags from the parent.
       
   827         if (pd->filtersDescendantEvents)
       
   828             flags |= AncestorFiltersChildEvents;
       
   829         if (pd->handlesChildEvents)
       
   830             flags |= AncestorHandlesChildEvents;
       
   831         if (pd->flags & QGraphicsItem::ItemClipsChildrenToShape)
       
   832             flags |= AncestorClipsChildren;
       
   833         if (pd->flags & QGraphicsItem::ItemIgnoresTransformations)
       
   834             flags |= AncestorIgnoresTransformations;
       
   835     }
       
   836 
       
   837     if (ancestorFlags == flags)
       
   838         return; // No change; stop propagation.
       
   839     ancestorFlags = flags;
       
   840 
       
   841     // Propagate to children recursively.
       
   842     for (int i = 0; i < children.size(); ++i)
       
   843         children.at(i)->d_ptr->updateAncestorFlags();
   803 }
   844 }
   804 
   845 
   805 /*!
   846 /*!
   806     \internal
   847     \internal
   807 
   848 
   982 
  1023 
   983     Make sure not to trigger any pure virtual function calls (e.g.,
  1024     Make sure not to trigger any pure virtual function calls (e.g.,
   984     prepareGeometryChange) if the item is in its destructor, i.e.
  1025     prepareGeometryChange) if the item is in its destructor, i.e.
   985     inDestructor is 1.
  1026     inDestructor is 1.
   986 */
  1027 */
   987 void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
  1028 void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const QVariant *newParentVariant,
       
  1029                                                const QVariant *thisPointerVariant)
   988 {
  1030 {
   989     Q_Q(QGraphicsItem);
  1031     Q_Q(QGraphicsItem);
   990     if (newParent == q) {
       
   991         qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
       
   992         return;
       
   993     }
       
   994     if (newParent == parent)
  1032     if (newParent == parent)
   995         return;
  1033         return;
   996 
  1034 
   997     const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange,
       
   998                                                   qVariantFromValue<QGraphicsItem *>(newParent)));
       
   999     newParent = qVariantValue<QGraphicsItem *>(newParentVariant);
       
  1000     if (newParent == parent)
       
  1001         return;
       
  1002 
       
  1003     if (scene) {
  1035     if (scene) {
  1004         // Deliver the change to the index
  1036         // Deliver the change to the index
  1005         scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant);
  1037         if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
       
  1038             scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParent);
  1006 
  1039 
  1007         // Disable scene pos notifications for old ancestors
  1040         // Disable scene pos notifications for old ancestors
  1008         if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
  1041         if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
  1009             scene->d_func()->setScenePosItemEnabled(q, false);
  1042             scene->d_func()->setScenePosItemEnabled(q, false);
  1010     }
  1043     }
  1018     // removed from the index at a later stage, and the whole scene will be
  1051     // removed from the index at a later stage, and the whole scene will be
  1019     // updated.
  1052     // updated.
  1020     if (!inDestructor)
  1053     if (!inDestructor)
  1021         q_ptr->prepareGeometryChange();
  1054         q_ptr->prepareGeometryChange();
  1022 
  1055 
  1023     const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(q));
       
  1024     if (parent) {
  1056     if (parent) {
  1025         // Remove from current parent
  1057         // Remove from current parent
  1026         parent->d_ptr->removeChild(q);
  1058         parent->d_ptr->removeChild(q);
  1027         parent->itemChange(QGraphicsItem::ItemChildRemovedChange, thisPointerVariant);
  1059         if (thisPointerVariant)
       
  1060             parent->itemChange(QGraphicsItem::ItemChildRemovedChange, *thisPointerVariant);
  1028     }
  1061     }
  1029 
  1062 
  1030     // Update toplevelitem list. If this item is being deleted, its parent
  1063     // Update toplevelitem list. If this item is being deleted, its parent
  1031     // will be 0 but we don't want to register/unregister it in the TLI list.
  1064     // will be 0 but we don't want to register/unregister it in the TLI list.
  1032     if (scene && !inDestructor) {
  1065     if (scene && !inDestructor) {
  1040     // Ensure any last parent focus scope does not point to this item or any of
  1073     // Ensure any last parent focus scope does not point to this item or any of
  1041     // its descendents.
  1074     // its descendents.
  1042     QGraphicsItem *p = parent;
  1075     QGraphicsItem *p = parent;
  1043     QGraphicsItem *parentFocusScopeItem = 0;
  1076     QGraphicsItem *parentFocusScopeItem = 0;
  1044     while (p) {
  1077     while (p) {
  1045         if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  1078         if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
  1046             // If this item's focus scope's focus scope item points
  1079             // If this item's focus scope's focus scope item points
  1047             // to this item or a descendent, then clear it.
  1080             // to this item or a descendent, then clear it.
  1048             QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
  1081             QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
  1049             if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
  1082             if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
  1050                 parentFocusScopeItem = fsi;
  1083                 parentFocusScopeItem = fsi;
  1053             break;
  1086             break;
  1054         }
  1087         }
  1055         p = p->d_ptr->parent;
  1088         p = p->d_ptr->parent;
  1056     }
  1089     }
  1057 
  1090 
       
  1091     // Update graphics effect optimization flag
       
  1092     if (newParent && (graphicsEffect || mayHaveChildWithGraphicsEffect))
       
  1093         newParent->d_ptr->updateChildWithGraphicsEffectFlagRecursively();
       
  1094 
  1058     // Update focus scope item ptr in new scope.
  1095     // Update focus scope item ptr in new scope.
  1059     QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
  1096     QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
  1060     if (newFocusScopeItem && newParent) {
  1097     if (newFocusScopeItem && newParent) {
  1061         if (subFocusItem) {
  1098         if (subFocusItem) {
  1062             // Find the subFocusItem's topmost focus scope.
  1099             // Find the subFocusItem's topmost focus scope.
  1063             QGraphicsItem *ancestorScope = 0;
  1100             QGraphicsItem *ancestorScope = 0;
  1064             QGraphicsItem *p = subFocusItem->d_ptr->parent;
  1101             QGraphicsItem *p = subFocusItem->d_ptr->parent;
  1065             while (p) {
  1102             while (p) {
  1066                 if (p->flags() & QGraphicsItem::ItemIsFocusScope)
  1103                 if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope)
  1067                     ancestorScope = p;
  1104                     ancestorScope = p;
  1068                 if (p->isPanel())
  1105                 if (p->d_ptr->flags & QGraphicsItem::ItemIsPanel)
  1069                     break;
  1106                     break;
  1070                 p = p->parentItem();
  1107                 p = p->d_ptr->parent;
  1071             }
  1108             }
  1072             if (ancestorScope)
  1109             if (ancestorScope)
  1073                 newFocusScopeItem = ancestorScope;
  1110                 newFocusScopeItem = ancestorScope;
  1074         }
  1111         }
  1075 
  1112 
  1076         QGraphicsItem *p = newParent;
  1113         QGraphicsItem *p = newParent;
  1077         while (p) {
  1114         while (p) {
  1078             if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
  1115             if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
  1079                 p->d_ptr->focusScopeItem = newFocusScopeItem;
  1116                 p->d_ptr->focusScopeItem = newFocusScopeItem;
  1080                 // Ensure the new item is no longer the subFocusItem. The
  1117                 // Ensure the new item is no longer the subFocusItem. The
  1081                 // only way to set focus on a child of a focus scope is
  1118                 // only way to set focus on a child of a focus scope is
  1082                 // by setting focus on the scope itself.
  1119                 // by setting focus on the scope itself.
  1083                 if (subFocusItem && !p->focusItem())
  1120                 if (subFocusItem && !p->focusItem())
  1087             p = p->d_ptr->parent;
  1124             p = p->d_ptr->parent;
  1088         }
  1125         }
  1089     }
  1126     }
  1090 
  1127 
  1091     if ((parent = newParent)) {
  1128     if ((parent = newParent)) {
  1092         bool implicitUpdate = false;
       
  1093         if (parent->d_func()->scene && parent->d_func()->scene != scene) {
  1129         if (parent->d_func()->scene && parent->d_func()->scene != scene) {
  1094             // Move this item to its new parent's scene
  1130             // Move this item to its new parent's scene
  1095             parent->d_func()->scene->addItem(q);
  1131             parent->d_func()->scene->addItem(q);
  1096             implicitUpdate = true;
       
  1097         } else if (!parent->d_func()->scene && scene) {
  1132         } else if (!parent->d_func()->scene && scene) {
  1098             // Remove this item from its former scene
  1133             // Remove this item from its former scene
  1099             scene->removeItem(q);
  1134             scene->removeItem(q);
  1100         }
  1135         }
  1101 
  1136 
  1102         parent->d_ptr->addChild(q);
  1137         parent->d_ptr->addChild(q);
  1103         parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
  1138         if (thisPointerVariant)
       
  1139             parent->itemChange(QGraphicsItem::ItemChildAddedChange, *thisPointerVariant);
  1104         if (scene) {
  1140         if (scene) {
  1105             if (!implicitUpdate)
       
  1106                 scene->d_func()->markDirty(q_ptr);
       
  1107 
       
  1108             // Re-enable scene pos notifications for new ancestors
  1141             // Re-enable scene pos notifications for new ancestors
  1109             if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
  1142             if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
  1110                 scene->d_func()->setScenePosItemEnabled(q, true);
  1143                 scene->d_func()->setScenePosItemEnabled(q, true);
  1111         }
  1144         }
  1112 
  1145 
       
  1146         // Propagate dirty flags to the new parent
       
  1147         markParentDirty(/*updateBoundingRect=*/true);
       
  1148 
  1113         // Inherit ancestor flags from the new parent.
  1149         // Inherit ancestor flags from the new parent.
  1114         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
  1150         updateAncestorFlags();
  1115         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
       
  1116         updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
       
  1117         updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
       
  1118 
  1151 
  1119         // Update item visible / enabled.
  1152         // Update item visible / enabled.
  1120         if (parent->isVisible() != visible) {
  1153         if (parent->d_ptr->visible != visible) {
  1121             if (!parent->isVisible() || !explicitlyHidden)
  1154             if (!parent->d_ptr->visible || !explicitlyHidden)
  1122                 setVisibleHelper(parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
  1155                 setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ false);
  1123         }
  1156         }
  1124         if (parent->isEnabled() != enabled) {
  1157         if (parent->isEnabled() != enabled) {
  1125             if (!parent->isEnabled() || !explicitlyDisabled)
  1158             if (!parent->d_ptr->enabled || !explicitlyDisabled)
  1126                 setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
  1159                 setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ false);
  1127         }
  1160         }
  1128 
  1161 
  1129         // Auto-activate if visible and the parent is active.
  1162         // Auto-activate if visible and the parent is active.
  1130         if (q->isVisible() && parent->isActive())
  1163         if (visible && parent->isActive())
  1131             q->setActive(true);
  1164             q->setActive(true);
  1132     } else {
  1165     } else {
  1133         // Inherit ancestor flags from the new parent.
  1166         // Inherit ancestor flags from the new parent.
  1134         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
  1167         updateAncestorFlags();
  1135         updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
       
  1136         updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
       
  1137         updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
       
  1138 
  1168 
  1139         if (!inDestructor) {
  1169         if (!inDestructor) {
  1140             // Update item visible / enabled.
  1170             // Update item visible / enabled.
  1141             if (!visible && !explicitlyHidden)
  1171             if (!visible && !explicitlyHidden)
  1142                 setVisibleHelper(true, /* explicit = */ false);
  1172                 setVisibleHelper(true, /* explicit = */ false);
  1143             if (!enabled && !explicitlyDisabled)
  1173             if (!enabled && !explicitlyDisabled)
  1144                 setEnabledHelper(true, /* explicit = */ false);
  1174                 setEnabledHelper(true, /* explicit = */ false);
  1145 
       
  1146             // If the item is being deleted, the whole scene will be updated.
       
  1147             if (scene)
       
  1148                 scene->d_func()->markDirty(q_ptr);
       
  1149         }
  1175         }
  1150     }
  1176     }
  1151 
  1177 
  1152     // Resolve depth.
  1178     // Resolve depth.
  1153     invalidateDepthRecursively();
  1179     invalidateDepthRecursively();
  1159         if (parent && parent->isActive())
  1185         if (parent && parent->isActive())
  1160             subFocusItem->setFocus();
  1186             subFocusItem->setFocus();
  1161     }
  1187     }
  1162 
  1188 
  1163     // Deliver post-change notification
  1189     // Deliver post-change notification
  1164     q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
  1190     if (newParentVariant)
       
  1191         q->itemChange(QGraphicsItem::ItemParentHasChanged, *newParentVariant);
  1165 
  1192 
  1166     if (isObject)
  1193     if (isObject)
  1167         emit static_cast<QGraphicsObject *>(q)->parentChanged();
  1194         emit static_cast<QGraphicsObject *>(q)->parentChanged();
  1168 }
  1195 }
  1169 
  1196 
  1348 
  1375 
  1349     if (d_ptr->scene) {
  1376     if (d_ptr->scene) {
  1350         d_ptr->scene->d_func()->removeItemHelper(this);
  1377         d_ptr->scene->d_func()->removeItemHelper(this);
  1351     } else {
  1378     } else {
  1352         d_ptr->resetFocusProxy();
  1379         d_ptr->resetFocusProxy();
  1353         d_ptr->setParentItemHelper(0);
  1380         setParentItem(0);
  1354     }
  1381     }
  1355 
  1382 
  1356 #ifndef QT_NO_GRAPHICSEFFECT
  1383 #ifndef QT_NO_GRAPHICSEFFECT
  1357     delete d_ptr->graphicsEffect;
  1384     delete d_ptr->graphicsEffect;
  1358 #endif //QT_NO_GRAPHICSEFFECT
  1385 #endif //QT_NO_GRAPHICSEFFECT
  1541 {
  1568 {
  1542     return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0;
  1569     return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0;
  1543 }
  1570 }
  1544 
  1571 
  1545 /*!
  1572 /*!
  1546     Sets this item's parent item to \a parent. If this item already has a
  1573   Sets this item's parent item to \a newParent. If this item already
  1547     parent, it is first removed from the previous parent. If \a parent is 0,
  1574   has a parent, it is first removed from the previous parent. If \a
  1548     this item will become a top-level item.
  1575   newParent is 0, this item will become a top-level item.
  1549 
  1576 
  1550     Note that this implicitly adds this graphics item to the scene of
  1577   Note that this implicitly adds this graphics item to the scene of
  1551     the parent. You should not \l{QGraphicsScene::addItem()}{add} the
  1578   the parent. You should not \l{QGraphicsScene::addItem()}{add} the
  1552     item to the scene yourself.
  1579   item to the scene yourself.
  1553 
  1580 
  1554     Calling this function on an item that is an ancestor of \a parent have undefined behaviour.
  1581   Calling this function on an item that is an ancestor of \a newParent
  1555 
  1582   have undefined behaviour.
  1556     \sa parentItem(), childItems()
  1583 
  1557 */
  1584   \sa parentItem(), childItems()
  1558 void QGraphicsItem::setParentItem(QGraphicsItem *parent)
  1585 */
  1559 {
  1586 void QGraphicsItem::setParentItem(QGraphicsItem *newParent)
  1560     d_ptr->setParentItemHelper(parent);
  1587 {
       
  1588     if (newParent == this) {
       
  1589         qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
       
  1590         return;
       
  1591     }
       
  1592     if (newParent == d_ptr->parent)
       
  1593         return;
       
  1594 
       
  1595     const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange,
       
  1596                                                qVariantFromValue<QGraphicsItem *>(newParent)));
       
  1597     newParent = qVariantValue<QGraphicsItem *>(newParentVariant);
       
  1598     if (newParent == d_ptr->parent)
       
  1599         return;
       
  1600 
       
  1601     const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this));
       
  1602     d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant);
  1561 }
  1603 }
  1562 
  1604 
  1563 /*!
  1605 /*!
  1564     \obsolete
  1606     \obsolete
  1565 
  1607 
  1605 
  1647 
  1606     \sa QGraphicsWidget::windowFlags()
  1648     \sa QGraphicsWidget::windowFlags()
  1607 */
  1649 */
  1608 bool QGraphicsItem::isWindow() const
  1650 bool QGraphicsItem::isWindow() const
  1609 {
  1651 {
  1610     return isWidget() && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
  1652     return d_ptr->isWidget && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
  1611 }
  1653 }
  1612 
  1654 
  1613 /*!
  1655 /*!
  1614     \since 4.6
  1656     \since 4.6
  1615     Returns true if the item is a panel; otherwise returns false.
  1657     Returns true if the item is a panel; otherwise returns false.
  1642     \sa flags(), setFlags()
  1684     \sa flags(), setFlags()
  1643 */
  1685 */
  1644 void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled)
  1686 void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled)
  1645 {
  1687 {
  1646     if (enabled)
  1688     if (enabled)
  1647         setFlags(flags() | flag);
  1689         setFlags(GraphicsItemFlags(d_ptr->flags) | flag);
  1648     else
  1690     else
  1649         setFlags(flags() & ~flag);
  1691         setFlags(GraphicsItemFlags(d_ptr->flags) & ~flag);
  1650 }
  1692 }
  1651 
  1693 
  1652 /*!
  1694 /*!
  1653     \internal
  1695     \internal
  1654 
  1696 
  1691     if (quint32(d_ptr->flags) == quint32(flags))
  1733     if (quint32(d_ptr->flags) == quint32(flags))
  1692         return;
  1734         return;
  1693     flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt());
  1735     flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt());
  1694     if (quint32(d_ptr->flags) == quint32(flags))
  1736     if (quint32(d_ptr->flags) == quint32(flags))
  1695         return;
  1737         return;
  1696     if (d_ptr->scene)
  1738     if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
  1697         d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags));
  1739         d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, &flags);
  1698 
  1740 
  1699     // Flags that alter the geometry of the item (or its children).
  1741     // Flags that alter the geometry of the item (or its children).
  1700     const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable);
  1742     const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable);
  1701     bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
  1743     bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
  1702     if (fullUpdate)
  1744     if (fullUpdate)
  1703         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  1745         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  1704 
  1746 
  1705     // Keep the old flags to compare the diff.
  1747     // Keep the old flags to compare the diff.
  1706     GraphicsItemFlags oldFlags = this->flags();
  1748     GraphicsItemFlags oldFlags = GraphicsItemFlags(d_ptr->flags);
  1707 
  1749 
  1708     // Update flags.
  1750     // Update flags.
  1709     d_ptr->flags = flags;
  1751     d_ptr->flags = flags;
  1710 
  1752 
  1711     if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
  1753     if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
  1730         // Item children clipping changes. Propagate the ancestor flag to
  1772         // Item children clipping changes. Propagate the ancestor flag to
  1731         // all children.
  1773         // all children.
  1732         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
  1774         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
  1733     }
  1775     }
  1734 
  1776 
       
  1777     if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) {
       
  1778         // NB! We change the flags directly here, so we must also update d_ptr->flags.
       
  1779         // Note that this has do be done before the ItemStacksBehindParent check
       
  1780         // below; otherwise we will loose the change.
       
  1781 
       
  1782         // Update stack-behind.
       
  1783         if (d_ptr->z < qreal(0.0))
       
  1784             flags |= ItemStacksBehindParent;
       
  1785         else
       
  1786             flags &= ~ItemStacksBehindParent;
       
  1787         d_ptr->flags = flags;
       
  1788     }
       
  1789 
  1735     if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
  1790     if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
       
  1791         // NB! This check has to come after the ItemNegativeZStacksBehindParent
       
  1792         // check above. Be careful.
       
  1793 
  1736         // Ensure child item sorting is up to date when toggling this flag.
  1794         // Ensure child item sorting is up to date when toggling this flag.
  1737         if (d_ptr->parent)
  1795         if (d_ptr->parent)
  1738             d_ptr->parent->d_ptr->needSortChildren = 1;
  1796             d_ptr->parent->d_ptr->needSortChildren = 1;
  1739         else if (d_ptr->scene)
  1797         else if (d_ptr->scene)
  1740             d_ptr->scene->d_func()->needSortTopLevelItems = 1;
  1798             d_ptr->scene->d_func()->needSortTopLevelItems = 1;
  1744         // Update input method sensitivity in any views.
  1802         // Update input method sensitivity in any views.
  1745         if (d_ptr->scene)
  1803         if (d_ptr->scene)
  1746             d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
  1804             d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
  1747     }
  1805     }
  1748 
  1806 
  1749     if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) {
       
  1750         // Update stack-behind.
       
  1751         setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0));
       
  1752     }
       
  1753 
  1807 
  1754     if ((d_ptr->panelModality != NonModal)
  1808     if ((d_ptr->panelModality != NonModal)
  1755         && d_ptr->scene
  1809         && d_ptr->scene
  1756         && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
  1810         && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
  1757         // update the panel's modal state
  1811         // update the panel's modal state
  2521     itemChange(ItemOpacityHasChanged, newOpacityVariant);
  2575     itemChange(ItemOpacityHasChanged, newOpacityVariant);
  2522 
  2576 
  2523     // Update.
  2577     // Update.
  2524     if (d_ptr->scene) {
  2578     if (d_ptr->scene) {
  2525 #ifndef QT_NO_GRAPHICSEFFECT
  2579 #ifndef QT_NO_GRAPHICSEFFECT
  2526         d_ptr->invalidateGraphicsEffectsRecursively();
  2580         d_ptr->invalidateParentGraphicsEffectsRecursively();
       
  2581         if (!(d_ptr->flags & ItemDoesntPropagateOpacityToChildren))
       
  2582             d_ptr->invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::OpacityChanged);
  2527 #endif //QT_NO_GRAPHICSEFFECT
  2583 #endif //QT_NO_GRAPHICSEFFECT
  2528         d_ptr->scene->d_func()->markDirty(this, QRectF(),
  2584         d_ptr->scene->d_func()->markDirty(this, QRectF(),
  2529                                           /*invalidateChildren=*/true,
  2585                                           /*invalidateChildren=*/true,
  2530                                           /*force=*/false,
  2586                                           /*force=*/false,
  2531                                           /*ignoreOpacity=*/true);
  2587                                           /*ignoreOpacity=*/true);
  2566         return;
  2622         return;
  2567 
  2623 
  2568     if (d_ptr->graphicsEffect) {
  2624     if (d_ptr->graphicsEffect) {
  2569         delete d_ptr->graphicsEffect;
  2625         delete d_ptr->graphicsEffect;
  2570         d_ptr->graphicsEffect = 0;
  2626         d_ptr->graphicsEffect = 0;
       
  2627     } else if (d_ptr->parent) {
       
  2628         d_ptr->parent->d_ptr->updateChildWithGraphicsEffectFlagRecursively();
  2571     }
  2629     }
  2572 
  2630 
  2573     if (effect) {
  2631     if (effect) {
  2574         // Set new effect.
  2632         // Set new effect.
  2575         QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
  2633         QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
  2578         effect->d_func()->setGraphicsEffectSource(source);
  2636         effect->d_func()->setGraphicsEffectSource(source);
  2579         prepareGeometryChange();
  2637         prepareGeometryChange();
  2580     }
  2638     }
  2581 }
  2639 }
  2582 #endif //QT_NO_GRAPHICSEFFECT
  2640 #endif //QT_NO_GRAPHICSEFFECT
       
  2641 
       
  2642 void QGraphicsItemPrivate::updateChildWithGraphicsEffectFlagRecursively()
       
  2643 {
       
  2644 #ifndef QT_NO_GRAPHICSEFFECT
       
  2645     QGraphicsItemPrivate *itemPrivate = this;
       
  2646     do {
       
  2647         // parent chain already notified?
       
  2648         if (itemPrivate->mayHaveChildWithGraphicsEffect)
       
  2649             return;
       
  2650         itemPrivate->mayHaveChildWithGraphicsEffect = 1;
       
  2651     } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
       
  2652 #endif
       
  2653 }
  2583 
  2654 
  2584 /*!
  2655 /*!
  2585     \internal
  2656     \internal
  2586     \since 4.6
  2657     \since 4.6
  2587     Returns the effective bounding rect of the given item space rect.
  2658     Returns the effective bounding rect of the given item space rect.
  4262     const QVariant newZVariant(itemChange(ItemZValueChange, z));
  4333     const QVariant newZVariant(itemChange(ItemZValueChange, z));
  4263     qreal newZ = newZVariant.toReal();
  4334     qreal newZ = newZVariant.toReal();
  4264     if (newZ == d_ptr->z)
  4335     if (newZ == d_ptr->z)
  4265         return;
  4336         return;
  4266 
  4337 
  4267     if (d_ptr->scene) {
  4338     if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) {
  4268         // Z Value has changed, we have to notify the index.
  4339         // Z Value has changed, we have to notify the index.
  4269         d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant);
  4340         d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, &newZ);
  4270     }
  4341     }
  4271 
  4342 
  4272     d_ptr->z = newZ;
  4343     d_ptr->z = newZ;
  4273     if (d_ptr->parent)
  4344     if (d_ptr->parent)
  4274         d_ptr->parent->d_ptr->needSortChildren = 1;
  4345         d_ptr->parent->d_ptr->needSortChildren = 1;
  5031 
  5102 
  5032 /*!
  5103 /*!
  5033     \internal
  5104     \internal
  5034 */
  5105 */
  5035 #ifndef QT_NO_GRAPHICSEFFECT
  5106 #ifndef QT_NO_GRAPHICSEFFECT
  5036 void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively()
  5107 void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively()
  5037 {
  5108 {
  5038     QGraphicsItemPrivate *itemPrivate = this;
  5109     QGraphicsItemPrivate *itemPrivate = this;
  5039     do {
  5110     do {
  5040         if (itemPrivate->graphicsEffect) {
  5111         if (itemPrivate->graphicsEffect) {
  5041             itemPrivate->notifyInvalidated = 1;
  5112             itemPrivate->notifyInvalidated = 1;
  5042 
  5113 
  5043             if (!itemPrivate->updateDueToGraphicsEffect)
  5114             if (!itemPrivate->updateDueToGraphicsEffect)
  5044                 static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
  5115                 static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
  5045         }
  5116         }
  5046     } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
  5117     } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
       
  5118 }
       
  5119 
       
  5120 void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason)
       
  5121 {
       
  5122     if (!mayHaveChildWithGraphicsEffect)
       
  5123         return;
       
  5124 
       
  5125     for (int i = 0; i < children.size(); ++i) {
       
  5126         QGraphicsItemPrivate *childPrivate = children.at(i)->d_ptr.data();
       
  5127         if (reason == OpacityChanged && (childPrivate->flags & QGraphicsItem::ItemIgnoresParentOpacity))
       
  5128             continue;
       
  5129         if (childPrivate->graphicsEffect) {
       
  5130             childPrivate->notifyInvalidated = 1;
       
  5131             static_cast<QGraphicsItemEffectSourcePrivate *>(childPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
       
  5132         }
       
  5133 
       
  5134         childPrivate->invalidateChildGraphicsEffectsRecursively(reason);
       
  5135     }
  5047 }
  5136 }
  5048 #endif //QT_NO_GRAPHICSEFFECT
  5137 #endif //QT_NO_GRAPHICSEFFECT
  5049 
  5138 
  5050 /*!
  5139 /*!
  5051     \internal
  5140     \internal
  5287     if (rect.isEmpty() && !rect.isNull())
  5376     if (rect.isEmpty() && !rect.isNull())
  5288         return;
  5377         return;
  5289 
  5378 
  5290     // Make sure we notify effects about invalidated source.
  5379     // Make sure we notify effects about invalidated source.
  5291 #ifndef QT_NO_GRAPHICSEFFECT
  5380 #ifndef QT_NO_GRAPHICSEFFECT
  5292     d_ptr->invalidateGraphicsEffectsRecursively();
  5381     d_ptr->invalidateParentGraphicsEffectsRecursively();
  5293 #endif //QT_NO_GRAPHICSEFFECT
  5382 #endif //QT_NO_GRAPHICSEFFECT
  5294 
  5383 
  5295     if (CacheMode(d_ptr->cacheMode) != NoCache) {
  5384     if (CacheMode(d_ptr->cacheMode) != NoCache) {
  5296         // Invalidate cache.
  5385         // Invalidate cache.
  5297         QGraphicsItemCache *cache = d_ptr->extraItemCache();
  5386         QGraphicsItemCache *cache = d_ptr->extraItemCache();
  7163         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  7252         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
  7164         d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
  7253         d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
  7165 
  7254 
  7166         QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
  7255         QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
  7167         scenePrivate->index->prepareBoundingRectChange(this);
  7256         scenePrivate->index->prepareBoundingRectChange(this);
  7168         scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true);
  7257         scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*force=*/false,
       
  7258                                 /*ignoreOpacity=*/ false, /*removingItemFromScene=*/ false,
       
  7259                                 /*updateBoundingRect=*/true);
  7169 
  7260 
  7170         // For compatibility reasons, we have to update the item's old geometry
  7261         // For compatibility reasons, we have to update the item's old geometry
  7171         // if someone is connected to the changed signal or the scene has no views.
  7262         // if someone is connected to the changed signal or the scene has no views.
  7172         // Note that this has to be done *after* markDirty to ensure that
  7263         // Note that this has to be done *after* markDirty to ensure that
  7173         // _q_processDirtyItems is called before _q_emitUpdated.
  7264         // _q_processDirtyItems is called before _q_emitUpdated.
  7180                 d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect()));
  7271                 d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect()));
  7181             }
  7272             }
  7182         }
  7273         }
  7183     }
  7274     }
  7184 
  7275 
  7185     QGraphicsItem *parent = this;
  7276     d_ptr->markParentDirty(/*updateBoundingRect=*/true);
  7186     while ((parent = parent->d_ptr->parent)) {
       
  7187         QGraphicsItemPrivate *parentp = parent->d_ptr.data();
       
  7188         parentp->dirtyChildrenBoundingRect = 1;
       
  7189         // ### Only do this if the parent's effect applies to the entire subtree.
       
  7190         parentp->notifyBoundingRectChanged = 1;
       
  7191 #ifndef QT_NO_GRAPHICSEFFECT
       
  7192         if (parentp->scene && parentp->graphicsEffect) {
       
  7193             parentp->notifyInvalidated = 1;
       
  7194             static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()->source->d_func())->invalidateCache();
       
  7195         }
       
  7196 #endif
       
  7197     }
       
  7198 }
  7277 }
  7199 
  7278 
  7200 /*!
  7279 /*!
  7201     \internal
  7280     \internal
  7202 
  7281