diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-03-20 11:11:02 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-05-09 10:45:49 +0000 |
commit | 3b806a18cc665b5ae0e12d45fe170bfc3f00352a (patch) | |
tree | 1403138f7ef2d9cd832e21b9c09dca073b049db1 /src/qml/types/qqmldelegatemodel.cpp | |
parent | a393929fd149906596bd74480a561b986a87b35d (diff) |
Fix crash when using repeaters with packages
When receiving the modelUpdated signal from the delegate model, the
repeater - unlike other views - queries for the objects right away. That
may result in instant incubation and when using Packages, we will end up
delivering the initItem signal emission for the parts models via
QQmlDelegateModelGroupPrivate::initPackage for _both_ repeaters
immediately. For the first repeater that's expected, but for the second
repeater that means initItem is received before modelUpdated was called.
That is very confusing for the repeater as d->deletables is not set up
yet.
While it's possible to make the repeater more "robust" towards such
behaving models, it seems cleaner to make the model behave well, by
ensuring that we emit initItem after modelUpdated.
Task-number: QTBUG-50349
Change-Id: Id2f3ba135e34d0111c8896bb4ecdfe51c8c649da
Reviewed-by: Michael Brasser <michael.brasser@live.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/types/qqmldelegatemodel.cpp')
-rw-r--r-- | src/qml/types/qqmldelegatemodel.cpp | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 3863f9e968..1c0da2875c 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -3256,7 +3256,10 @@ void QQmlPartsModel::createdPackage(int index, QQuickPackage *package) void QQmlPartsModel::initPackage(int index, QQuickPackage *package) { - emit initItem(index, package->part(m_part)); + if (m_modelUpdatePending) + m_pendingPackageInitializations << index; + else + emit initItem(index, package->part(m_part)); } void QQmlPartsModel::destroyingPackage(QQuickPackage *package) @@ -3268,9 +3271,22 @@ void QQmlPartsModel::destroyingPackage(QQuickPackage *package) void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) { + m_modelUpdatePending = false; emit modelUpdated(changeSet, reset); if (changeSet.difference() != 0) emit countChanged(); + + QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model); + QVector<int> pendingPackageInitializations; + qSwap(pendingPackageInitializations, m_pendingPackageInitializations); + for (int index : pendingPackageInitializations) { + if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) + continue; + QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous); + if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) + emit initItem(index, package->part(m_part)); + model->release(object); + } } //============================================================================ |