From 8ae7f9508a94e37ceddd4c2b1b94dc43ff039cf3 Mon Sep 17 00:00:00 2001
From: Martin Jones <martin.jones@nokia.com>
Date: Mon, 16 Aug 2010 13:38:54 +1000
Subject: Make positioners work with QGraphicsWidgets also

Task-number: QTBUG-12416
Reviewed-by: Alexis Menard
---
 .../graphicsitems/qdeclarativepositioners.cpp      | 107 ++++++++++++---------
 .../graphicsitems/qdeclarativepositioners_p.h      |   8 +-
 .../graphicsitems/qdeclarativepositioners_p_p.h    |   5 +-
 3 files changed, 71 insertions(+), 49 deletions(-)

diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp
index 179f13d..f32c532 100644
--- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp
@@ -61,16 +61,33 @@ static const QDeclarativeItemPrivate::ChangeTypes watchedChanges
     | QDeclarativeItemPrivate::Opacity
     | QDeclarativeItemPrivate::Destroyed;
 
-void QDeclarativeBasePositionerPrivate::watchChanges(QDeclarativeItem *other)
+void QDeclarativeBasePositionerPrivate::watchChanges(QGraphicsObject *other)
 {
-    QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
-    otherPrivate->addItemChangeListener(this, watchedChanges);
+    if (QGraphicsItemPrivate::get(other)->isDeclarativeItem) {
+        QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
+        otherPrivate->addItemChangeListener(this, watchedChanges);
+    } else {
+        Q_Q(QDeclarativeBasePositioner);
+        QObject::connect(other, SIGNAL(widthChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+        QObject::connect(other, SIGNAL(heightChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+    }
 }
 
-void QDeclarativeBasePositionerPrivate::unwatchChanges(QDeclarativeItem* other)
+void QDeclarativeBasePositionerPrivate::unwatchChanges(QGraphicsObject* other)
 {
-    QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
-    otherPrivate->removeItemChangeListener(this, watchedChanges);
+    if (QGraphicsItemPrivate::get(other)->isDeclarativeItem) {
+        QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
+        otherPrivate->removeItemChangeListener(this, watchedChanges);
+    } else {
+        Q_Q(QDeclarativeBasePositioner);
+        QObject::disconnect(other, SIGNAL(widthChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+        QObject::disconnect(other, SIGNAL(heightChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+    }
+}
+
+void QDeclarativeBasePositioner::graphicsWidgetGeometryChanged()
+{
+    prePositioning();
 }
 
 /*!
@@ -174,16 +191,16 @@ QVariant QDeclarativeBasePositioner::itemChange(GraphicsItemChange change,
     Q_D(QDeclarativeBasePositioner);
     if (change == ItemChildAddedChange){
         QGraphicsItem* item = value.value<QGraphicsItem*>();
-        QDeclarativeItem* child = 0;
+        QGraphicsObject* child = 0;
         if(item)
-            child = qobject_cast<QDeclarativeItem*>(item->toGraphicsObject());
+            child = item->toGraphicsObject();
         if (child)
             prePositioning();
     } else if (change == ItemChildRemovedChange) {
         QGraphicsItem* item = value.value<QGraphicsItem*>();
-        QDeclarativeItem* child = 0;
+        QGraphicsObject* child = 0;
         if(item)
-            child = qobject_cast<QDeclarativeItem*>(item->toGraphicsObject());
+            child = item->toGraphicsObject();
         if (child) {
             QDeclarativeBasePositioner::PositionedItem posItem(child);
             int idx = positionedItems.find(posItem);
@@ -194,7 +211,6 @@ QVariant QDeclarativeBasePositioner::itemChange(GraphicsItemChange change,
             prePositioning();
         }
     }
-
     return QDeclarativeItem::itemChange(change, value);
 }
 
@@ -216,7 +232,7 @@ void QDeclarativeBasePositioner::prePositioning()
     QPODVector<PositionedItem,8> oldItems;
     positionedItems.copyAndClear(oldItems);
     for (int ii = 0; ii < children.count(); ++ii) {
-        QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(ii));
+        QGraphicsObject *child = children.at(ii)->toGraphicsObject();
         if (!child)
             continue;
         QDeclarativeItemPrivate *childPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(child));
@@ -302,10 +318,10 @@ void QDeclarativeBasePositioner::finishApplyTransitions()
     d->moveActions.clear();
 }
 
-static inline bool isInvisible(QDeclarativeItem *child)
+static inline bool isInvisible(QGraphicsObject *child)
 {
     QDeclarativeItemPrivate *childPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(child));
-    return child->opacity() == 0.0 || childPrivate->explicitlyHidden || !child->width() || !child->height();
+    return child->opacity() == 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height();
 }
 
 /*!
@@ -440,9 +456,9 @@ void QDeclarativeColumn::doPositioning(QSizeF *contentSize)
         if(child.item->y() != voffset)
             positionY(voffset, child);
 
-        contentSize->setWidth(qMax(contentSize->width(), child.item->width()));
+        contentSize->setWidth(qMax(contentSize->width(), QGraphicsItemPrivate::get(child.item)->width()));
 
-        voffset += child.item->height();
+        voffset += QGraphicsItemPrivate::get(child.item)->height();
         voffset += spacing();
     }
 
@@ -454,8 +470,8 @@ void QDeclarativeColumn::reportConflictingAnchors()
     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
     for (int ii = 0; ii < positionedItems.count(); ++ii) {
         const PositionedItem &child = positionedItems.at(ii);
-        if (child.item) {
-            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(child.item)->_anchors;
+        if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
             if (anchors) {
                 QDeclarativeAnchors::Anchors usedAnchors = anchors->usedAnchors();
                 if (usedAnchors & QDeclarativeAnchors::TopAnchor ||
@@ -579,9 +595,9 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize)
         if(child.item->x() != hoffset)
             positionX(hoffset, child);
 
-        contentSize->setHeight(qMax(contentSize->height(), child.item->height()));
+        contentSize->setHeight(qMax(contentSize->height(), QGraphicsItemPrivate::get(child.item)->height()));
 
-        hoffset += child.item->width();
+        hoffset += QGraphicsItemPrivate::get(child.item)->width();
         hoffset += spacing();
     }
 
@@ -593,8 +609,8 @@ void QDeclarativeRow::reportConflictingAnchors()
     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
     for (int ii = 0; ii < positionedItems.count(); ++ii) {
         const PositionedItem &child = positionedItems.at(ii);
-        if (child.item) {
-            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(child.item)->_anchors;
+        if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
             if (anchors) {
                 QDeclarativeAnchors::Anchors usedAnchors = anchors->usedAnchors();
                 if (usedAnchors & QDeclarativeAnchors::LeftAnchor ||
@@ -814,10 +830,11 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
                 const PositionedItem &child = positionedItems.at(childIndex++);
                 if (!child.item || isInvisible(child.item))
                     continue;
-                if (child.item->width() > maxColWidth[j])
-                    maxColWidth[j] = child.item->width();
-                if (child.item->height() > maxRowHeight[i])
-                    maxRowHeight[i] = child.item->height();
+                QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
+                if (childPrivate->width() > maxColWidth[j])
+                    maxColWidth[j] = childPrivate->width();
+                if (childPrivate->height() > maxRowHeight[i])
+                    maxRowHeight[i] = childPrivate->height();
             }
         }
     } else {
@@ -833,10 +850,11 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
                 const PositionedItem &child = positionedItems.at(childIndex++);
                 if (!child.item || isInvisible(child.item))
                     continue;
-                if (child.item->width() > maxColWidth[j])
-                    maxColWidth[j] = child.item->width();
-                if (child.item->height() > maxRowHeight[i])
-                    maxRowHeight[i] = child.item->height();
+                QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
+                if (childPrivate->width() > maxColWidth[j])
+                    maxColWidth[j] = childPrivate->width();
+                if (childPrivate->height() > maxRowHeight[i])
+                    maxRowHeight[i] = childPrivate->height();
             }
         }
     }
@@ -855,7 +873,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
         }
 
         if (m_flow == LeftToRight) {
-            contentSize->setWidth(qMax(contentSize->width(), xoffset + child.item->width()));
+            contentSize->setWidth(qMax(contentSize->width(), xoffset + QGraphicsItemPrivate::get(child.item)->width()));
             contentSize->setHeight(yoffset + maxRowHeight[curRow]);
 
             xoffset+=maxColWidth[curCol]+spacing();
@@ -869,7 +887,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
                     break;
             }
         } else {
-            contentSize->setHeight(qMax(contentSize->height(), yoffset + child.item->height()));
+            contentSize->setHeight(qMax(contentSize->height(), yoffset + QGraphicsItemPrivate::get(child.item)->height()));
             contentSize->setWidth(xoffset + maxColWidth[curCol]);
 
             yoffset+=maxRowHeight[curRow]+spacing();
@@ -891,8 +909,8 @@ void QDeclarativeGrid::reportConflictingAnchors()
     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
     for (int ii = 0; ii < positionedItems.count(); ++ii) {
         const PositionedItem &child = positionedItems.at(ii);
-        if (child.item) {
-            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(child.item)->_anchors;
+        if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
             if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
                 d->anchorConflict = true;
                 break;
@@ -1026,14 +1044,15 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize)
         if (!child.item || isInvisible(child.item))
             continue;
 
+        QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
         if (d->flow == LeftToRight)  {
-            if (widthValid() && hoffset && hoffset + child.item->width() > width()) {
+            if (widthValid() && hoffset && hoffset + childPrivate->width() > width()) {
                 hoffset = 0;
                 voffset += linemax + spacing();
                 linemax = 0;
             }
         } else {
-            if (heightValid() && voffset && voffset + child.item->height() > height()) {
+            if (heightValid() && voffset && voffset + childPrivate->height() > height()) {
                 voffset = 0;
                 hoffset += linemax + spacing();
                 linemax = 0;
@@ -1045,17 +1064,17 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize)
             positionY(voffset, child);
         }
 
-        contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width()));
-        contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height()));
+        contentSize->setWidth(qMax(contentSize->width(), hoffset + childPrivate->width()));
+        contentSize->setHeight(qMax(contentSize->height(), voffset + childPrivate->height()));
 
         if (d->flow == LeftToRight)  {
-            hoffset += child.item->width();
+            hoffset += childPrivate->width();
             hoffset += spacing();
-            linemax = qMax(linemax, qCeil(child.item->height()));
+            linemax = qMax(linemax, qCeil(childPrivate->height()));
         } else {
-            voffset += child.item->height();
+            voffset += childPrivate->height();
             voffset += spacing();
-            linemax = qMax(linemax, qCeil(child.item->width()));
+            linemax = qMax(linemax, qCeil(childPrivate->width()));
         }
     }
 }
@@ -1065,8 +1084,8 @@ void QDeclarativeFlow::reportConflictingAnchors()
     Q_D(QDeclarativeFlow);
     for (int ii = 0; ii < positionedItems.count(); ++ii) {
         const PositionedItem &child = positionedItems.at(ii);
-        if (child.item) {
-            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(child.item)->_anchors;
+        if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+            QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
             if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
                 d->anchorConflict = true;
                 break;
diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p.h
index c03e518..f9ecc0a 100644
--- a/src/declarative/graphicsitems/qdeclarativepositioners_p.h
+++ b/src/declarative/graphicsitems/qdeclarativepositioners_p.h
@@ -91,14 +91,16 @@ Q_SIGNALS:
 
 protected Q_SLOTS:
     void prePositioning();
+    void graphicsWidgetGeometryChanged();
 
 protected:
     virtual void doPositioning(QSizeF *contentSize)=0;
     virtual void reportConflictingAnchors()=0;
-    struct PositionedItem {
-        PositionedItem(QDeclarativeItem *i) : item(i), isNew(false), isVisible(true) {}
+    class PositionedItem {
+    public :
+        PositionedItem(QGraphicsObject *i) : item(i), isNew(false), isVisible(true) {}
         bool operator==(const PositionedItem &other) const { return other.item == item; }
-        QDeclarativeItem *item;
+        QGraphicsObject *item;
         bool isNew;
         bool isVisible;
     };
diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h
index 822079b..35946e9 100644
--- a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h
@@ -94,8 +94,8 @@ public:
     QDeclarativeTransitionManager addTransitionManager;
     QDeclarativeTransitionManager moveTransitionManager;
 
-    void watchChanges(QDeclarativeItem *other);
-    void unwatchChanges(QDeclarativeItem* other);
+    void watchChanges(QGraphicsObject *other);
+    void unwatchChanges(QGraphicsObject* other);
     bool queuedPositioning : 1;
     bool doingPositioning : 1;
     bool anchorConflict : 1;
@@ -123,6 +123,7 @@ public:
         if (newGeometry.size() != oldGeometry.size())
             q->prePositioning();
     }
+
     virtual void itemVisibilityChanged(QDeclarativeItem *)
     {
         schedulePositioning();
-- 
cgit v0.12