Positioners: fix layout mirroring
authorJ-P Nurmi <jpnurmi@digia.com>
Tue, 21 Jan 2014 21:40:50 +0000 (23:40 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sat, 25 Jan 2014 17:26:27 +0000 (18:26 +0100)
Listen to positioner geometry changes when the _effective_ layout
direction is RTL.

Task-number: QTBUG-35095
Change-Id: If06955c6bb04e5bed2126b05489229278c192173
Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
src/quick/items/qquickpositioners.cpp
src/quick/items/qquickpositioners_p.h
src/quick/items/qquickpositioners_p_p.h
tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp

index c72c227..0ef871b 100644 (file)
@@ -869,8 +869,31 @@ void QQuickColumn::reportConflictingAnchors()
   \sa Grid::spacing
 */
 
+class QQuickRowPrivate : public QQuickBasePositionerPrivate
+{
+    Q_DECLARE_PUBLIC(QQuickRow)
+
+public:
+    QQuickRowPrivate()
+        : QQuickBasePositionerPrivate()
+    {}
+
+    void effectiveLayoutDirectionChange()
+    {
+        Q_Q(QQuickRow);
+        // For RTL layout the positioning changes when the width changes.
+        if (getEffectiveLayoutDirection(q) == Qt::RightToLeft)
+            addItemChangeListener(this, QQuickItemPrivate::Geometry);
+        else
+            removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+        // Don't postpone, as it might be the only trigger for visible changes.
+        q->prePositioning();
+        emit q->effectiveLayoutDirectionChanged();
+    }
+};
+
 QQuickRow::QQuickRow(QQuickItem *parent)
-: QQuickBasePositioner(Horizontal, parent)
+: QQuickBasePositioner(*new QQuickRowPrivate, Horizontal, parent)
 {
 }
 /*!
@@ -900,14 +923,8 @@ void QQuickRow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
     QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this));
     if (d->layoutDirection != layoutDirection) {
         d->layoutDirection = layoutDirection;
-        // For RTL layout the positioning changes when the width changes.
-        if (d->layoutDirection == Qt::RightToLeft)
-            d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
-        else
-            d->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
-        prePositioning();
         emit layoutDirectionChanged();
-        emit effectiveLayoutDirectionChanged();
+        d->effectiveLayoutDirectionChange();
     }
 }
 /*!
@@ -1111,8 +1128,33 @@ void QQuickRow::reportConflictingAnchors()
 
   \sa rows, columns
 */
+
+class QQuickGridPrivate : public QQuickBasePositionerPrivate
+{
+    Q_DECLARE_PUBLIC(QQuickGrid)
+
+public:
+    QQuickGridPrivate()
+        : QQuickBasePositionerPrivate()
+    {}
+
+    void effectiveLayoutDirectionChange()
+    {
+        Q_Q(QQuickGrid);
+        // For RTL layout the positioning changes when the width changes.
+        if (getEffectiveLayoutDirection(q) == Qt::RightToLeft)
+            addItemChangeListener(this, QQuickItemPrivate::Geometry);
+        else
+            removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+        // Don't postpone, as it might be the only trigger for visible changes.
+        q->prePositioning();
+        emit q->effectiveLayoutDirectionChanged();
+        emit q->effectiveHorizontalAlignmentChanged(q->effectiveHAlign());
+    }
+};
+
 QQuickGrid::QQuickGrid(QQuickItem *parent)
-    : QQuickBasePositioner(Both, parent)
+    : QQuickBasePositioner(*new QQuickGridPrivate, Both, parent)
     , m_rows(-1)
     , m_columns(-1)
     , m_rowSpacing(-1)
@@ -1260,15 +1302,8 @@ void QQuickGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
     QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
     if (d->layoutDirection != layoutDirection) {
         d->layoutDirection = layoutDirection;
-        // For RTL layout the positioning changes when the width changes.
-        if (d->layoutDirection == Qt::RightToLeft)
-            d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
-        else
-            d->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
-        prePositioning();
         emit layoutDirectionChanged();
-        emit effectiveLayoutDirectionChanged();
-        emit effectiveHorizontalAlignmentChanged(effectiveHAlign());
+        d->effectiveLayoutDirectionChange();
     }
 }
 
@@ -1652,6 +1687,14 @@ public:
         : QQuickBasePositionerPrivate(), flow(QQuickFlow::LeftToRight)
     {}
 
+    void effectiveLayoutDirectionChange()
+    {
+        Q_Q(QQuickFlow);
+        // Don't postpone, as it might be the only trigger for visible changes.
+        q->prePositioning();
+        emit q->effectiveLayoutDirectionChanged();
+    }
+
     QQuickFlow::Flow flow;
 };
 
@@ -1724,9 +1767,8 @@ void QQuickFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
     Q_D(QQuickFlow);
     if (d->layoutDirection != layoutDirection) {
         d->layoutDirection = layoutDirection;
-        prePositioning();
         emit layoutDirectionChanged();
-        emit effectiveLayoutDirectionChanged();
+        d->effectiveLayoutDirectionChange();
     }
 }
 
index eaccdf7..bbb8319 100644 (file)
@@ -187,6 +187,7 @@ private:
     Q_DISABLE_COPY(QQuickColumn)
 };
 
+class QQuickRowPrivate;
 class Q_AUTOTEST_EXPORT QQuickRow: public QQuickBasePositioner
 {
     Q_OBJECT
@@ -208,8 +209,10 @@ protected:
     virtual void reportConflictingAnchors();
 private:
     Q_DISABLE_COPY(QQuickRow)
+    Q_DECLARE_PRIVATE(QQuickRow)
 };
 
+class QQuickGridPrivate;
 class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner
 {
     Q_OBJECT
@@ -293,6 +296,7 @@ private:
     HAlignment m_hItemAlign;
     VAlignment m_vItemAlign;
     Q_DISABLE_COPY(QQuickGrid)
+    Q_DECLARE_PRIVATE(QQuickGrid)
 };
 
 class QQuickFlowPrivate;
index 835c592..c045003 100644 (file)
@@ -107,9 +107,7 @@ public:
     Qt::LayoutDirection layoutDirection;
 
     void mirrorChange() {
-        Q_Q(QQuickBasePositioner);
-        if (type != QQuickBasePositioner::Vertical)
-            q->prePositioning(); //Don't postpone, as it might be the only trigger for visible changes.
+        effectiveLayoutDirectionChange();
     }
     bool isLeftToRight() const {
         if (type == QQuickBasePositioner::Vertical)
@@ -155,6 +153,10 @@ public:
         else
             return positioner->d_func()->layoutDirection;
     }
+
+    virtual void effectiveLayoutDirectionChange()
+    {
+    }
 };
 
 QT_END_NAMESPACE
index 6900848..e63ff66 100644 (file)
@@ -1968,6 +1968,14 @@ void tst_qquickpositioners::test_mirroring()
             QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
             QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
             QTRY_COMPARE(itemA->x(), itemB->x());
+
+            // after resize (QTBUG-35095)
+            QQuickItem *positionerA = itemA->parentItem();
+            QQuickItem *positionerB = itemB->parentItem();
+            positionerA->setWidth(positionerA->width() * 2);
+            positionerB->setWidth(positionerB->width() * 2);
+            QTRY_VERIFY(!QQuickItemPrivate::get(positionerA)->polishScheduled && !QQuickItemPrivate::get(positionerB)->polishScheduled);
+            QTRY_COMPARE(itemA->x(), itemB->x());
         }
 
         rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight