From bc5ae286c891e40aed6f483d78eac43905ea5c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Tue, 9 Mar 2021 10:13:57 +0100 Subject: DelegateModelGroup: Fix bug where item could be removed from the model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an item was removed from the DelegateModelGroup before it was completed it caused subsequent items in the model to be missing in some cases. The reason was that while populating the ListView, it iterated with an index for each item to call createItem() on. However, createItem() might call onCompleted (which in the case of QTBUG-86708 removed the item from the DelegateModel), which caused the next index we called createItem() with to be wrong (it became one step ahead). We therefore add a helper class MutableModelIterator, which keeps track of if a index in the model got removed (and if the iterator index needs to be adjusted because of that).... Task-number: QTBUG-86708 Change-Id: I33537b43727aed4f2b9bdda794b011b6684c44b4 Reviewed-by: Richard Moe Gustavsen (cherry picked from commit 0ff9db566c48172c688bf9327fe6a781dc4a1c34) Reviewed-by: Jan Arve Sæther --- tests/auto/qml/qqmldelegatemodel/CMakeLists.txt | 1 + .../qml/qqmldelegatemodel/data/removeFromGroup.qml | 45 ++++++++++++++++++++++ .../qml/qqmldelegatemodel/qqmldelegatemodel.pro | 2 +- .../qqmldelegatemodel/tst_qqmldelegatemodel.cpp | 15 ++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/auto/qml/qqmldelegatemodel/data/removeFromGroup.qml (limited to 'tests/auto') diff --git a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt index ef31fa3db3..9020d9e892 100644 --- a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt +++ b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt @@ -22,6 +22,7 @@ qt_internal_add_test(tst_qqmldelegatemodel Qt::Qml Qt::QmlModelsPrivate Qt::QmlPrivate + Qt::Quick TESTDATA ${test_data} ) diff --git a/tests/auto/qml/qqmldelegatemodel/data/removeFromGroup.qml b/tests/auto/qml/qqmldelegatemodel/data/removeFromGroup.qml new file mode 100644 index 0000000000..4ae1a8aacc --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/removeFromGroup.qml @@ -0,0 +1,45 @@ +import QtQuick 2.8 +import QtQml.Models 2.1 + +Item { + id: root + width: 200 + height: 200 + + DelegateModel { + id: visualModel + model: ListModel { + id: myLM + ListElement { + name: "Apple" + } + ListElement { + name: "Banana" + } + ListElement { + name: "Orange" + } + } + filterOnGroup: "selected" + groups: [ + DelegateModelGroup { + name: "selected" + includeByDefault: true + } + ] + delegate: Text { + Component.onCompleted: { + if (index === 1) { + DelegateModel.inSelected = false + } + } + text: index + ": " + model.name + } + } + + // Needs an actual ListView in order for the DelegateModel to instantiate all items + ListView { + model: visualModel + anchors.fill: parent + } +} diff --git a/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro index 7fdd3ab5f1..fbd72f6a44 100644 --- a/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro +++ b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro @@ -2,7 +2,7 @@ CONFIG += testcase TARGET = tst_qqmldelegatemodel macos:CONFIG -= app_bundle -QT += qml testlib core-private qml-private qmlmodels-private +QT += qml quick testlib core-private qml-private qmlmodels-private SOURCES += tst_qqmldelegatemodel.cpp diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp index 87f42c0c8a..71550a50f3 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "../../shared/util.h" @@ -42,6 +44,7 @@ public: private slots: void valueWithoutCallingObjectFirst_data(); void valueWithoutCallingObjectFirst(); + void filterOnGroup_removeWhenCompleted(); }; class AbstractItemModel : public QAbstractItemModel @@ -134,6 +137,18 @@ void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst() QCOMPARE(model->variantValue(index, role), expectedValue); } +void tst_QQmlDelegateModel::filterOnGroup_removeWhenCompleted() +{ + QQuickView view(testFileUrl("removeFromGroup.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + QQuickItem *root = view.rootObject(); + QVERIFY(root); + QQmlDelegateModel *model = root->findChild(); + QVERIFY(model); + QTest::qWaitFor([=]{ return model->count() == 2; } ); +} + QTEST_MAIN(tst_QQmlDelegateModel) #include "tst_qqmldelegatemodel.moc" -- cgit v1.2.3