From afb5bf71c942d411d6102ce637bc7499d8ae467c Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 21 Jan 2014 23:40:50 +0200 Subject: [PATCH] Positioners: fix layout mirroring MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- src/quick/items/qquickpositioners.cpp | 80 +++++++++++++++++----- src/quick/items/qquickpositioners_p.h | 4 ++ src/quick/items/qquickpositioners_p_p.h | 8 ++- .../qquickpositioners/tst_qquickpositioners.cpp | 8 +++ 4 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index c72c227..0ef871b 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -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::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::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(); } } diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index eaccdf7..bbb8319 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -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; diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h index 835c592..c045003 100644 --- a/src/quick/items/qquickpositioners_p_p.h +++ b/src/quick/items/qquickpositioners_p_p.h @@ -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 diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp index 6900848..e63ff66 100644 --- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp +++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp @@ -1968,6 +1968,14 @@ void tst_qquickpositioners::test_mirroring() QQuickItem *itemA = rootA->findChild(objectName); QQuickItem *itemB = rootB->findChild(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 -- 2.7.4