src/gui/graphicsview/qgraphicsitem_p.h
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
--- a/src/gui/graphicsview/qgraphicsitem_p.h	Tue Feb 02 00:43:10 2010 +0200
+++ b/src/gui/graphicsview/qgraphicsitem_p.h	Wed Mar 31 11:06:36 2010 +0300
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 ** All rights reserved.
 ** Contact: Nokia Corporation (qt-info@nokia.com)
 **
@@ -71,6 +71,62 @@
 
 class QGraphicsItemPrivate;
 
+#ifndef QDECLARATIVELISTPROPERTY
+#define QDECLARATIVELISTPROPERTY
+template<typename T>
+struct QDeclarativeListProperty {
+    typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
+    typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
+    typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
+    typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
+
+    QDeclarativeListProperty()
+        : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
+    QDeclarativeListProperty(QObject *o, QList<T *> &list)
+        : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
+          clear(qlist_clear), dummy1(0), dummy2(0) {}
+    QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
+                    ClearFunction r = 0)
+        : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
+
+    bool operator==(const QDeclarativeListProperty &o) const {
+        return object == o.object &&
+               data == o.data &&
+               append == o.append &&
+               count == o.count &&
+               at == o.at &&
+               clear == o.clear;
+    }
+
+    QObject *object;
+    void *data;
+
+    AppendFunction append;
+
+    CountFunction count;
+    AtFunction at;
+
+    ClearFunction clear;
+
+    void *dummy1;
+    void *dummy2;
+
+private:
+    static void qlist_append(QDeclarativeListProperty *p, T *v) {
+        ((QList<T *> *)p->data)->append(v);
+    }
+    static int qlist_count(QDeclarativeListProperty *p) {
+        return ((QList<T *> *)p->data)->count();
+    }
+    static T *qlist_at(QDeclarativeListProperty *p, int idx) {
+        return ((QList<T *> *)p->data)->at(idx);
+    }
+    static void qlist_clear(QDeclarativeListProperty *p) {
+        return ((QList<T *> *)p->data)->clear();
+    }
+};
+#endif
+
 class QGraphicsItemCache
 {
 public:
@@ -153,7 +209,7 @@
         dirtyChildren(0),
         localCollisionHack(0),
         inSetPosHelper(0),
-        needSortChildren(1), // ### can be 0 by default?
+        needSortChildren(0),
         allChildrenDirty(0),
         fullUpdatePending(0),
         flags(0),
@@ -178,6 +234,8 @@
         sequentialOrdering(1),
         updateDueToGraphicsEffect(0),
         scenePosDescendants(0),
+        pendingPolish(0),
+        mayHaveChildWithGraphicsEffect(0),
         globalStackingOrder(-1),
         q_ptr(0)
     {
@@ -195,8 +253,10 @@
         return item->d_ptr.data();
     }
 
+    void updateChildWithGraphicsEffectFlagRecursively();
     void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
                             AncestorFlag flag = NoFlag, bool enabled = false, bool root = true);
+    void updateAncestorFlags();
     void setIsMemberOfGroup(bool enabled);
     void remapItemPos(QEvent *event, QGraphicsItem *item);
     QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const;
@@ -223,13 +283,19 @@
                               bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
     int depth() const;
 #ifndef QT_NO_GRAPHICSEFFECT
-    void invalidateGraphicsEffectsRecursively();
+    enum InvalidateReason {
+        OpacityChanged
+    };
+    void invalidateParentGraphicsEffectsRecursively();
+    void invalidateChildGraphicsEffectsRecursively(InvalidateReason reason);
 #endif //QT_NO_GRAPHICSEFFECT
     void invalidateDepthRecursively();
     void resolveDepth();
     void addChild(QGraphicsItem *child);
     void removeChild(QGraphicsItem *child);
-    void setParentItemHelper(QGraphicsItem *parent);
+    QDeclarativeListProperty<QGraphicsObject> childrenList();
+    void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
+                             const QVariant *thisPointerVariant);
     void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
     void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
                          const QRegion &exposedRegion, bool allItems = false) const;
@@ -349,14 +415,20 @@
         return o;
     }
 
