diff options
Diffstat (limited to 'tests/auto/quick/qquicklistview/tst_qquicklistview.cpp')
-rw-r--r-- | tests/auto/quick/qquicklistview/tst_qquicklistview.cpp | 567 |
1 files changed, 417 insertions, 150 deletions
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 20d71aa0d7..4e49344bc0 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -41,6 +41,7 @@ #include <QtQuick/private/qquicklistview_p.h> #include <QtQuick/private/qquickmousearea_p.h> #include <QtQuick/private/qquicktext_p.h> +#include <QtQuick/private/qquickrectangle_p.h> #include <QtQmlModels/private/qqmlobjectmodel_p.h> #include <QtQmlModels/private/qqmllistmodel_p.h> #include <QtQmlModels/private/qqmldelegatemodel_p.h> @@ -50,6 +51,7 @@ #include "incrementalmodel.h" #include "proxytestinnermodel.h" #include "randomsortmodel.h" +#include "reusemodel.h" #include <math.h> Q_DECLARE_METATYPE(Qt::LayoutDirection) @@ -128,6 +130,7 @@ private slots: void qAbstractItemModel_package_sections(); void qAbstractItemModel_sections(); void sectionsPositioning(); + void sectionsDelegate_data(); void sectionsDelegate(); void sectionsDragOutsideBounds_data(); void sectionsDragOutsideBounds(); @@ -283,9 +286,17 @@ private slots: void setPositionOnLayout(); void touchCancel(); void resizeAfterComponentComplete(); + void dragOverFloatingHeaderOrFooter(); + + void delegateWithRequiredProperties(); + + void reuse_reuseIsOffByDefault(); + void reuse_checkThatItemsAreReused(); void moveObjectModelItemToAnotherObjectModel(); void changeModelAndDestroyTheOldOne(); + void requiredObjectListModel(); + private: template <class T> void items(const QUrl &source); template <class T> void changed(const QUrl &source); @@ -395,7 +406,7 @@ void tst_QQuickListView::init() m_view = nullptr; } #endif - qmlRegisterType<QAbstractItemModel>(); + qmlRegisterAnonymousType<QAbstractItemModel>("Proxy", 1); qmlRegisterType<ProxyTestInnerModel>("Proxy", 1, 0, "ProxyTestInnerModel"); qmlRegisterType<QSortFilterProxyModel>("Proxy", 1, 0, "QSortFilterProxyModel"); } @@ -422,8 +433,8 @@ void tst_QQuickListView::items(const QUrl &source) QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(source); qApp->processEvents(); @@ -487,8 +498,6 @@ void tst_QQuickListView::items(const QUrl &source) QTRY_COMPARE(listview->highlightResizeVelocity(), 1000.0); QTRY_COMPARE(listview->highlightMoveVelocity(), 100000.0); - - delete testObject; } @@ -505,8 +514,8 @@ void tst_QQuickListView::changed(const QUrl &source) QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(source); qApp->processEvents(); @@ -528,8 +537,6 @@ void tst_QQuickListView::changed(const QUrl &source) QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1); QTRY_VERIFY(number != nullptr); QTRY_COMPARE(number->text(), model.number(1)); - - delete testObject; } template <class T> @@ -547,8 +554,8 @@ void tst_QQuickListView::inserted(const QUrl &source) QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(source); qApp->processEvents(); @@ -625,8 +632,6 @@ void tst_QQuickListView::inserted(const QUrl &source) QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0); QVERIFY(item); QTRY_COMPARE(item->y() - listview->contentY(), 0.); - - delete testObject; } template <class T> @@ -645,8 +650,8 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -704,7 +709,7 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v break; } } - QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex)); // Confirm items positioned correctly and indexes correct QQuickText *name; @@ -713,14 +718,14 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v const qreal visibleToPos = listview->contentY() + listview->height() + listview->displayMarginEnd() + listview->cacheBuffer(); for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); qreal pos = i*20.0 + itemsOffsetAfterMove; if (verticalLayoutDirection == QQuickItemView::BottomToTop) pos = -item->height() - pos; // Items outside the visible area (including cache buffer) should be skipped if (pos > visibleToPos || pos < visibleFromPos) { QTRY_VERIFY2(QQuickItemPrivate::get(item)->culled || item->y() < visibleFromPos || item->y() > visibleToPos, - QTest::toString(QString("index %5, y %1, from %2, to %3, expected pos %4, culled %6"). + qPrintable(QString("index %5, y %1, from %2, to %3, expected pos %4, culled %6"). arg(item->y()).arg(visibleFromPos).arg(visibleToPos).arg(pos).arg(i).arg(bool(QQuickItemPrivate::get(item)->culled)))); continue; } @@ -734,7 +739,6 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v } releaseView(window); - delete testObject; } void tst_QQuickListView::inserted_more_data() @@ -840,8 +844,8 @@ void tst_QQuickListView::insertBeforeVisible() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -889,7 +893,7 @@ void tst_QQuickListView::insertBeforeVisible() int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); for (int i = 0; i < model.count() && i < itemCount; ++i) { item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove); name = findItem<QQuickText>(contentItem, "textName", i); QVERIFY(name != nullptr); @@ -897,7 +901,6 @@ void tst_QQuickListView::insertBeforeVisible() } releaseView(window); - delete testObject; } void tst_QQuickListView::insertBeforeVisible_data() @@ -953,8 +956,8 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(source); window->show(); @@ -1116,8 +1119,6 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) for (int i = 0; i < 18; ++i) model.removeItems(model.count() - 1, 1); QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() > 16); - - delete testObject; } template <class T> @@ -1137,8 +1138,8 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(source); window->show(); @@ -1180,14 +1181,14 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic break; } } - QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex)); // Confirm items positioned correctly and indexes correct QQuickText *name; QQuickText *number; for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); qreal pos = i*20.0 + itemsOffsetAfterMove; if (verticalLayoutDirection == QQuickItemView::BottomToTop) pos = -item0->height() - pos; @@ -1201,7 +1202,6 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic } releaseView(window); - delete testObject; } void tst_QQuickListView::removed_more_data() @@ -1319,8 +1319,8 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(source); window->show(); @@ -1353,8 +1353,6 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou QTRY_COMPARE(listview->count(), 1); QVERIFY(listview->currentItem() != nullptr); QCOMPARE(listview->currentIndex(), 0); - - delete testObject; } template <class T> @@ -1377,8 +1375,8 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(source); window->show(); @@ -1414,12 +1412,12 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou break; } } - QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex)); // Confirm items positioned correctly and indexes correct for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); qreal pos = i*20.0 + itemsOffsetAfterMove; if (verticalLayoutDirection == QQuickItemView::BottomToTop) pos = -item->height() - pos; @@ -1437,7 +1435,6 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou } releaseView(window); - delete testObject; } void tst_QQuickListView::moved_data() @@ -1607,8 +1604,8 @@ void tst_QQuickListView::multipleChanges(bool condensed) QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -1660,7 +1657,7 @@ void tst_QQuickListView::multipleChanges(bool condensed) int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); for (int i=0; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); name = findItem<QQuickText>(contentItem, "textName", i); QVERIFY(name != nullptr); QTRY_COMPARE(name->text(), model.name(i)); @@ -1669,7 +1666,6 @@ void tst_QQuickListView::multipleChanges(bool condensed) QTRY_COMPARE(number->text(), model.number(i)); } - delete testObject; releaseView(window); } @@ -1855,8 +1851,8 @@ void tst_QQuickListView::swapWithFirstItem() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -1870,8 +1866,6 @@ void tst_QQuickListView::swapWithFirstItem() listview->setContentY(0); model.moveItem(1, 0); QTRY_COMPARE(listview->contentY(), qreal(0)); - - delete testObject; } void tst_QQuickListView::checkCountForMultiColumnModels() @@ -2039,8 +2033,8 @@ void tst_QQuickListView::spacing() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -2084,8 +2078,6 @@ void tst_QQuickListView::spacing() QTRY_VERIFY(item); QTRY_COMPARE(item->y(), i*20.0); } - - delete testObject; } template <typename T> @@ -2189,8 +2181,17 @@ void tst_QQuickListView::sections(const QUrl &source) QTRY_COMPARE(item->height(), 40.0); } +void tst_QQuickListView::sectionsDelegate_data() +{ + QTest::addColumn<QUrl>("path"); + QTest::addRow("implicit") << testFileUrl("listview-sections_delegate.qml"); + QTest::addRow("required") << testFileUrl("listview-sections_delegate_required.qml"); +} + void tst_QQuickListView::sectionsDelegate() { + QFETCH(QUrl, path); + QScopedPointer<QQuickView> window(createView()); QaimModel model; @@ -2200,7 +2201,7 @@ void tst_QQuickListView::sectionsDelegate() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - window->setSource(testFileUrl("listview-sections_delegate.qml")); + window->setSource(path); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window.data())); @@ -2803,7 +2804,7 @@ void tst_QQuickListView::currentIndex() for (int i = 0; i < 30; i++) initModel.addItem("Item" + QString::number(i), QString::number(i)); - QQuickView *window = new QQuickView(nullptr); + QScopedPointer<QQuickView> window(new QQuickView(nullptr)); window->setGeometry(0,0,240,320); QQmlContext *ctxt = window->rootContext(); @@ -2813,7 +2814,7 @@ void tst_QQuickListView::currentIndex() QString filename(testFile("listview-initCurrent.qml")); window->setSource(QUrl::fromLocalFile(filename)); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); QTRY_VERIFY(listview != nullptr); @@ -2901,8 +2902,6 @@ void tst_QQuickListView::currentIndex() QCOMPARE(QQmlProperty(window->rootObject(), "s").read().toString(), "-1"); QCOMPARE(window->rootObject()->property("currentItemChangedCount").toInt(), 1); QCOMPARE(listview->currentIndex(), -1); - - delete window; } void tst_QQuickListView::noCurrentIndex() @@ -2911,7 +2910,7 @@ void tst_QQuickListView::noCurrentIndex() for (int i = 0; i < 30; i++) model.addItem("Item" + QString::number(i), QString::number(i)); - QQuickView *window = new QQuickView(nullptr); + QScopedPointer<QQuickView> window(new QQuickView(nullptr)); window->setGeometry(0,0,240,320); QQmlContext *ctxt = window->rootContext(); @@ -2920,7 +2919,7 @@ void tst_QQuickListView::noCurrentIndex() QString filename(testFile("listview-noCurrent.qml")); window->setSource(QUrl::fromLocalFile(filename)); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); QTRY_VERIFY(listview != nullptr); @@ -2939,8 +2938,6 @@ void tst_QQuickListView::noCurrentIndex() QCOMPARE(listview->currentIndex(), 2); QVERIFY(listview->highlightItem()); QVERIFY(listview->currentItem()); - - delete window; } void tst_QQuickListView::keyNavigation() @@ -2958,9 +2955,9 @@ void tst_QQuickListView::keyNavigation() model.addItem("Item" + QString::number(i), ""); QQuickView *window = getView(); - TestObject *testObject = new TestObject; + QScopedPointer<TestObject> testObject(new TestObject); window->rootContext()->setContextProperty("testModel", &model); - window->rootContext()->setContextProperty("testObject", testObject); + window->rootContext()->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); QVERIFY(QTest::qWaitForWindowActive(window)); @@ -3030,7 +3027,6 @@ void tst_QQuickListView::keyNavigation() QTRY_COMPARE(listview->contentY(), contentPosAtFirstItem.y()); releaseView(window); - delete testObject; } void tst_QQuickListView::keyNavigation_data() @@ -3172,8 +3168,8 @@ void tst_QQuickListView::cacheBuffer() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -3261,8 +3257,6 @@ void tst_QQuickListView::cacheBuffer() // negative cache buffer is ignored listview->setCacheBuffer(-1); QCOMPARE(listview->cacheBuffer(), 200); - - delete testObject; } void tst_QQuickListView::positionViewAtBeginningEnd() @@ -3276,8 +3270,8 @@ void tst_QQuickListView::positionViewAtBeginningEnd() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->show(); window->setSource(testFileUrl("listviewtest.qml")); QVERIFY(QTest::qWaitForWindowExposed(window.data())); @@ -3315,8 +3309,6 @@ void tst_QQuickListView::positionViewAtBeginningEnd() QTRY_COMPARE(listview->contentY(), -30.); QVERIFY(listview->highlightItem()); QCOMPARE(listview->highlightItem()->y(), 20.); - - delete testObject; } void tst_QQuickListView::positionViewAtIndex() @@ -3336,8 +3328,8 @@ void tst_QQuickListView::positionViewAtIndex() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->show(); window->setSource(testFileUrl("listviewtest.qml")); QVERIFY(QTest::qWaitForWindowExposed(window)); @@ -3642,7 +3634,7 @@ void tst_QQuickListView::QTBUG_33568() void tst_QQuickListView::manualHighlight() { - QQuickView *window = new QQuickView(nullptr); + QScopedPointer<QQuickView> window(new QQuickView(nullptr)); window->setGeometry(0,0,240,320); QString filename(testFile("manual-highlight.qml")); @@ -3672,8 +3664,6 @@ void tst_QQuickListView::manualHighlight() QTRY_COMPARE(listview->currentIndex(), 2); QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2)); QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y()); - - delete window; } void tst_QQuickListView::QTBUG_11105() @@ -3686,8 +3676,8 @@ void tst_QQuickListView::QTBUG_11105() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -3719,8 +3709,6 @@ void tst_QQuickListView::QTBUG_11105() itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); QCOMPARE(itemCount, 5); - - delete testObject; } void tst_QQuickListView::initialZValues() @@ -4358,8 +4346,8 @@ void tst_QQuickListView::resizeView() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -4422,8 +4410,6 @@ void tst_QQuickListView::resizeView() QTRY_COMPARE(item->y(), i*20.); QCOMPARE(delegateVisible(item), i < 6); // inside view visible, outside not visible } - - delete testObject; } void tst_QQuickListView::resizeViewAndRepaint() @@ -4470,8 +4456,8 @@ void tst_QQuickListView::sizeLessThan1() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("sizelessthan1.qml")); window->show(); @@ -4491,8 +4477,6 @@ void tst_QQuickListView::sizeLessThan1() QTRY_VERIFY(item); QTRY_COMPARE(item->y(), i*0.5); } - - delete testObject; } void tst_QQuickListView::QTBUG_14821() @@ -4603,8 +4587,8 @@ void tst_QQuickListView::resizeFirstDelegate() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -4659,8 +4643,6 @@ void tst_QQuickListView::resizeFirstDelegate() for (int i=0; i<3; i++) { QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", i)); } - - delete testObject; } void tst_QQuickListView::repositionResizedDelegate() @@ -4812,8 +4794,8 @@ void tst_QQuickListView::indexAt_itemAt() QQmlContext *ctxt = window->rootContext(); ctxt->setContextProperty("testModel", &model); - TestObject *testObject = new TestObject; - ctxt->setContextProperty("testObject", testObject); + QScopedPointer<TestObject> testObject(new TestObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("listviewtest.qml")); window->show(); @@ -4835,7 +4817,6 @@ void tst_QQuickListView::indexAt_itemAt() QCOMPARE(listview->itemAt(x,y), item); releaseView(window); - delete testObject; } void tst_QQuickListView::itemAtIndex() @@ -6466,7 +6447,7 @@ void tst_QQuickListView::unrequestedVisibility() for (int i = 0; i < 30; i++) model.addItem("Item" + QString::number(i), QString::number(i)); - QQuickView *window = new QQuickView(nullptr); + QScopedPointer<QQuickView> window(new QQuickView(nullptr)); window->setGeometry(0,0,240,320); QQmlContext *ctxt = window->rootContext(); @@ -6475,7 +6456,7 @@ void tst_QQuickListView::unrequestedVisibility() window->setSource(testFileUrl("unrequestedItems.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); QQuickListView *leftview; @@ -6662,8 +6643,6 @@ void tst_QQuickListView::unrequestedVisibility() item = findItem<QQuickItem>(rightContent, wrapperObjectName, 17); QVERIFY(item); QCOMPARE(delegateVisible(item), false); - - delete window; } void tst_QQuickListView::populateTransitions() @@ -6684,8 +6663,9 @@ void tst_QQuickListView::populateTransitions() } QQuickView *window = getView(); + QScopedPointer<TestObject> testObject(new TestObject(window->rootContext())); window->rootContext()->setContextProperty("testModel", &model); - window->rootContext()->setContextProperty("testObject", new TestObject(window->rootContext())); + window->rootContext()->setContextProperty("testObject", testObject.data()); window->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition); window->rootContext()->setContextProperty("dynamicallyPopulate", dynamicallyPopulate); window->rootContext()->setContextProperty("transitionFrom", transitionFrom); @@ -6716,7 +6696,7 @@ void tst_QQuickListView::populateTransitions() int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); for (int i=0; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->x(), 0.0); QTRY_COMPARE(item->y(), i*20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); @@ -6751,7 +6731,7 @@ void tst_QQuickListView::populateTransitions() itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); for (int i=0; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->x(), 0.0); QTRY_COMPARE(item->y(), i*20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); @@ -6769,7 +6749,7 @@ void tst_QQuickListView::populateTransitions() itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); for (int i=0; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->x(), 0.0); QTRY_COMPARE(item->y(), i*20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); @@ -6811,7 +6791,7 @@ void tst_QQuickListView::sizeTransitions() QaimModel model; ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("topToBottom", topToBottom); - TestObject *testObject = new TestObject; + QScopedPointer<TestObject> testObject(new TestObject); ctxt->setContextProperty("testObject", &model); window->setSource(testFileUrl("sizeTransitions.qml")); window->show(); @@ -6832,7 +6812,6 @@ void tst_QQuickListView::sizeTransitions() QCOMPARE(listview->property("transitionFinished").toBool(), true); releaseView(window); - delete testObject; } void tst_QQuickListView::sizeTransitions_data() @@ -6869,13 +6848,13 @@ void tst_QQuickListView::addTransitions() QQuickView *window = getView(); QQmlContext *ctxt = window->rootContext(); - TestObject *testObject = new TestObject; + QScopedPointer<TestObject> testObject(new TestObject); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom); ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom); ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); - ctxt->setContextProperty("testObject", testObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("addTransitions.qml")); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); @@ -6954,12 +6933,12 @@ void tst_QQuickListView::addTransitions() break; } } - QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex)); // verify all items moved to the correct final positions for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->y(), i*20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); QVERIFY(name != nullptr); @@ -6967,7 +6946,6 @@ void tst_QQuickListView::addTransitions() } releaseView(window); - delete testObject; } void tst_QQuickListView::addTransitions_data() @@ -7065,13 +7043,13 @@ void tst_QQuickListView::moveTransitions() QQuickView *window = getView(); QQmlContext *ctxt = window->rootContext(); - TestObject *testObject = new TestObject; + QScopedPointer<TestObject> testObject(new TestObject); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("model_targetItems_transitionVia", &model_targetItems_transitionVia); ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); ctxt->setContextProperty("targetItems_transitionVia", targetItems_transitionVia); ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); - ctxt->setContextProperty("testObject", testObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("moveTransitions.qml")); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); @@ -7138,13 +7116,13 @@ void tst_QQuickListView::moveTransitions() break; } } - QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex)); // verify all items moved to the correct final positions int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove); name = findItem<QQuickText>(contentItem, "textName", i); QVERIFY(name != nullptr); @@ -7152,7 +7130,6 @@ void tst_QQuickListView::moveTransitions() } releaseView(window); - delete testObject; } void tst_QQuickListView::moveTransitions_data() @@ -7268,13 +7245,13 @@ void tst_QQuickListView::removeTransitions() QQuickView *window = getView(); QQmlContext *ctxt = window->rootContext(); - TestObject *testObject = new TestObject; + QScopedPointer<TestObject> testObject(new TestObject); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("model_targetItems_transitionTo", &model_targetItems_transitionTo); ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); ctxt->setContextProperty("targetItems_transitionTo", targetItems_transitionTo); ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); - ctxt->setContextProperty("testObject", testObject); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("removeTransitions.qml")); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); @@ -7352,12 +7329,12 @@ void tst_QQuickListView::removeTransitions() if (index < 0) itemCount--; // exclude deleted items } - QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + QVERIFY2(firstVisibleIndex >= 0, QByteArray::number(firstVisibleIndex)); // verify all items moved to the correct final positions for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QCOMPARE(item->x(), 0.0); QCOMPARE(item->y(), contentY + (i-firstVisibleIndex) * 20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); @@ -7366,7 +7343,6 @@ void tst_QQuickListView::removeTransitions() } releaseView(window); - delete testObject; } void tst_QQuickListView::removeTransitions_data() @@ -7467,9 +7443,9 @@ void tst_QQuickListView::displacedTransitions() QQuickView *window = getView(); QQmlContext *ctxt = window->rootContext(); - TestObject *testObject = new TestObject(window); + QScopedPointer<TestObject> testObject(new TestObject(window)); ctxt->setContextProperty("testModel", &model); - ctxt->setContextProperty("testObject", testObject); + ctxt->setContextProperty("testObject", testObject.data()); ctxt->setContextProperty("model_displaced_transitionVia", &model_displaced_transitionVia); ctxt->setContextProperty("model_addDisplaced_transitionVia", &model_addDisplaced_transitionVia); ctxt->setContextProperty("model_moveDisplaced_transitionVia", &model_moveDisplaced_transitionVia); @@ -7490,7 +7466,6 @@ void tst_QQuickListView::displacedTransitions() window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); - QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); QTRY_VERIFY(listview != nullptr); QQuickItem *contentItem = listview->contentItem(); @@ -7572,7 +7547,7 @@ void tst_QQuickListView::displacedTransitions() QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); for (int i=0; i < model.count() && i < items.count(); ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QCOMPARE(item->x(), 0.0); QCOMPARE(item->y(), i * 20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); @@ -7694,9 +7669,9 @@ void tst_QQuickListView::multipleTransitions() QQuickView *window = getView(); QQmlContext *ctxt = window->rootContext(); - TestObject *testObject = new TestObject; + QScopedPointer<TestObject> testObject(new TestObject); ctxt->setContextProperty("testModel", &model); - ctxt->setContextProperty("testObject", testObject); + ctxt->setContextProperty("testObject", testObject.data()); ctxt->setContextProperty("addTargets_transitionFrom", addTargets_transitionFrom); ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom); ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom); @@ -7780,7 +7755,7 @@ void tst_QQuickListView::multipleTransitions() QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); for (int i=0; i < model.count() && i < items.count(); ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->x(), 0.0); QTRY_COMPARE(item->y(), i*20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); @@ -7789,7 +7764,6 @@ void tst_QQuickListView::multipleTransitions() } releaseView(window); - delete testObject; } void tst_QQuickListView::multipleTransitions_data() @@ -7862,8 +7836,9 @@ void tst_QQuickListView::multipleDisplaced() QQuickView *window = getView(); QQmlContext *ctxt = window->rootContext(); + QScopedPointer<TestObject> testObject(new TestObject(window)); ctxt->setContextProperty("testModel", &model); - ctxt->setContextProperty("testObject", new TestObject(window)); + ctxt->setContextProperty("testObject", testObject.data()); window->setSource(testFileUrl("multipleDisplaced.qml")); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); @@ -7882,14 +7857,14 @@ void tst_QQuickListView::multipleDisplaced() QVariantMap transitionsStarted = listview->property("displaceTransitionsStarted").toMap(); foreach (const QString &name, transitionsStarted.keys()) { QVERIFY2(transitionsStarted[name] == 1, - QTest::toString(QString("%1 was displaced %2 times").arg(name).arg(transitionsStarted[name].toInt()))); + qPrintable(QString("%1 was displaced %2 times").arg(name).arg(transitionsStarted[name].toInt()))); } // verify all items moved to the correct final positions QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); for (int i=0; i < model.count() && i < items.count(); ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QVERIFY2(item, qPrintable(QString("Item %1 not found").arg(i))); QTRY_COMPARE(item->x(), 0.0); QTRY_COMPARE(item->y(), i*20.0); QQuickText *name = findItem<QQuickText>(contentItem, "textName", i); @@ -7931,7 +7906,7 @@ void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const Qa QCOMPARE(it.value().type(), QVariant::Int); QString name = it.key(); int itemIndex = it.value().toInt(); - QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex))); + QVERIFY2(expectedIndexes.contains(itemIndex), qPrintable(QString("Index %1 not found in expectedIndexes").arg(itemIndex))); if (model.name(itemIndex) != name) qDebug() << itemIndex; QCOMPARE(model.name(itemIndex), name); @@ -7946,8 +7921,8 @@ void tst_QQuickListView::matchItemLists(const QVariantList &itemLists, const QLi QVariantList current = itemLists[i].toList(); for (int j=0; j<current.count(); j++) { QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>()); - QVERIFY2(o, QTest::toString(QString("Invalid actual item at %1").arg(j))); - QVERIFY2(expectedItems.contains(o), QTest::toString(QString("Cannot match item %1").arg(j))); + QVERIFY2(o, qPrintable(QString("Invalid actual item at %1").arg(j))); + QVERIFY2(expectedItems.contains(o), qPrintable(QString("Cannot match item %1").arg(j))); } QCOMPARE(current.count(), expectedItems.count()); } @@ -8121,7 +8096,7 @@ void tst_QQuickListView::defaultHighlightMoveDuration() QQmlComponent component(&engine); component.setData("import QtQuick 2.0; ListView {}", QUrl::fromLocalFile("")); - QObject *obj = component.create(); + QScopedPointer<QObject> obj(component.create()); QVERIFY(obj); QCOMPARE(obj->property("highlightMoveDuration").toInt(), -1); @@ -8937,15 +8912,15 @@ void tst_QQuickListView::programmaticFlickAtBounds3() void tst_QQuickListView::layoutChange() { - RandomSortModel *model = new RandomSortModel; - QSortFilterProxyModel *sortModel = new QSortFilterProxyModel; - sortModel->setSourceModel(model); + QScopedPointer<RandomSortModel> model(new RandomSortModel); + QScopedPointer<QSortFilterProxyModel> sortModel(new QSortFilterProxyModel); + sortModel->setSourceModel(model.data()); sortModel->setSortRole(Qt::UserRole); sortModel->setDynamicSortFilter(true); sortModel->sort(0); QScopedPointer<QQuickView> window(createView()); - window->rootContext()->setContextProperty("testModel", QVariant::fromValue(sortModel)); + window->rootContext()->setContextProperty("testModel", QVariant::fromValue(sortModel.data())); window->setSource(testFileUrl("layoutChangeSort.qml")); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window.data())); @@ -9093,7 +9068,8 @@ void tst_QQuickListView::objectModel() QQmlEngine engine; QQmlComponent component(&engine, testFileUrl("objectmodel.qml")); - QQuickListView *listview = qobject_cast<QQuickListView *>(component.create()); + QScopedPointer<QObject> obj(component.create()); + QQuickListView *listview = qobject_cast<QQuickListView *>(obj.data()); QVERIFY(listview); QQmlObjectModel *model = listview->model().value<QQmlObjectModel *>(); @@ -9133,8 +9109,6 @@ void tst_QQuickListView::objectModel() model->clear(); QCOMPARE(model->count(), 0); QCOMPARE(listview->count(), 0); - - delete listview; } void tst_QQuickListView::contentHeightWithDelayRemove_data() @@ -9552,13 +9526,13 @@ void tst_QQuickListView::releaseItems() void tst_QQuickListView::QTBUG_34576_velocityZero() { - QQuickView *window = new QQuickView(nullptr); + QScopedPointer<QQuickView> window(new QQuickView(nullptr)); window->setGeometry(0,0,240,320); QString filename(testFile("qtbug34576.qml")); window->setSource(QUrl::fromLocalFile(filename)); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); QVERIFY(listview); @@ -9581,8 +9555,8 @@ void tst_QQuickListView::QTBUG_34576_velocityZero() QSignalSpy currentIndexChangedSpy(listview, SIGNAL(currentIndexChanged())); // click button which increases currentIndex - QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(295,215)); - QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(295,215)); + QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(295,215)); + QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(295,215)); // verify that currentIndexChanged is triggered QTRY_VERIFY(currentIndexChangedSpy.count() > 0); @@ -9593,8 +9567,6 @@ void tst_QQuickListView::QTBUG_34576_velocityZero() // velocity should be always > 0.0 QTRY_COMPARE(window->rootObject()->property("horizontalVelocityZeroCount").toInt(), 0); - - delete window; } void tst_QQuickListView::QTBUG_61537_modelChangesAsync() @@ -9726,6 +9698,247 @@ void tst_QQuickListView::resizeAfterComponentComplete() // QTBUG-76487 QTRY_COMPARE(lastItem->property("y").toInt(), 9 * lastItem->property("height").toInt()); } +class Animal +{ +public: + Animal(const int cost, const QString &name) {m_name = name; m_cost = cost;} + + int cost() const {return m_cost;} + QString name() const {return m_name;} + + QString m_name; + int m_cost; +}; + +class FruitModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum AnimalRoles { + NameRole = Qt::UserRole + 1, + CostRole + }; + + FruitModel(QObject* = nullptr) { + m_animals.push_back(Animal {4, QLatin1String("Melon")}); + m_animals.push_back(Animal {5, QLatin1String("Cherry")}); + } + + int rowCount(const QModelIndex & = QModelIndex()) const override {return m_animals.count();} + + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override { + if (!checkIndex(index)) + return {}; + const Animal &animal = m_animals[index.row()]; + if (role == CostRole) + return animal.cost(); + else if (role == NameRole) + return animal.name(); + return QVariant(); + } + +protected: + QHash<int, QByteArray> roleNames() const override { + QHash<int, QByteArray> roles; + roles[CostRole] = "cost"; + roles[NameRole] = "name"; + return roles; + } +private: + QList<Animal> m_animals; +}; + +void tst_QQuickListView::delegateWithRequiredProperties() +{ + FruitModel myModel; + qmlRegisterSingletonInstance("Qt.fruit", 1, 0, "FruitModelCpp", &myModel); + { + // ListModel + QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Apple2"); + QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Orange3"); + QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Banana1"); + QScopedPointer<QQuickView> window(createView()); + window->setInitialProperties({{QLatin1String("useCpp"), false}}); + window->setSource(testFileUrl("delegatesWithRequiredProperties.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QObject *listView = window->rootObject(); + QVERIFY(listView); + } + { + // C++ model + QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Melon4"); + QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Cherry5"); + QScopedPointer<QQuickView> window(createView()); + window->setInitialProperties({{QLatin1String("useCpp"), true}}); + window->setSource(testFileUrl("delegatesWithRequiredProperties.qml")); + + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QObject *listView = window->rootObject(); + QVERIFY(listView); + } +} + +void tst_QQuickListView::reuse_reuseIsOffByDefault() +{ + // Check that delegate recycling is off by default. The reason is that + // ListView needs to be backwards compatible with legacy applications. And + // when using delegate recycling, there are certain differences, like that + // a delegates Component.onCompleted will just be called the first time the + // item is created, and not when it's reused. + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("listviewtest.qml")); + window->resize(640, 480); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickListView *listView = findItem<QQuickListView>(window->rootObject(), "list"); + QVERIFY(listView != nullptr); + QVERIFY(!listView->reuseItems()); +} + +void tst_QQuickListView::reuse_checkThatItemsAreReused() +{ + // Flick up and down one page of items. Check that this results in the + // delegate items being reused once. + // Note that this is slightly different from tableview, which will reuse the items + // twice during a similar down-then-up flick. The reason is that listview fills up + // free space in the view with items _before_ it release old items that have been + // flicked out. But changing this will break other auto tests (and perhaps legacy + // apps), so we have chosen to stick with this behavior for now. + QScopedPointer<QQuickView> window(createView()); + + ReuseModel model(100); + QQmlContext *ctxt = window->rootContext(); + ctxt->setContextProperty("reuseModel", &model); + + window->setSource(testFileUrl("reusedelegateitems.qml")); + window->resize(640, 480); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + QVERIFY(window->rootObject() != nullptr); + + QQuickListView *listView = findItem<QQuickListView>(window->rootObject(), "list"); + QTRY_VERIFY(listView != nullptr); + const auto itemView_d = QQuickItemViewPrivate::get(listView); + + QVERIFY(listView->reuseItems()); + + auto items = findItems<QQuickItem>(listView, "delegate"); + const int initialItemCount = items.count(); + QVERIFY(initialItemCount > 0); + + // Sanity check that the size of the initial list of items match the count we tracked from QML + QCOMPARE(listView->property("delegatesCreatedCount").toInt(), initialItemCount); + + // Go through all the initial items and check that they have not been reused yet + for (const auto item : qAsConst(items)) + QCOMPARE(item->property("reusedCount").toInt(), 0); + + // Flick one page down and count how many items we have created thus + // far. We expect this number to be twice as high as the initial count + // since we flicked one whole page. + const qreal delegateHeight = items.at(0)->height(); + const qreal flickDistance = (initialItemCount * delegateHeight) + 1; + listView->setContentY(flickDistance); + QVERIFY(QQuickTest::qWaitForItemPolished(listView)); + const int countAfterDownFlick = listView->property("delegatesCreatedCount").toInt(); + QCOMPARE(countAfterDownFlick, initialItemCount * 2); + + // Check that the reuse pool is now populated. We expect all initial items to be pooled, + // except model index 0, which was never reused or released, since it's ListView.currentItem. + const int poolSizeAfterDownFlick = itemView_d->model->poolSize(); + QCOMPARE(poolSizeAfterDownFlick, initialItemCount - 1); + + // Go through all items and check that all model data inside the delegate + // have values updated according to their model index. Since model roles + // like 'display' are injected into the context in a special way by the + // QML model classes, we need to catch it through a binding instead (which is + // OK, since then we can also check that bindings are updated when reused). + items = findItems<QQuickItem>(listView, "delegate"); + for (const auto item : qAsConst(items)) { + const QString display = item->property("displayBinding").toString(); + const int modelIndex = item->property("modelIndex").toInt(); + QVERIFY(modelIndex >= initialItemCount); + QCOMPARE(display, model.displayStringForRow(modelIndex)); + } + + // Flick one page up. This time there shouldn't be any new items created, so + // delegatesCreatedCount should remain unchanged. But while we reuse all the items + // in the pool during the flick, we also fill it up again with all the items that + // were inside the page that was flicked out. + listView->setContentY(0); + QVERIFY(QQuickTest::qWaitForItemPolished(listView)); + const int countAfterUpFlick = listView->property("delegatesCreatedCount").toInt(); + const int poolSizeAfterUpFlick = itemView_d->model->poolSize(); + QCOMPARE(countAfterUpFlick, countAfterDownFlick); + QCOMPARE(poolSizeAfterUpFlick, initialItemCount); + + // Go through all items and check that they have been reused exactly once + // (except for ListView.currentItem, which was never released). + const auto listViewCurrentItem = listView->currentItem(); + items = findItems<QQuickItem>(listView, "delegate"); + for (const auto item : qAsConst(items)) { + const int reusedCount = item->property("reusedCount").toInt(); + if (item == listViewCurrentItem) + QCOMPARE(reusedCount, 0); + else + QCOMPARE(reusedCount, 1); + } + + // Go through all items again and check that all model data inside the delegate + // have correct values now that they have been reused. + items = findItems<QQuickItem>(listView, "delegate"); + for (const auto item : qAsConst(items)) { + const QString display = item->property("displayBinding").toString(); + const int modelIndex = item->property("modelIndex").toInt(); + QVERIFY(modelIndex < initialItemCount); + QCOMPARE(display, model.displayStringForRow(modelIndex)); + } +} + +void tst_QQuickListView::dragOverFloatingHeaderOrFooter() // QTBUG-74046 +{ + QQuickView *window = getView(); + QQuickViewTestUtil::moveMouseAway(window); + window->setSource(testFileUrl("qtbug63974.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickListView *listview = qmlobject_cast<QQuickListView *>(window->rootObject()); + QVERIFY(listview); + QCOMPARE(listview->contentY(), -20); + + // Drag downwards from the header: the list shouldn't move + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,10)); + for (int i = 0; i < 10; ++i) + QTest::mouseMove(window, QPoint(10, 10 + i * 10)); + QCOMPARE(listview->isMoving(), false); + QCOMPARE(listview->contentY(), -20); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier); + + // Drag upwards from the footer: the list shouldn't move + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,190)); + for (int i = 0; i < 10; ++i) + QTest::mouseMove(window, QPoint(10, 190 - i * 10)); + QCOMPARE(listview->isMoving(), false); + QCOMPARE(listview->contentY(), -20); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier); + + // Drag upwards from the middle: the list should move + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,100)); + for (int i = 0; i < 10 && listview->contentY() == -20; ++i) + QTest::mouseMove(window, QPoint(10, 100 - i * 10)); + QVERIFY(listview->isMoving()); + QVERIFY(listview->contentY() > -20); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier); + + releaseView(window); +} + void tst_QQuickListView::moveObjectModelItemToAnotherObjectModel() { QScopedPointer<QQuickView> window(createView()); @@ -9775,6 +9988,60 @@ void tst_QQuickListView::changeModelAndDestroyTheOldOne() // QTBUG-80203 // no crash } +class DataObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(QString color READ color CONSTANT) + +public: + DataObject(QObject *parent = nullptr) : QObject(parent) {} + DataObject(const QString &name, const QString &color, QObject *parent = nullptr) + : QObject(parent), m_name(name), m_color(color) {} + + QString name() const { return m_name; } + QString color() const { return m_color; } + +private: + QString m_name; + QString m_color; +}; + +void tst_QQuickListView::requiredObjectListModel() +{ + QList<QObject *> dataList = { + new DataObject("Item 1", "red", this), + new DataObject("Item 2", "green", this), + new DataObject("Item 3", "blue", this), + new DataObject("Item 4", "yellow", this) + }; + + const auto deleter = qScopeGuard([&](){ qDeleteAll(dataList); }); + Q_UNUSED(deleter); + + QQuickView view; + view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }}); + view.setSource(testFileUrl("requiredObjectListModel.qml")); + view.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + const auto *root = qobject_cast<QQuickListView *>(view.rootObject()); + QVERIFY(root); + + QCOMPARE(root->count(), dataList.count()); + + for (int i = 0, end = dataList.count(); i != end; ++i) { + const auto *rect = qobject_cast<QQuickRectangle *>(root->itemAtIndex(i)); + QVERIFY(rect); + const auto *data = qobject_cast<DataObject *>(dataList.at(i)); + QVERIFY(data); + + QCOMPARE(rect->color(), QColor(data->color())); + QCOMPARE(rect->property("name").toString(), data->name()); + } +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" |