diff options
author | Robin Burchell <robin.burchell@viroteck.net> | 2014-11-04 18:23:45 -0800 |
---|---|---|
committer | Robin Burchell <robin.burchell@viroteck.net> | 2014-11-07 18:39:15 +0100 |
commit | 9d1cd3098a066c7b6689d4776bfd3a25621a26fc (patch) | |
tree | 382ee7f41a48d8d2feca29892a4bda3c603e477a | |
parent | b340caa0d3ebf7f76c0445b2cdd4032d8e3bf8d5 (diff) |
QQuickRepeater::clear: Remove items from the end backwards.
This way, the indices for itemRemoved will make sense consistently.
This was broken with 5f5aba5b6e690ca54e66f41b93474f7e67e83c8b, dated November
2011.
Task-number: QTBUG-42243
Change-Id: I5fecfd4174049f51e0cec90e40e6332de5d5bf01
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
-rw-r--r-- | src/quick/items/qquickrepeater.cpp | 4 | ||||
-rw-r--r-- | tests/auto/quick/qquickrepeater/data/clearremovalorder.qml | 31 | ||||
-rw-r--r-- | tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp | 38 |
3 files changed, 72 insertions, 1 deletions
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp index e2a3043857..975682192e 100644 --- a/src/quick/items/qquickrepeater.cpp +++ b/src/quick/items/qquickrepeater.cpp @@ -350,7 +350,9 @@ void QQuickRepeater::clear() bool complete = isComponentComplete(); if (d->model) { - for (int i = 0; i < d->deletables.count(); ++i) { + // We remove in reverse order deliberately; so that signals are emitted + // with sensible indices. + for (int i = d->deletables.count() - 1; i >= 0; --i) { if (QQuickItem *item = d->deletables.at(i)) { if (complete) emit itemRemoved(i, item); diff --git a/tests/auto/quick/qquickrepeater/data/clearremovalorder.qml b/tests/auto/quick/qquickrepeater/data/clearremovalorder.qml new file mode 100644 index 0000000000..a341246163 --- /dev/null +++ b/tests/auto/quick/qquickrepeater/data/clearremovalorder.qml @@ -0,0 +1,31 @@ +import QtQuick 2.0 + +Item { + ListModel { + id: firstModel + objectName: "firstModel" + + ListElement { + name: "Captain" + } + ListElement { + name: "Jack" + } + ListElement { + name: "Sparrow" + } + } + ListModel { + id: secondModel + objectName: "secondModel" + } + Repeater { + objectName: "repeater" + model: firstModel + delegate: Rectangle { + width: 5 + height: 5 + color: "green" + } + } +} diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp index 258eaee981..62ace2ac7e 100644 --- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp +++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp @@ -40,6 +40,7 @@ #include <QtQml/qqmlincubator.h> #include <private/qquickrepeater_p.h> #include <QtQuick/private/qquicktext_p.h> +#include <QtQml/private/qqmllistmodel_p.h> #include "../../shared/util.h" #include "../shared/viewtestutil.h" @@ -73,6 +74,7 @@ private slots: void visualItemModelCrash(); void invalidContextCrash(); void jsArrayChange(); + void clearRemovalOrder(); }; class TestObject : public QObject @@ -807,6 +809,42 @@ void tst_QQuickRepeater::jsArrayChange() QCOMPARE(spy.count(), 1); } +void tst_QQuickRepeater::clearRemovalOrder() +{ + // Here, we're going to test that when the model is cleared, item removal + // signals are sent in a sensible order that gives us correct indices. + // (QTBUG-42243) + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("clearremovalorder.qml")); + + QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create()); + QVERIFY(rootObject); + + QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater"); + QVERIFY(repeater); + QCOMPARE(repeater->count(), 3); + + QQmlListModel *model = rootObject->findChild<QQmlListModel*>("secondModel"); + QVERIFY(model); + QCOMPARE(model->count(), 0); + + // Now change the model + QSignalSpy removedSpy(repeater, &QQuickRepeater::itemRemoved); + repeater->setModel(QVariant::fromValue(model)); + + // we should have 0 items, and 3 removal signals. + QCOMPARE(repeater->count(), 0); + QCOMPARE(removedSpy.count(), 3); + + // column 1 is for the items, we won't bother verifying these. just look at + // the indices and make sure they're sane. + QCOMPARE(removedSpy.at(0).at(0).toInt(), 2); + QCOMPARE(removedSpy.at(1).at(0).toInt(), 1); + QCOMPARE(removedSpy.at(2).at(0).toInt(), 0); + + delete rootObject; +} + QTEST_MAIN(tst_QQuickRepeater) #include "tst_qquickrepeater.moc" |