+    inline bool isOpacityNull() const
+    { return (opacity < qreal(0.001)); }
+
+    static inline bool isOpacityNull(qreal opacity)
+    { return (opacity < qreal(0.001)); }
+
     inline bool isFullyTransparent() const
     {
-        if (opacity < 0.001)
+        if (isOpacityNull())
             return true;
         if (!parent)
             return false;
 
-        return calcEffectiveOpacity() < 0.001;
+        return isOpacityNull(calcEffectiveOpacity());
     }
 
     inline qreal effectiveOpacity() const {
@@ -397,7 +469,10 @@
         return !visible || (childrenCombineOpacity() && isFullyTransparent());
     }
 
-    void setFocusHelper(Qt::FocusReason focusReason, bool climb);
+    inline void markParentDirty(bool updateBoundingRect = false);
+
+    void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow);
+    void clearFocusHelper(bool giveFocusToParent);
     void setSubFocus(QGraphicsItem *rootItem = 0);
     void clearSubFocus(QGraphicsItem *rootItem = 0);
     void resetFocusProxy();
@@ -405,11 +480,21 @@
 
     inline QTransform transformToParent() const;
     inline void ensureSortedChildren();
+    static void append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item);
     static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
     void ensureSequentialSiblingIndex();
     inline void sendScenePosChange();
     virtual void siblingOrderChange();
 
+    // Private Properties
+    virtual qreal width() const;
+    virtual void setWidth(qreal);
+    virtual void resetWidth();
+
+    virtual qreal height() const;
+    virtual void setHeight(qreal);
+    virtual void resetHeight();
+
     QRectF childrenBoundingRect;
     QRectF needsRepaint;
     QMap<QWidget *, QRect> paintedViewBoundingRects;
@@ -484,6 +569,8 @@
     quint32 sequentialOrdering : 1;
     quint32 updateDueToGraphicsEffect : 1;
     quint32 scenePosDescendants : 1;
+    quint32 pendingPolish : 1;
+    quint32 mayHaveChildWithGraphicsEffect : 1;
 
     // Optional stacking order
     int globalStackingOrder;
@@ -609,6 +696,7 @@
     QPixmap pixmap(Qt::CoordinateSystem system,
                    QPoint *offset,
                    QGraphicsEffect::PixmapPadMode mode) const;
+    QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const;
 
     QGraphicsItem *item;
     QGraphicsItemPaintInfo *info;
@@ -720,11 +808,13 @@
 inline void QGraphicsItemPrivate::ensureSortedChildren()
 {
     if (needSortChildren) {
-        qSort(children.begin(), children.end(), qt_notclosestLeaf);
         needSortChildren = 0;
         sequentialOrdering = 1;
+        if (children.isEmpty())
+            return;
+        qSort(children.begin(), children.end(), qt_notclosestLeaf);
         for (int i = 0; i < children.size(); ++i) {
-            if (children[i]->d_ptr->siblingIndex != i) {
+            if (children.at(i)->d_ptr->siblingIndex != i) {
                 sequentialOrdering = 0;
                 break;
             }
@@ -740,6 +830,37 @@
     return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex;
 }
 
+/*!
+    \internal
+*/
+inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect)
+{
+    QGraphicsItemPrivate *parentp = this;
+    while (parentp->parent) {
+        parentp = parentp->parent->d_ptr.data();
+        parentp->dirtyChildren = 1;
+
+        if (updateBoundingRect) {
+            parentp->dirtyChildrenBoundingRect = 1;
+            // ### Only do this if the parent's effect applies to the entire subtree.
+            parentp->notifyBoundingRectChanged = 1;
+        }
+#ifndef QT_NO_GRAPHICSEFFECT
+        if (parentp->graphicsEffect) {
+            if (updateBoundingRect) {
+                parentp->notifyInvalidated = 1;
+                static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()
+                                                                ->source->d_func())->invalidateCache();
+            }
+            if (parentp->graphicsEffect->isEnabled()) {
+                parentp->dirty = 1;
+                parentp->fullUpdatePending = 1;
+            }
+        }
+#endif
+    }
+}
+
 QT_END_NAMESPACE
 
 #endif // QT_NO_GRAPHICSVIEW