diff options
Diffstat (limited to 'tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp')
-rw-r--r-- | tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp | 357 |
1 files changed, 233 insertions, 124 deletions
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp index 7ae0476f15..0821669703 100644 --- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp +++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp @@ -1,33 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "../../shared/util.h" -#include "../shared/visualtestutil.h" -#include "../shared/viewtestutil.h" +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QtQuickTestUtils/private/visualtestutils_p.h> +#include <QtQuickTestUtils/private/viewtestutils_p.h> #include <qtest.h> #include <QtCore/qregularexpression.h> @@ -47,8 +23,8 @@ #include <math.h> #include <QtGui/qstandarditemmodel.h> -using namespace QQuickVisualTestUtil; -using namespace QQuickViewTestUtil; +using namespace QQuickVisualTestUtils; +using namespace QQuickViewTestUtils; template <typename T, int N> int lengthOf(const T (&)[N]) { return N; } @@ -84,9 +60,9 @@ public: struct Branch { Branch(Branch *parent = nullptr) : parent(parent) {} - ~Branch() { foreach (const Node &child, children) delete child.branch; } + ~Branch() { for (const Node &child : std::as_const(children)) delete child.branch; } int indexOf(Branch *branch) const { - for (int i = 0; i < children.count(); ++i) { + for (int i = 0; i < children.size(); ++i) { if (children.at(i).branch == branch) return i; } @@ -100,12 +76,12 @@ public: SingleRoleModel(const QStringList &list = QStringList(), const QByteArray &role = "name", QObject *parent = nullptr) : QAbstractItemModel(parent), m_role(role) { - foreach (const QString &string, list) + for (const QString &string : list) trunk.children.append(Node(string)); } ~SingleRoleModel() {} - QHash<int,QByteArray> roleNames() const + QHash<int,QByteArray> roleNames() const override { QHash<int,QByteArray> roles; roles.insert(Qt::DisplayRole, m_role); @@ -130,42 +106,42 @@ public: } } - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const { + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override { if (row < 0 || column != 0) return QModelIndex(); Branch * const branch = branchForIndex(parent); - return branch && row < branch->children.count() + return branch && row < branch->children.size() ? createIndex(row, column, branch) : QModelIndex(); } - QModelIndex parent(const QModelIndex &child) const { + QModelIndex parent(const QModelIndex &child) const override { Branch * const branch = static_cast<Branch *>(child.internalPointer()); return branch->parent ? createIndex(branch->parent->indexOf(branch), 0, branch->parent) : QModelIndex(); } - int rowCount(const QModelIndex &parent) const { + int rowCount(const QModelIndex &parent) const override { Branch * const branch = branchForIndex(parent); - return branch ? branch->children.count() : 0; + return branch ? branch->children.size() : 0; } - int columnCount(const QModelIndex &parent) const { + int columnCount(const QModelIndex &parent) const override { Branch * const branch = branchForIndex(parent); return branch ? 1 : 0; } - QVariant data(const QModelIndex &index, int role) const { + QVariant data(const QModelIndex &index, int role) const override { return index.isValid() && role == Qt::DisplayRole ? static_cast<Branch *>(index.internalPointer())->children.at(index.row()).display : QVariant(); } void insert(const QModelIndex &parent, int index, const QStringList &data) { - beginInsertRows(parent, index, index + data.count() - 1); + beginInsertRows(parent, index, index + data.size() - 1); Branch * const branch = createBranchForIndex(parent); - for (int i = 0; i < data.count(); ++i) + for (int i = 0; i < data.size(); ++i) branch->children.insert(index + i, Node(data.at(i))); endInsertRows(); } @@ -207,21 +183,21 @@ public: QStringList getList() const { QStringList list; - foreach (const Node &node, trunk.children) + for (const Node &node : trunk.children) list.append(node.display); return list; } void setList(const QStringList &l) { - if (trunk.children.count() > 0) { - beginRemoveRows(QModelIndex(), 0, trunk.children.count() - 1); - foreach (const Node &child, trunk.children) delete child.branch; + if (trunk.children.size() > 0) { + beginRemoveRows(QModelIndex(), 0, trunk.children.size() - 1); + for (const Node &child : std::as_const(trunk.children)) delete child.branch; trunk.children.clear(); endRemoveRows(); } - if (l.count() > 0) { - beginInsertRows(QModelIndex(), 0, l.count() -1); - foreach (const QString &string, l) + if (l.size() > 0) { + beginInsertRows(QModelIndex(), 0, l.size() -1); + for (const QString &string : l) trunk.children.append(Node(string)); endInsertRows(); } @@ -424,6 +400,7 @@ private slots: void warnings_data(); void warnings(); void invalidAttachment(); + void declarativeAssignViaAttached(); void asynchronousInsert_data(); void asynchronousInsert(); void asynchronousRemove_data(); @@ -434,8 +411,10 @@ private slots: void invalidContext(); void externalManagedModel(); void delegateModelChangeDelegate(); + void noDoubleDelegateUpdate(); void checkFilterGroupForDelegate(); void readFromProxyObject(); + void noWarningOnObjectDeletion(); private: template <int N> void groups_verify( @@ -502,6 +481,7 @@ void tst_qquickvisualdatamodel::cleanupTestCase() } tst_qquickvisualdatamodel::tst_qquickvisualdatamodel() + : QQmlDataTest(QT_QMLTEST_DATADIR) { } @@ -624,7 +604,8 @@ void tst_qquickvisualdatamodel::childChanged() QVERIFY(name); QCOMPARE(name->text(), QString("Row 2 updated child")); - model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2"))); + QStandardItem item(QLatin1String("Row 2 Child Item 2")); + model.item(1,0)->appendRow(&item); QCOMPARE(listview->count(), 2); listview->forceLayout(); @@ -656,10 +637,10 @@ void tst_qquickvisualdatamodel::objectListModel() QQuickView view; QList<QObject*> dataList; - dataList.append(new DataObject("Item 1", "red")); - dataList.append(new DataObject("Item 2", "green")); - dataList.append(new DataObject("Item 3", "blue")); - dataList.append(new DataObject("Item 4", "yellow")); + dataList.append(new DataObject("Item 1", "red", &view)); + dataList.append(new DataObject("Item 2", "green", &view)); + dataList.append(new DataObject("Item 3", "blue", &view)); + dataList.append(new DataObject("Item 4", "yellow", &view)); QQmlContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); @@ -798,10 +779,10 @@ void tst_qquickvisualdatamodel::modelProperties() QQuickView view; QList<QObject*> dataList; - dataList.append(new DataObject("Item 1", "red")); - dataList.append(new DataObject("Item 2", "green")); - dataList.append(new DataObject("Item 3", "blue")); - dataList.append(new DataObject("Item 4", "yellow")); + dataList.append(new DataObject("Item 1", "red", &view)); + dataList.append(new DataObject("Item 2", "green", &view)); + dataList.append(new DataObject("Item 3", "blue", &view)); + dataList.append(new DataObject("Item 4", "yellow", &view)); QQmlContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); @@ -867,12 +848,9 @@ void tst_qquickvisualdatamodel::modelProperties() QUrl source(testFileUrl("modelproperties2.qml")); //3 items, 3 i each - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: TypeError: Cannot read property 'display' of undefined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: TypeError: Cannot read property 'display' of undefined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: TypeError: Cannot read property 'display' of undefined"); QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined"); QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined"); QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined"); @@ -1061,14 +1039,14 @@ void tst_qquickvisualdatamodel::qaimRowsMoved() QSignalSpy spy(obj, SIGNAL(modelUpdated(QQmlChangeSet,bool))); model.emitMove(sourceFirst, sourceLast, destinationChild); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); - QCOMPARE(spy[0].count(), 2); + QCOMPARE(spy[0].size(), 2); QQmlChangeSet changeSet = spy[0][0].value<QQmlChangeSet>(); - QCOMPARE(changeSet.removes().count(), 1); + QCOMPARE(changeSet.removes().size(), 1); QCOMPARE(changeSet.removes().at(0).index, expectFrom); QCOMPARE(changeSet.removes().at(0).count, expectCount); - QCOMPARE(changeSet.inserts().count(), 1); + QCOMPARE(changeSet.inserts().size(), 1); QCOMPARE(changeSet.inserts().at(0).index, expectTo); QCOMPARE(changeSet.inserts().at(0).count, expectCount); QCOMPARE(changeSet.removes().at(0).moveId, changeSet.inserts().at(0).moveId); @@ -1130,33 +1108,33 @@ void tst_qquickvisualdatamodel::subtreeRowsMoved() // Move items from the current root index to a sub tree. model.move(QModelIndex(), 1, model.index(0, 0), 3, 2); QCOMPARE(vdm->count(), 2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); changeSet = spy.last().at(0).value<QQmlChangeSet>(); - QCOMPARE(changeSet.removes().count(), 1); + QCOMPARE(changeSet.removes().size(), 1); QCOMPARE(changeSet.removes().at(0).index, 1); QCOMPARE(changeSet.removes().at(0).count, 2); - QCOMPARE(changeSet.inserts().count(), 0); + QCOMPARE(changeSet.inserts().size(), 0); // Move items from a sub tree to the current root index. model.move(model.index(0, 0), 4, QModelIndex(), 2, 1); QCOMPARE(vdm->count(), 3); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); changeSet = spy.last().at(0).value<QQmlChangeSet>(); - QCOMPARE(changeSet.removes().count(), 0); - QCOMPARE(changeSet.inserts().count(), 1); + QCOMPARE(changeSet.removes().size(), 0); + QCOMPARE(changeSet.inserts().size(), 1); QCOMPARE(changeSet.inserts().at(0).index, 2); QCOMPARE(changeSet.inserts().at(0).count, 1); vdm->setRootIndex(QVariant::fromValue(model.index(2, 0))); QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(2, 0)); QCOMPARE(vdm->count(), 3); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); changeSet = spy.at(2).at(0).value<QQmlChangeSet>(); - QCOMPARE(changeSet.removes().count(), 1); + QCOMPARE(changeSet.removes().size(), 1); QCOMPARE(changeSet.removes().at(0).index, 0); QCOMPARE(changeSet.removes().at(0).count, 3); changeSet = spy.last().at(0).value<QQmlChangeSet>(); - QCOMPARE(changeSet.inserts().count(), 1); + QCOMPARE(changeSet.inserts().size(), 1); QCOMPARE(changeSet.inserts().at(0).index, 0); QCOMPARE(changeSet.inserts().at(0).count, 3); @@ -1164,41 +1142,41 @@ void tst_qquickvisualdatamodel::subtreeRowsMoved() model.move(QModelIndex(), 2, QModelIndex(), 0, 1); QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(0, 0)); QCOMPARE(vdm->count(), 3); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); // Move the current root index, changing its parent. model.move(QModelIndex(), 0, model.index(1, 0), 0, 1); QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(0, 0, model.index(0, 0))); QCOMPARE(vdm->count(), 3); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); model.insert(model.index(0, 0), 0, QStringList() << "new1" << "new2"); QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(2, 0, model.index(0, 0))); QCOMPARE(vdm->count(), 3); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); model.remove(model.index(0, 0), 1, 1); QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(1, 0, model.index(0, 0))); QCOMPARE(vdm->count(), 3); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); model.remove(model.index(0, 0), 1, 1); QCOMPARE(vdm->rootIndex().value<QModelIndex>(), QModelIndex()); QCOMPARE(vdm->count(), 0); - QCOMPARE(spy.count(), 5); + QCOMPARE(spy.size(), 5); changeSet = spy.last().at(0).value<QQmlChangeSet>(); - QCOMPARE(changeSet.removes().count(), 1); + QCOMPARE(changeSet.removes().size(), 1); QCOMPARE(changeSet.removes().at(0).index, 0); QCOMPARE(changeSet.removes().at(0).count, 3); - QCOMPARE(changeSet.inserts().count(), 0); + QCOMPARE(changeSet.inserts().size(), 0); vdm->setRootIndex(QVariant::fromValue(QModelIndex())); QCOMPARE(vdm->rootIndex().value<QModelIndex>(), QModelIndex()); QCOMPARE(vdm->count(), 2); - QCOMPARE(spy.count(), 6); + QCOMPARE(spy.size(), 6); changeSet = spy.last().at(0).value<QQmlChangeSet>(); - QCOMPARE(changeSet.removes().count(), 0); - QCOMPARE(changeSet.inserts().count(), 1); + QCOMPARE(changeSet.removes().size(), 0); + QCOMPARE(changeSet.inserts().size(), 1); QCOMPARE(changeSet.inserts().at(0).index, 0); QCOMPARE(changeSet.inserts().at(0).count, 2); } @@ -1230,44 +1208,44 @@ void tst_qquickvisualdatamodel::watchedRoles() QCOMPARE(vdm->count(), 30); emit model.dataChanged(model.index(0), model.index(4)); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); emit model.dataChanged(model.index(0), model.index(4), QVector<int>() << QaimModel::Name); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); emit model.dataChanged(model.index(0), model.index(4), QVector<int>() << QaimModel::Number); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); vdm->setWatchedRoles(QList<QByteArray>() << "name" << "dummy"); emit model.dataChanged(model.index(0), model.index(4)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); changeSet = spy.last().at(0).value<QQmlChangeSet>(); QCOMPARE(changeSet.changes().at(0).index, 0); QCOMPARE(changeSet.changes().at(0).count, 5); emit model.dataChanged(model.index(1), model.index(6), QVector<int>() << QaimModel::Name); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); changeSet = spy.last().at(0).value<QQmlChangeSet>(); QCOMPARE(changeSet.changes().at(0).index, 1); QCOMPARE(changeSet.changes().at(0).count, 6); emit model.dataChanged(model.index(8), model.index(8), QVector<int>() << QaimModel::Number); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); vdm->setWatchedRoles(QList<QByteArray>() << "number" << "dummy"); emit model.dataChanged(model.index(0), model.index(4)); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); changeSet = spy.last().at(0).value<QQmlChangeSet>(); QCOMPARE(changeSet.changes().at(0).index, 0); QCOMPARE(changeSet.changes().at(0).count, 5); emit model.dataChanged(model.index(1), model.index(6), QVector<int>() << QaimModel::Name); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); emit model.dataChanged(model.index(8), model.index(8), QVector<int>() << QaimModel::Number); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); changeSet = spy.last().at(0).value<QQmlChangeSet>(); QCOMPARE(changeSet.changes().at(0).index, 8); QCOMPARE(changeSet.changes().at(0).count, 1); @@ -1275,19 +1253,19 @@ void tst_qquickvisualdatamodel::watchedRoles() vdm->setWatchedRoles(QList<QByteArray>() << "number" << "name"); emit model.dataChanged(model.index(0), model.index(4)); - QCOMPARE(spy.count(), 5); + QCOMPARE(spy.size(), 5); changeSet = spy.last().at(0).value<QQmlChangeSet>(); QCOMPARE(changeSet.changes().at(0).index, 0); QCOMPARE(changeSet.changes().at(0).count, 5); emit model.dataChanged(model.index(1), model.index(6), QVector<int>() << QaimModel::Name); - QCOMPARE(spy.count(), 6); + QCOMPARE(spy.size(), 6); changeSet = spy.last().at(0).value<QQmlChangeSet>(); QCOMPARE(changeSet.changes().at(0).index, 1); QCOMPARE(changeSet.changes().at(0).count, 6); emit model.dataChanged(model.index(8), model.index(8), QVector<int>() << QaimModel::Number); - QCOMPARE(spy.count(), 7); + QCOMPARE(spy.size(), 7); changeSet = spy.last().at(0).value<QQmlChangeSet>(); QCOMPARE(changeSet.changes().at(0).index, 8); QCOMPARE(changeSet.changes().at(0).count, 1); @@ -2282,7 +2260,7 @@ void tst_qquickvisualdatamodel::onChanged() evaluate<void>(object.data(), expression); - foreach (const QString &test, tests) { + for (const QString &test : std::as_const(tests)) { bool passed = evaluate<bool>(object.data(), test); if (!passed) qWarning() << test; @@ -2448,24 +2426,24 @@ void tst_qquickvisualdatamodel::incompleteModel() QSignalSpy persistedItemsSpy(model->items(), SIGNAL(countChanged())); evaluate<void>(model, "items.removeGroups(0, items.count, \"items\")"); - QCOMPARE(itemsSpy.count(), 0); - QCOMPARE(persistedItemsSpy.count(), 0); + QCOMPARE(itemsSpy.size(), 0); + QCOMPARE(persistedItemsSpy.size(), 0); evaluate<void>(model, "items.setGroups(0, items.count, \"persistedItems\")"); - QCOMPARE(itemsSpy.count(), 0); - QCOMPARE(persistedItemsSpy.count(), 0); + QCOMPARE(itemsSpy.size(), 0); + QCOMPARE(persistedItemsSpy.size(), 0); evaluate<void>(model, "items.addGroups(0, items.count, \"persistedItems\")"); - QCOMPARE(itemsSpy.count(), 0); - QCOMPARE(persistedItemsSpy.count(), 0); + QCOMPARE(itemsSpy.size(), 0); + QCOMPARE(persistedItemsSpy.size(), 0); evaluate<void>(model, "items.remove(0, items.count)"); - QCOMPARE(itemsSpy.count(), 0); - QCOMPARE(persistedItemsSpy.count(), 0); + QCOMPARE(itemsSpy.size(), 0); + QCOMPARE(persistedItemsSpy.size(), 0); evaluate<void>(model, "items.insert([ \"color\": \"blue\" ])"); - QCOMPARE(itemsSpy.count(), 0); - QCOMPARE(persistedItemsSpy.count(), 0); + QCOMPARE(itemsSpy.size(), 0); + QCOMPARE(persistedItemsSpy.size(), 0); QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*get: index out of range")); QVERIFY(evaluate<bool>(model, "items.get(0) === undefined")); @@ -3091,7 +3069,7 @@ void tst_qquickvisualdatamodel::insert() QCOMPARE(evaluate<int>(visualModel, "visibleItems.count"), visible ? visualCount : modelCount); QCOMPARE(evaluate<int>(visualModel, "selectedItems.count"), selected ? 1 : 0); - QCOMPARE(propertyData.count(), visualCount); + QCOMPARE(propertyData.size(), visualCount); for (int i = 0; i < visualCount; ++i) { int modelIndex = i; if (modelIndex > index) @@ -3559,7 +3537,7 @@ void tst_qquickvisualdatamodel::resolve() QCOMPARE(evaluate<int>(visualModel, "visibleItems.count"), visible ? visualCount : modelCount); QCOMPARE(evaluate<int>(visualModel, "selectedItems.count"), selected ? 1 : 0); - QCOMPARE(propertyData.count(), visualCount); + QCOMPARE(propertyData.size(), visualCount); for (int i = 0; i < visualCount; ++i) { int modelIndex = i; @@ -3960,7 +3938,7 @@ void tst_qquickvisualdatamodel::invalidAttachment() QScopedPointer<QObject> object(component.create()); QVERIFY(object); - QCOMPARE(component.errors().count(), 0); + QCOMPARE(component.errors().size(), 0); QVariant property = object->property("invalidVdm"); QCOMPARE(property.userType(), qMetaTypeId<QQmlDelegateModel *>()); @@ -3975,7 +3953,19 @@ void tst_qquickvisualdatamodel::invalidAttachment() property = item->property("invalidVdm"); QCOMPARE(property.userType(), qMetaTypeId<QQmlDelegateModel *>()); - QVERIFY(!property.value<QQmlDelegateModel *>()); + // has been explicitly requested by specifying the attached property + QVERIFY(property.value<QQmlDelegateModel *>()); +} + +void tst_qquickvisualdatamodel::declarativeAssignViaAttached() +{ + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("attachedDeclarativelySet.qml")); + + QScopedPointer<QObject> root(component.create()); + QCOMPARE(root->property("count").toInt(), 6); // 1 (from instantiator + 5 from model) + root->setProperty("includeAll", true); + QCOMPARE(root->property("count").toInt(), 11); // 1 (from instantiator + 10 from model) } void tst_qquickvisualdatamodel::asynchronousInsert_data() @@ -4007,7 +3997,8 @@ void tst_qquickvisualdatamodel::asynchronousInsert() engine.rootContext()->setContextProperty("myModel", &model); - QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create()); + QScopedPointer<QObject> o(c.create()); + QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data()); QVERIFY(visualModel); ItemRequester requester; @@ -4072,7 +4063,8 @@ void tst_qquickvisualdatamodel::asynchronousRemove() engine.rootContext()->setContextProperty("myModel", &model); - QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create()); + QScopedPointer<QObject> o(c.create()); + QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data()); QVERIFY(visualModel); ItemRequester requester; @@ -4151,7 +4143,8 @@ void tst_qquickvisualdatamodel::asynchronousMove() engine.rootContext()->setContextProperty("myModel", &model); - QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create()); + QScopedPointer<QObject> o(c.create()); + QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data()); QVERIFY(visualModel); ItemRequester requester; @@ -4199,7 +4192,8 @@ void tst_qquickvisualdatamodel::asynchronousCancel() engine.rootContext()->setContextProperty("myModel", &model); - QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create()); + QScopedPointer<QObject> o(c.create()); + QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data()); QVERIFY(visualModel); QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, QQmlIncubator::Asynchronous)); @@ -4235,7 +4229,7 @@ void tst_qquickvisualdatamodel::invalidContext() QVERIFY(item); visualModel->release(item); - delete context.take(); + context.reset(); model.insertItem(4, "new item", ""); @@ -4277,7 +4271,7 @@ public: static qsizetype listLength(QQmlListProperty<QObject> *property) { auto objectsProvider = qobject_cast<ObjectsProvider*>(property->object); - return objectsProvider ? objectsProvider->m_objects.length() : 0; + return objectsProvider ? objectsProvider->m_objects.size() : 0; } static QObject* listAt(QQmlListProperty<QObject> *property, qsizetype index) @@ -4321,7 +4315,8 @@ void tst_qquickvisualdatamodel::delegateModelChangeDelegate() c.setData("import QtQml.Models 2.2\nDelegateModel {}\n", QUrl()); QCOMPARE(c.status(), QQmlComponent::Ready); - QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create(context.data())); + QScopedPointer<QObject> o(c.create(context.data())); + QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(o.data()); QVERIFY(visualModel); visualModel->setModel(QVariant(3)); @@ -4349,6 +4344,20 @@ void tst_qquickvisualdatamodel::delegateModelChangeDelegate() QCOMPARE(visualModel->count(), 3); } +void tst_qquickvisualdatamodel::noDoubleDelegateUpdate() +{ + // changing a delegate only refreshes its instances once + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("setDelegateNoDoubleChange.qml")); + + QScopedPointer<QObject> root(component.create()); + QVERIFY(root); + + bool ok = root->setProperty("testStarted", true); + QVERIFY(ok); + QCOMPARE(root->property("creationCount").toInt(), 1); +} + void tst_qquickvisualdatamodel::checkFilterGroupForDelegate() { QQuickView view; @@ -4377,6 +4386,106 @@ void tst_qquickvisualdatamodel::readFromProxyObject() QTRY_VERIFY(window->property("name").toString() != QLatin1String("wrong")); } + +class ComponentEntity : public QObject +{ + Q_OBJECT + +public: + ComponentEntity(QObject *parent = nullptr) : QObject(parent) + { + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + } +}; + +class InventoryModel : public QAbstractListModel +{ + Q_OBJECT + +public: + InventoryModel() { + for (int i = 0; i < 10; ++i) { + QSharedPointer<ComponentEntity> entity(new ComponentEntity()); + entity->setObjectName(QString::fromLatin1("Item %1").arg(i)); + mContents.append(entity); + } + } + + int rowCount(const QModelIndex &) const override { return mContents.size(); } + + QVariant data(const QModelIndex &index, int role) const override + { + if (!checkIndex(index, CheckIndexOption::IndexIsValid)) + return {}; + + auto entity = mContents.at(index.row()).data(); + switch (role) { + case ItemNameRole: return entity->objectName(); + case EntityRole: return QVariant::fromValue(entity); + } + + return {}; + } + + Q_INVOKABLE void removeLast() { + const int index = rowCount(QModelIndex()) - 1; + if (index < 0) + return; + + const auto item = mContents.at(index); + beginRemoveRows(QModelIndex(), index, index); + mContents.takeLast(); + endRemoveRows(); + } + + enum InventoryModelRoles { + ItemNameRole = Qt::UserRole, + EntityRole + }; + + virtual QHash<int, QByteArray> roleNames() const override { + QHash<int, QByteArray> names; + names.insert(ItemNameRole, "itemName"); + names.insert(EntityRole, "entity"); + return names; + } + +private: + QVector<QSharedPointer<ComponentEntity>> mContents; +}; + + +static QString lastWarning; +static QtMessageHandler oldHandler; +static void warningsHandler(QtMsgType type, const QMessageLogContext &ctxt, const QString &msg) +{ + if (type == QtWarningMsg) + lastWarning = msg; + else + oldHandler(type, ctxt, msg); +} + +void tst_qquickvisualdatamodel::noWarningOnObjectDeletion() +{ + qmlRegisterType<InventoryModel>("TestTypes", 1, 0, "InventoryModel"); + qmlRegisterUncreatableType<ComponentEntity>("TestTypes", 1, 0, "ComponentEntity", "no"); + + oldHandler = qInstallMessageHandler(warningsHandler); + const auto guard = qScopeGuard([&]() { qInstallMessageHandler(oldHandler); }); + + { + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("objectDeletion.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + for (int i = 0; i < 5; ++i) + o->metaObject()->invokeMethod(o.data(), "removeLast"); + } + + QVERIFY2(lastWarning.isEmpty(), qPrintable(lastWarning)); +} + QTEST_MAIN(tst_qquickvisualdatamodel) #include "tst_qquickvisualdatamodel.moc" |