diff options
author | Daiwei Li <daiweili@suitabletech.com> | 2015-01-27 18:47:20 -0800 |
---|---|---|
committer | Daiwei Li <daiweili@suitabletech.com> | 2015-02-05 10:09:47 +0000 |
commit | 13f53d45037629ad27b93e7a817dc0567dea5e66 (patch) | |
tree | 860eebe4735b259faad48b2fcf69c3602d0fd8fa | |
parent | 5f7f27759e23fb1e5f3779a580adcf5bb6d5ecd6 (diff) | |
download | qtquickcontrols-13f53d45037629ad27b93e7a817dc0567dea5e66.tar.gz |
Fix crash when invalidating a layout while rearranging
Queue the invalidations and upates while rearranging and
apply them after. If we do them during, we can delete the
items being arranged, leading to a crash.
Change-Id: Ic3fe25c52afd1c8d36644f3cf7e3377ba3bec9c1
Task-number: QTBUG-44139
Reviewed-by: Jan Arve Sæther <jan-arve.saether@theqtcompany.com>
-rw-r--r-- | src/layouts/qquicklinearlayout.cpp | 21 | ||||
-rw-r--r-- | src/layouts/qquicklinearlayout_p.h | 5 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_gridlayout.qml | 31 |
3 files changed, 57 insertions, 0 deletions
diff --git a/src/layouts/qquicklinearlayout.cpp b/src/layouts/qquicklinearlayout.cpp index d2fb1933..6c9c59f4 100644 --- a/src/layouts/qquicklinearlayout.cpp +++ b/src/layouts/qquicklinearlayout.cpp @@ -390,6 +390,11 @@ void QQuickGridLayoutBase::invalidate(QQuickItem *childItem) Q_D(QQuickGridLayoutBase); if (!isReady()) return; + if (d->m_rearranging) { + d->m_invalidateAfterRearrange << childItem; + return; + } + quickLayoutDebug() << "QQuickGridLayoutBase::invalidate()"; if (childItem) { @@ -429,6 +434,11 @@ void QQuickGridLayoutBase::updateLayoutItems() Q_D(QQuickGridLayoutBase); if (!isReady()) return; + if (d->m_rearranging) { + d->m_updateAfterRearrange = true; + return; + } + quickLayoutDebug() << "QQuickGridLayoutBase::updateLayoutItems"; d->engine.deleteItems(); insertLayoutItems(); @@ -548,6 +558,7 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size) if (!isReady()) return; + d->m_rearranging = true; quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::rearrange()" << size; Qt::LayoutDirection visualDir = effectiveLayoutDirection(); d->engine.setVisualDirection(visualDir); @@ -563,6 +574,16 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size) // This could happen if there is a binding like implicitWidth: height QQuickLayout::rearrange(size); d->engine.setGeometries(QRectF(QPointF(0,0), size), d->styleInfo); + d->m_rearranging = false; + + foreach (QQuickItem *invalid, d->m_invalidateAfterRearrange) + invalidate(invalid); + d->m_invalidateAfterRearrange.clear(); + + if (d->m_updateAfterRearrange) { + updateLayoutItems(); + d->m_updateAfterRearrange = false; + } } bool QQuickGridLayoutBase::shouldIgnoreItem(QQuickItem *child, QQuickLayoutAttached *&info, QSizeF *sizeHints) diff --git a/src/layouts/qquicklinearlayout_p.h b/src/layouts/qquicklinearlayout_p.h index 931ef2cb..aaab2248 100644 --- a/src/layouts/qquicklinearlayout_p.h +++ b/src/layouts/qquicklinearlayout_p.h @@ -107,6 +107,8 @@ class QQuickGridLayoutBasePrivate : public QQuickLayoutPrivate public: QQuickGridLayoutBasePrivate() : m_disableRearrange(true) , m_isReady(false) + , m_rearranging(false) + , m_updateAfterRearrange(false) , m_layoutDirection(Qt::LeftToRight) {} @@ -120,6 +122,9 @@ public: Qt::Orientation orientation; unsigned m_disableRearrange : 1; unsigned m_isReady : 1; + unsigned m_rearranging : 1; + unsigned m_updateAfterRearrange : 1; + QVector<QQuickItem *> m_invalidateAfterRearrange; Qt::LayoutDirection m_layoutDirection : 2; QSet<QQuickItem *> m_ignoredItems; diff --git a/tests/auto/controls/data/tst_gridlayout.qml b/tests/auto/controls/data/tst_gridlayout.qml index e3d9a66b..8b271f02 100644 --- a/tests/auto/controls/data/tst_gridlayout.qml +++ b/tests/auto/controls/data/tst_gridlayout.qml @@ -924,5 +924,36 @@ Item { layout.destroy() } + + Component { + id: layout_invalidateWhileRearranging_Component + + GridLayout { + columns: 1 + Rectangle { + height: 50 + Layout.fillWidth: true + color: 'blue' + } + + Rectangle { + height: 50 + Layout.fillWidth: true + color: 'red' + onYChanged: { + visible = false; + } + } + } + } + + function test_invalidateWhileRearranging_QTBUG_44139() + { + var layout = layout_invalidateWhileRearranging_Component.createObject(container) + + waitForRendering(layout); + verify(layout.children[1].visible == false); + layout.destroy() + } } } |