src/declarative/graphicsitems/qdeclarativepositioners.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
--- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp	Fri Sep 17 08:34:18 2010 +0300
+++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp	Mon Oct 04 01:19:32 2010 +0300
@@ -61,16 +61,37 @@
     | 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()));
+        QObject::connect(other, SIGNAL(opacityChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+        QObject::connect(other, SIGNAL(visibleChanged()), 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()));
+        QObject::disconnect(other, SIGNAL(opacityChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+        QObject::disconnect(other, SIGNAL(visibleChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+    }
+}
+
+void QDeclarativeBasePositioner::graphicsWidgetGeometryChanged()
+{
+    prePositioning();
 }
 
 /*!
@@ -87,8 +108,7 @@
     You also need to set a PositionerType, to declare whether you are positioning the x, y or both
     for the child items. Depending on the chosen type, only x or y changes will be applied.
 
-    Note that the subclass is responsible for adding the
-    spacing in between items.
+    Note that the subclass is responsible for adding the spacing in between items.
 */
 QDeclarativeBasePositioner::QDeclarativeBasePositioner(PositionerType at, QDeclarativeItem *parent)
     : QDeclarativeItem(*(new QDeclarativeBasePositionerPrivate), parent)
@@ -174,16 +194,16 @@
     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 +214,6 @@
             prePositioning();
         }
     }
-
     return QDeclarativeItem::itemChange(change, value);
 }
 
@@ -216,10 +235,10 @@
     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));
+        QGraphicsItemPrivate *childPrivate = static_cast<QGraphicsItemPrivate*>(QGraphicsItemPrivate::get(child));
         PositionedItem *item = 0;
         PositionedItem posItem(child);
         int wIdx = oldItems.find(posItem);
@@ -228,13 +247,13 @@
             positionedItems.append(posItem);
             item = &positionedItems[positionedItems.count()-1];
             item->isNew = true;
-            if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden)
+            if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height())
                 item->isVisible = false;
         } else {
             item = &oldItems[wIdx];
             // Items are only omitted from positioning if they are explicitly hidden
             // i.e. their positioning is not affected if an ancestor is hidden.
-            if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden) {
+            if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) {
                 item->isVisible = false;
             } else if (!item->isVisible) {
                 item->isVisible = true;
@@ -302,14 +321,9 @@
     d->moveActions.clear();
 }
 
-static inline bool isInvisible(QDeclarativeItem *child)
-{
-    QDeclarativeItemPrivate *childPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(child));
-    return child->opacity() == 0.0 || childPrivate->explicitlyHidden || !child->width() || !child->height();
-}
-
 /*!
   \qmlclass Column QDeclarativeColumn
+    \ingroup qml-positioning-elements
     \since 4.7
   \brief The Column item arranges its children vertically.
   \inherits Item
@@ -418,11 +432,6 @@
   \image spacing_b.png
 
 */
-/*!
-    \internal
-    \class QDeclarativeColumn
-    \brief The QDeclarativeColumn class lines up items vertically.
-*/
 QDeclarativeColumn::QDeclarativeColumn(QDeclarativeItem *parent)
 : QDeclarativeBasePositioner(Vertical, parent)
 {
@@ -434,15 +443,15 @@
 
     for (int ii = 0; ii < positionedItems.count(); ++ii) {
         const PositionedItem &child = positionedItems.at(ii);
-        if (!child.item || isInvisible(child.item))
+        if (!child.item || !child.isVisible)
             continue;
 
         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 +463,8 @@
     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 ||
@@ -475,6 +484,7 @@
 
 /*!
   \qmlclass Row QDeclarativeRow
+    \ingroup qml-positioning-elements
   \since 4.7
   \brief The Row item arranges its children horizontally.
   \inherits Item
@@ -557,11 +567,6 @@
   \image spacing_b.png
 
 */
-/*!
-    \internal
-    \class QDeclarativeRow
-    \brief The QDeclarativeRow class lines up items horizontally.
-*/
 QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent)
 : QDeclarativeBasePositioner(Horizontal, parent)
 {
@@ -573,15 +578,15 @@
 
     for (int ii = 0; ii < positionedItems.count(); ++ii) {
         const PositionedItem &child = positionedItems.at(ii);
-        if (!child.item || isInvisible(child.item))
+        if (!child.item || !child.isVisible)
             continue;
 
         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 +598,8 @@
     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 ||
@@ -613,6 +618,7 @@
 
 /*!
   \qmlclass Grid QDeclarativeGrid
+    \ingroup qml-positioning-elements
   \since 4.7
   \brief The Grid item positions its children in a grid.
   \inherits Item
@@ -713,11 +719,6 @@
   \image spacing_b.png
 
 */
-/*!
-    \internal
-    \class QDeclarativeGrid
-    \brief The QDeclarativeGrid class lays out items in a grid.
-*/
 QDeclarativeGrid::QDeclarativeGrid(QDeclarativeItem *parent) :
     QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight)
 {
@@ -786,9 +787,17 @@
 
 void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
 {
+
     int c = m_columns;
     int r = m_rows;
-    int numVisible = positionedItems.count();
+    //Is allocating the extra QPODVector too much overhead?
+    QPODVector<PositionedItem, 8> visibleItems;//we aren't concerned with invisible items
+    visibleItems.reserve(positionedItems.count());
+    for(int i=0; i<positionedItems.count(); i++)
+        if(positionedItems[i].item && positionedItems[i].isVisible)
+            visibleItems.append(positionedItems[i]);
+
+    int numVisible = visibleItems.count();
     if (m_columns <= 0 && m_rows <= 0){
         c = 4;
         r = (numVisible+3)/4;
@@ -809,15 +818,15 @@
                 if (i==0)
                     maxColWidth << 0;
 
-                if (childIndex == positionedItems.count())
-                    continue;
-                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();
+                if (childIndex == visibleItems.count())
+                    break;
+
+                const PositionedItem &child = visibleItems.at(childIndex++);
+                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 {
@@ -829,14 +838,14 @@
                     maxColWidth << 0;
 
                 if (childIndex == positionedItems.count())
-                    continue;
-                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();
+                    break;
+
+                const PositionedItem &child = visibleItems.at(childIndex++);
+                QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
+                if (childPrivate->width() > maxColWidth[j])
+                    maxColWidth[j] = childPrivate->width();
+                if (childPrivate->height() > maxRowHeight[i])
+                    maxRowHeight[i] = childPrivate->height();
             }
         }
     }
@@ -845,17 +854,15 @@
     int yoffset=0;
     int curRow =0;
     int curCol =0;
-    for (int i = 0; i < positionedItems.count(); ++i) {
-        const PositionedItem &child = positionedItems.at(i);
-        if (!child.item || isInvisible(child.item))
-            continue;
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        const PositionedItem &child = visibleItems.at(i);
         if((child.item->x()!=xoffset)||(child.item->y()!=yoffset)){
             positionX(xoffset, child);
             positionY(yoffset, child);
         }
 
         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 +876,7 @@
                     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 +898,8 @@
     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;
@@ -905,6 +912,7 @@
 
 /*!
   \qmlclass Flow QDeclarativeFlow
+    \ingroup qml-positioning-elements
   \since 4.7
   \brief The Flow item arranges its children side by side, wrapping as necessary.
   \inherits Item
@@ -1023,17 +1031,18 @@
 
     for (int i = 0; i < positionedItems.count(); ++i) {
         const PositionedItem &child = positionedItems.at(i);
-        if (!child.item || isInvisible(child.item))
+        if (!child.item || !child.isVisible)
             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 +1054,17 @@
             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 +1074,8 @@
     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;