summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiwei Li <daiweili@suitabletech.com>2015-01-27 18:47:20 -0800
committerDaiwei Li <daiweili@suitabletech.com>2015-02-05 10:09:47 +0000
commit13f53d45037629ad27b93e7a817dc0567dea5e66 (patch)
tree860eebe4735b259faad48b2fcf69c3602d0fd8fa
parent5f7f27759e23fb1e5f3779a580adcf5bb6d5ecd6 (diff)
downloadqtquickcontrols-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.cpp21
-rw-r--r--src/layouts/qquicklinearlayout_p.h5
-rw-r--r--tests/auto/controls/data/tst_gridlayout.qml31
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()
+ }
}
}