src/gui/graphicsview/qgraphicsitem.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
child 22 79de32ba3296
--- a/src/gui/graphicsview/qgraphicsitem.cpp	Fri Apr 16 15:50:13 2010 +0300
+++ b/src/gui/graphicsview/qgraphicsitem.cpp	Mon May 03 13:17:34 2010 +0300
@@ -414,12 +414,6 @@
 /*!
     \enum QGraphicsItem::GraphicsItemChange
 
-        ItemVisibleHasChanged,
-        ItemEnabledHasChanged,
-        ItemSelectedHasChanged,
-        ItemParentHasChanged,
-        ItemSceneHasChanged
-
     This enum describes the state changes that are notified by
     QGraphicsItem::itemChange(). The notifications are sent as the state
     changes, and in some cases, adjustments can be made (see the documentation
@@ -647,9 +641,16 @@
     are children of a modal panel are not blocked.
 
     The values are:
-    \value NonModal   The panel is not modal and does not block input to other panels.
-    \value PanelModal The panel is modal to a single item hierarchy and blocks input to its parent pane, all grandparent panels, and all siblings of its parent and grandparent panels.
-    \value SceneModal The window is modal to the entire scene and blocks input to all panels.
+
+    \value NonModal The panel is not modal and does not block input to
+    other panels. This is the default value for panels.
+
+    \value PanelModal The panel is modal to a single item hierarchy
+    and blocks input to its parent pane, all grandparent panels, and
+    all siblings of its parent and grandparent panels.
+
+    \value SceneModal The window is modal to the entire scene and
+    blocks input to all panels.
 
     \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel
 */
@@ -1129,6 +1130,9 @@
         }
     }
 
+    // Resolve depth.
+    invalidateDepthRecursively();
+
     if ((parent = newParent)) {
         if (parent->d_func()->scene && parent->d_func()->scene != scene) {
             // Move this item to its new parent's scene
@@ -1179,8 +1183,6 @@
         }
     }
 
-    // Resolve depth.
-    invalidateDepthRecursively();
     dirtySceneTransform = 1;
 
     // Restore the sub focus chain.
@@ -1881,7 +1883,8 @@
     d_ptr->cacheMode = mode;
     bool noVisualChange = (mode == NoCache && lastMode == NoCache)
                           || (mode == NoCache && lastMode == DeviceCoordinateCache)
-                          || (mode == DeviceCoordinateCache && lastMode == NoCache);
+                          || (mode == DeviceCoordinateCache && lastMode == NoCache)
+                          || (mode == DeviceCoordinateCache && lastMode == DeviceCoordinateCache);
     if (mode == NoCache) {
         d_ptr->removeExtraItemCache();
     } else {
@@ -2175,11 +2178,16 @@
         QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
         if (c)
             c->purge();
-        if (scene)
+        if (scene) {
+#ifndef QT_NO_GRAPHICSEFFECT
+            invalidateParentGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
             scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
+        }
     }
 
     // Certain properties are dropped as an item becomes invisible.
+    bool hasFocus = q_ptr->hasFocus();
     if (!newVisible) {
         if (scene) {
             if (scene->d_func()->mouseGrabberItems.contains(q))
@@ -2189,7 +2197,7 @@
             if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
                 scene->d_func()->leaveModal(q_ptr);
         }
-        if (q_ptr->hasFocus() && scene) {
+        if (hasFocus && scene) {
             // Hiding the closest non-panel ancestor of the focus item
             QGraphicsItem *focusItem = scene->focusItem();
             bool clear = true;
@@ -2202,7 +2210,7 @@
                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
             }
             if (clear)
-                q_ptr->clearFocus();
+                clearFocusHelper(/* giveFocusToParent = */ false);
         }
         if (q_ptr->isSelected())
             q_ptr->setSelected(false);
@@ -2240,26 +2248,45 @@
     }
 
     // Enable subfocus
-    if (scene && newVisible) {
-        QGraphicsItem *p = parent;
-        bool done = false;
-        while (p) {
-            if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
-                QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
-                if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
-                    done = true;
-                    while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
-                        fsi = fsi->d_ptr->focusScopeItem;
-                    scene->setFocusItem(fsi);
+    if (scene) {
+        if (newVisible) {
+            // Item is shown
+            QGraphicsItem *p = parent;
+            bool done = false;
+            while (p) {
+                if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+                    QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
+                    if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
+                        done = true;
+                        while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
+                            fsi = fsi->d_ptr->focusScopeItem;
+                        fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
+                                                   /* focusFromShow = */ true);
+                    }
+                    break;
                 }
-                break;
+                p = p->d_ptr->parent;
+            }
+            if (!done) {
+                QGraphicsItem *fi = subFocusItem;
+                if (fi && fi != scene->focusItem()) {
+                    scene->setFocusItem(fi);
+                }
             }
-            p = p->d_ptr->parent;
-        }
-        if (!done) {
-            QGraphicsItem *fi = subFocusItem;
-            if (fi && fi != scene->focusItem()) {
-                scene->setFocusItem(fi);
+        } else {
+            // Item is hidden
+            if (hasFocus) {
+                QGraphicsItem *p = parent;
+                while (p) {
+                    if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+                        if (p->d_ptr->visible) {
+                            p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
+                                                     /* focusFromShow = */ true);
+                        }
+                        break;
+                    }
+                    p = p->d_ptr->parent;
+                }
             }
         }
     }
@@ -3110,13 +3137,13 @@
 */
 void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
 {
-    d_ptr->setFocusHelper(focusReason, /* climb = */ true);
+    d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromShow = */ false);
 }
 
 /*!
     \internal
 */
-void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb)
+void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow)
 {
     // Disabled / unfocusable items cannot accept focus.
     if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable))
@@ -3136,7 +3163,7 @@
     while (p) {
         if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
             p->d_ptr->focusScopeItem = q_ptr;
-            if (!p->focusItem()) {
+            if (!p->focusItem() && !focusFromShow) {
                 // If you call setFocus on a child of a focus scope that
                 // doesn't currently have a focus item, then stop.
                 return;
@@ -3177,24 +3204,35 @@
 */
 void QGraphicsItem::clearFocus()
 {
-    // Pass focus to the closest parent focus scope.
-    if (!d_ptr->inDestructor) {
-        QGraphicsItem *p = d_ptr->parent;
-        while (p) {
-            if (p->flags() & ItemIsFocusScope) {
-                p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false);
-                return;
+    d_ptr->clearFocusHelper(/* giveFocusToParent = */ true);
+}
+
+/*!
+    \internal
+*/
+void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent)
+{
+    if (giveFocusToParent) {
+        // Pass focus to the closest parent focus scope
+        if (!inDestructor) {
+            QGraphicsItem *p = parent;
+            while (p) {
+                if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+                    p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
+                                             /* focusFromShow = */ false);
+                    return;
+                }
+                p = p->d_ptr->parent;
             }
-            p = p->d_ptr->parent;
         }
     }
 
     // Invisible items with focus must explicitly clear subfocus.
-    d_ptr->clearSubFocus(this);
-
-    if (hasFocus()) {
+    clearSubFocus(q_ptr);
+
+    if (q_ptr->hasFocus()) {
         // If this item has the scene's input focus, clear it.
-        d_ptr->scene->setFocusItem(0);
+        scene->setFocusItem(0);
     }
 }
 
@@ -5187,6 +5225,8 @@
     needSortChildren = 1; // ### maybe 0
     child->d_ptr->siblingIndex = children.size();
     children.append(child);
+    if (isObject)
+        emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
 }
 
 /*!
@@ -5209,6 +5249,8 @@
     // the child is not guaranteed to be at the index after the list is sorted.
     // (see ensureSortedChildren()).
     child->d_ptr->siblingIndex = -1;
+    if (isObject)
+        emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
 }
 
 /*!
@@ -7416,6 +7458,88 @@
     }
 }
 
+void QGraphicsItemPrivate::append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item)
+{
+    QGraphicsItemPrivate::get(item)->setParentItemHelper(static_cast<QGraphicsObject *>(list->object), /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+}
+
+/*!
+    Returns a list of this item's children.
+
+    The items are sorted by stacking order. This takes into account both the
+    items' insertion order and their Z-values.
+
+*/
+QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList()
+{
+    Q_Q(QGraphicsItem);
+    if (isObject) {
+        QGraphicsObject *that = static_cast<QGraphicsObject *>(q);
+        return QDeclarativeListProperty<QGraphicsObject>(that, &children, QGraphicsItemPrivate::append);
+    } else {
+        //QGraphicsItem is not supported for this property
+        return QDeclarativeListProperty<QGraphicsObject>();
+    }
+}
+
+/*!
+  \internal
+  Returns the width of the item
+  Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::width() const
+{
+    return 0;
+}
+
+/*!
+  \internal
+  Set the width of the item
+  Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setWidth(qreal w)
+{
+    Q_UNUSED(w);
+}
+
+/*!
+  \internal
+  Reset the width of the item
+  Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetWidth()
+{
+}
+
+/*!
+  \internal
+  Returns the height of the item
+  Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::height() const
+{
+    return 0;
+}
+
+/*!
+  \internal
+  Set the height of the item
+  Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setHeight(qreal h)
+{
+    Q_UNUSED(h);
+}
+
+/*!
+  \internal
+  Reset the height of the item
+  Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetHeight()
+{
+}
+
 /*!
   \property QGraphicsObject::parent
   \brief the parent of the item
@@ -7602,6 +7726,23 @@
   \sa scale, rotation, QGraphicsItem::transformOriginPoint()
 */
 
+/*!
+    \fn void QGraphicsObject::widthChanged()
+    \internal
+*/
+
+/*!
+    \fn void QGraphicsObject::heightChanged()
+    \internal
+*/
+
+/*!
+
+  \fn QGraphicsObject::childrenChanged()
+
+  This signal gets emitted whenever the children list changes
+  \internal
+*/
 
 /*!
     \class QAbstractGraphicsShapeItem
@@ -10809,6 +10950,7 @@
     }
 }
 
+// sourceRect must be in the given coordinate system
 QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
 {
     QRectF effectRectF;
@@ -10818,7 +10960,8 @@
 
     if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) {
         if (info) {
-            effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates));
+            QRectF deviceRect = system == Qt::DeviceCoordinates ? sourceRect : info->painter->worldTransform().mapRect(sourceRect);
+            effectRectF = item->graphicsEffect()->boundingRectFor(deviceRect);
             if (unpadded)
                 *unpadded = (effectRectF.size() == sourceRect.size());
             if (info && system == Qt::LogicalCoordinates)
@@ -10867,30 +11010,6 @@
         return static_cast<QGraphicsPixmapItem *>(item)->pixmap();
     }
 
-    if (deviceCoordinates) {
-        // Clip to viewport rect.
-        int left, top, right, bottom;
-        effectRect.getCoords(&left, &top, &right, &bottom);
-        if (left < 0) {
-            if (offset)
-                offset->rx() += -left;
-            effectRect.setX(0);
-        }
-        if (top < 0) {
-            if (offset)
-                offset->ry() += -top;
-            effectRect.setY(0);
-        }
-        // NB! We use +-1 for historical reasons (see QRect documentation).
-        QPaintDevice *device = info->painter->device();
-        const int deviceWidth = device->width();
-        const int deviceHeight = device->height();
-        if (right + 1 > deviceWidth)
-            effectRect.setRight(deviceWidth - 1);
-        if (bottom + 1 > deviceHeight)
-            effectRect.setBottom(deviceHeight -1);
-
-    }
     if (effectRect.isEmpty())
         return QPixmap();