1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2018 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | #include "../../shared/util.h" |
29 | #include "../shared/visualtestutil.h" |
30 | #include "../shared/viewtestutil.h" |
31 | |
32 | #include <qtest.h> |
33 | #include <QtCore/qregularexpression.h> |
34 | #include <QtTest/QSignalSpy> |
35 | #include <QtQml/qqmlengine.h> |
36 | #include <QtQml/qqmlcomponent.h> |
37 | #include <QtQml/qqmlcontext.h> |
38 | #include <QtQml/qqmlexpression.h> |
39 | #include <QtQml/qqmlincubator.h> |
40 | #include <QtQuick/qquickview.h> |
41 | #include <private/qquicklistview_p.h> |
42 | #include <QtQuick/private/qquicktext_p.h> |
43 | #include <QtQmlModels/private/qqmldelegatemodel_p.h> |
44 | #include <private/qqmlvaluetype_p.h> |
45 | #include <private/qqmlchangeset_p.h> |
46 | #include <private/qqmlengine_p.h> |
47 | #include <math.h> |
48 | #include <QtGui/qstandarditemmodel.h> |
49 | |
50 | using namespace QQuickVisualTestUtil; |
51 | using namespace QQuickViewTestUtil; |
52 | |
53 | template <typename T, int N> int lengthOf(const T (&)[N]) { return N; } |
54 | |
55 | static void initStandardTreeModel(QStandardItemModel *model) |
56 | { |
57 | QStandardItem *item; |
58 | item = new QStandardItem(QLatin1String("Row 1 Item" )); |
59 | model->insertRow(arow: 0, aitem: item); |
60 | |
61 | item = new QStandardItem(QLatin1String("Row 2 Item" )); |
62 | item->setCheckable(true); |
63 | model->insertRow(arow: 1, aitem: item); |
64 | |
65 | QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item" )); |
66 | item->setChild(arow: 0, aitem: childItem); |
67 | |
68 | item = new QStandardItem(QLatin1String("Row 3 Item" )); |
69 | item->setIcon(QIcon()); |
70 | model->insertRow(arow: 2, aitem: item); |
71 | } |
72 | |
73 | class SingleRoleModel : public QAbstractItemModel |
74 | { |
75 | Q_OBJECT |
76 | Q_PROPERTY(QStringList values READ getList WRITE setList) |
77 | public: |
78 | struct Branch; |
79 | struct Node { |
80 | Node(const QString &display = QString()) : branch(nullptr), display(display) {} |
81 | Branch *branch; |
82 | QString display; |
83 | }; |
84 | |
85 | struct Branch { |
86 | Branch(Branch *parent = nullptr) : parent(parent) {} |
87 | ~Branch() { foreach (const Node &child, children) delete child.branch; } |
88 | int indexOf(Branch *branch) const { |
89 | for (int i = 0; i < children.count(); ++i) { |
90 | if (children.at(i).branch == branch) |
91 | return i; |
92 | } |
93 | return -1; |
94 | } |
95 | Branch *parent; |
96 | QVector<Node> children; |
97 | |
98 | }; |
99 | |
100 | SingleRoleModel(const QStringList &list = QStringList(), const QByteArray &role = "name" , QObject *parent = nullptr) |
101 | : QAbstractItemModel(parent), m_role(role) |
102 | { |
103 | foreach (const QString &string, list) |
104 | trunk.children.append(t: Node(string)); |
105 | } |
106 | ~SingleRoleModel() {} |
107 | |
108 | QHash<int,QByteArray> roleNames() const |
109 | { |
110 | QHash<int,QByteArray> roles; |
111 | roles.insert(key: Qt::DisplayRole, value: m_role); |
112 | return roles; |
113 | } |
114 | |
115 | Branch *branchForIndex(const QModelIndex &index) const { |
116 | return index.isValid() |
117 | ? static_cast<Branch *>(index.internalPointer())->children.at(i: index.row()).branch |
118 | : const_cast<Branch *>(&trunk); |
119 | } |
120 | |
121 | Branch *createBranchForIndex(const QModelIndex &index) const { |
122 | if (index.isValid()) { |
123 | Branch * const parentBranch = static_cast<Branch *>(index.internalPointer()); |
124 | Node &node = parentBranch->children[index.row()]; |
125 | if (!node.branch) |
126 | node.branch = new Branch(parentBranch); |
127 | return node.branch; |
128 | } else { |
129 | return const_cast<Branch *>(&trunk); |
130 | } |
131 | } |
132 | |
133 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const { |
134 | if (row < 0 || column != 0) |
135 | return QModelIndex(); |
136 | Branch * const branch = branchForIndex(index: parent); |
137 | return branch && row < branch->children.count() |
138 | ? createIndex(arow: row, acolumn: column, adata: branch) |
139 | : QModelIndex(); |
140 | } |
141 | |
142 | QModelIndex parent(const QModelIndex &child) const { |
143 | Branch * const branch = static_cast<Branch *>(child.internalPointer()); |
144 | return branch->parent |
145 | ? createIndex(arow: branch->parent->indexOf(branch), acolumn: 0, adata: branch->parent) |
146 | : QModelIndex(); |
147 | } |
148 | |
149 | int rowCount(const QModelIndex &parent) const { |
150 | Branch * const branch = branchForIndex(index: parent); |
151 | return branch ? branch->children.count() : 0; |
152 | } |
153 | |
154 | int columnCount(const QModelIndex &parent) const { |
155 | Branch * const branch = branchForIndex(index: parent); |
156 | return branch ? 1 : 0; |
157 | } |
158 | |
159 | QVariant data(const QModelIndex &index, int role) const { |
160 | return index.isValid() && role == Qt::DisplayRole |
161 | ? static_cast<Branch *>(index.internalPointer())->children.at(i: index.row()).display |
162 | : QVariant(); |
163 | } |
164 | |
165 | void insert(const QModelIndex &parent, int index, const QStringList &data) { |
166 | beginInsertRows(parent, first: index, last: index + data.count() - 1); |
167 | Branch * const branch = createBranchForIndex(index: parent); |
168 | for (int i = 0; i < data.count(); ++i) |
169 | branch->children.insert(i: index + i, t: Node(data.at(i))); |
170 | endInsertRows(); |
171 | } |
172 | |
173 | void remove(const QModelIndex &parent, int index, int count) { |
174 | beginRemoveRows(parent, first: index, last: index + count - 1); |
175 | Branch * const branch = branchForIndex(index: parent); |
176 | for (int i = 0; i < count; ++i) { |
177 | delete branch->children.at(i: index).branch; |
178 | branch->children.remove(i: index); |
179 | } |
180 | endRemoveRows(); |
181 | } |
182 | |
183 | void move(const QModelIndex &fromParent, int from, const QModelIndex &toParent, int to, int count) { |
184 | beginMoveRows(sourceParent: fromParent, sourceFirst: from, sourceLast: from + count - 1, destinationParent: toParent, destinationRow: to); |
185 | Branch * const fromBranch = branchForIndex(index: fromParent); |
186 | Branch * const toBranch = createBranchForIndex(index: toParent); |
187 | |
188 | if (fromBranch == toBranch) { |
189 | qquickmodelviewstestutil_move(from, to, n: count, items: &fromBranch->children); |
190 | } else { |
191 | for (int i = 0; i < count; ++i) { |
192 | Node node = fromBranch->children.at(i: from); |
193 | fromBranch->children.remove(i: from); |
194 | if (node.branch) |
195 | node.branch->parent = toBranch; |
196 | toBranch->children.insert(i: to + i, t: node); |
197 | |
198 | } |
199 | } |
200 | endMoveRows(); |
201 | } |
202 | |
203 | void emitMove(int sourceFirst, int sourceLast, int destinationChild) { |
204 | emit beginMoveRows(sourceParent: QModelIndex(), sourceFirst, sourceLast, destinationParent: QModelIndex(), destinationRow: destinationChild); |
205 | emit endMoveRows(); |
206 | } |
207 | |
208 | QStringList getList() const { |
209 | QStringList list; |
210 | foreach (const Node &node, trunk.children) |
211 | list.append(t: node.display); |
212 | return list; |
213 | } |
214 | |
215 | void setList(const QStringList &l) { |
216 | if (trunk.children.count() > 0) { |
217 | beginRemoveRows(parent: QModelIndex(), first: 0, last: trunk.children.count() - 1); |
218 | foreach (const Node &child, trunk.children) delete child.branch; |
219 | trunk.children.clear(); |
220 | endRemoveRows(); |
221 | } |
222 | if (l.count() > 0) { |
223 | beginInsertRows(parent: QModelIndex(), first: 0, last: l.count() -1); |
224 | foreach (const QString &string, l) |
225 | trunk.children.append(t: Node(string)); |
226 | endInsertRows(); |
227 | } |
228 | } |
229 | |
230 | QString at(int index) const { return trunk.children.at(i: index).display; } |
231 | |
232 | public slots: |
233 | void set(int idx, QString string) { |
234 | trunk.children[idx].display = string; |
235 | emit dataChanged(topLeft: createIndex(arow: idx, acolumn: 0, adata: &trunk), bottomRight: createIndex(arow: idx, acolumn: 0, adata: &trunk)); |
236 | } |
237 | |
238 | private: |
239 | const QByteArray m_role; |
240 | Branch trunk; |
241 | }; |
242 | |
243 | class StandardItem : public QObject, public QStandardItem |
244 | { |
245 | Q_OBJECT |
246 | Q_PROPERTY(QString text READ readText WRITE setText) |
247 | |
248 | public: |
249 | QString readText() const { return text(); } |
250 | void writeText(const QString &text) { setText(text); } |
251 | }; |
252 | |
253 | class StandardItemModel : public QStandardItemModel |
254 | { |
255 | Q_OBJECT |
256 | Q_PROPERTY(QQmlListProperty<StandardItem> items READ items CONSTANT) |
257 | Q_CLASSINFO("DefaultProperty" , "items" ) |
258 | public: |
259 | QQmlListProperty<StandardItem> items() { return QQmlListProperty<StandardItem>(this, nullptr, append, nullptr, nullptr, nullptr); } |
260 | |
261 | static void append(QQmlListProperty<StandardItem> *property, StandardItem *item) |
262 | { |
263 | static_cast<QStandardItemModel *>(property->object)->appendRow(aitem: item); |
264 | } |
265 | }; |
266 | |
267 | class DataSubObject : public QObject |
268 | { |
269 | Q_OBJECT |
270 | |
271 | Q_PROPERTY(QString subName READ subName WRITE setSubName NOTIFY subNameChanged) |
272 | |
273 | public: |
274 | DataSubObject(QObject *parent=nullptr) : QObject(parent) {} |
275 | |
276 | QString subName() const { return m_subName; } |
277 | void setSubName(const QString &name) { |
278 | if (name != m_subName) { |
279 | m_subName = name; |
280 | emit subNameChanged(); |
281 | } |
282 | } |
283 | |
284 | signals: |
285 | void subNameChanged(); |
286 | |
287 | private: |
288 | QString m_subName; |
289 | }; |
290 | |
291 | class DataObject : public QObject |
292 | { |
293 | Q_OBJECT |
294 | |
295 | Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) |
296 | Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged) |
297 | Q_PROPERTY(QObject *object READ object) |
298 | |
299 | public: |
300 | DataObject(QObject *parent=nullptr) : QObject(parent) {} |
301 | DataObject(const QString &name, const QString &color, QObject *parent=nullptr) |
302 | : QObject(parent), m_name(name), m_color(color), m_object(new DataSubObject(this)) { } |
303 | |
304 | |
305 | QString name() const { return m_name; } |
306 | void setName(const QString &name) { |
307 | if (name != m_name) { |
308 | m_name = name; |
309 | emit nameChanged(); |
310 | } |
311 | } |
312 | |
313 | QString color() const { return m_color; } |
314 | void setColor(const QString &color) { |
315 | if (color != m_color) { |
316 | m_color = color; |
317 | emit colorChanged(); |
318 | } |
319 | } |
320 | |
321 | QObject *object() const { return m_object; } |
322 | void setSubName(const QString &sn) { |
323 | m_object->setSubName(sn); |
324 | } |
325 | |
326 | signals: |
327 | void nameChanged(); |
328 | void colorChanged(); |
329 | |
330 | private: |
331 | QString m_name; |
332 | QString m_color; |
333 | DataSubObject *m_object; |
334 | }; |
335 | |
336 | class ItemRequester : public QObject |
337 | { |
338 | Q_OBJECT |
339 | public: |
340 | ItemRequester(QObject *parent = nullptr) |
341 | : QObject(parent) |
342 | , itemInitialized(nullptr) |
343 | , itemCreated(nullptr) |
344 | , itemDestroyed(nullptr) |
345 | , indexInitialized(-1) |
346 | , indexCreated(-1) |
347 | { |
348 | } |
349 | |
350 | QQuickItem *itemInitialized; |
351 | QQuickItem *itemCreated; |
352 | QQuickItem *itemDestroyed; |
353 | int indexInitialized; |
354 | int indexCreated; |
355 | |
356 | public Q_SLOTS: |
357 | void initItem(int index, QObject *item) |
358 | { |
359 | itemInitialized = qobject_cast<QQuickItem*>(object: item); |
360 | indexInitialized = index; |
361 | } |
362 | |
363 | void createdItem(int index, QObject *item) |
364 | { |
365 | itemCreated = qobject_cast<QQuickItem*>(object: item); |
366 | indexCreated = index; |
367 | } |
368 | |
369 | void destroyingItem(QObject *item) |
370 | { |
371 | itemDestroyed = qobject_cast<QQuickItem*>(object: item); |
372 | } |
373 | }; |
374 | |
375 | QML_DECLARE_TYPE(SingleRoleModel) |
376 | QML_DECLARE_TYPE(DataObject) |
377 | QML_DECLARE_TYPE(StandardItem) |
378 | QML_DECLARE_TYPE(StandardItemModel) |
379 | |
380 | class tst_qquickvisualdatamodel : public QQmlDataTest |
381 | { |
382 | Q_OBJECT |
383 | public: |
384 | tst_qquickvisualdatamodel(); |
385 | |
386 | private slots: |
387 | void initTestCase(); |
388 | void cleanupTestCase(); |
389 | void rootIndex(); |
390 | void updateLayout_data(); |
391 | void updateLayout(); |
392 | void childChanged_data(); |
393 | void childChanged(); |
394 | void noDelegate_data(); |
395 | void noDelegate(); |
396 | void itemsDestroyed_data(); |
397 | void itemsDestroyed(); |
398 | void objectListModel(); |
399 | void singleRole(); |
400 | void modelProperties(); |
401 | void packagesDestroyed(); |
402 | void qaimRowsMoved(); |
403 | void qaimRowsMoved_data(); |
404 | void subtreeRowsMoved(); |
405 | void watchedRoles(); |
406 | void hasModelChildren(); |
407 | void setValue(); |
408 | void remove_data(); |
409 | void remove(); |
410 | void move_data(); |
411 | void move(); |
412 | void groups_data(); |
413 | void groups(); |
414 | void invalidGroups(); |
415 | void get(); |
416 | void onChanged_data(); |
417 | void onChanged(); |
418 | void create(); |
419 | void incompleteModel(); |
420 | void insert_data(); |
421 | void insert(); |
422 | void resolve_data(); |
423 | void resolve(); |
424 | void warnings_data(); |
425 | void warnings(); |
426 | void invalidAttachment(); |
427 | void asynchronousInsert_data(); |
428 | void asynchronousInsert(); |
429 | void asynchronousRemove_data(); |
430 | void asynchronousRemove(); |
431 | void asynchronousMove(); |
432 | void asynchronousMove_data(); |
433 | void asynchronousCancel(); |
434 | void invalidContext(); |
435 | void externalManagedModel(); |
436 | void delegateModelChangeDelegate(); |
437 | void checkFilterGroupForDelegate(); |
438 | void readFromProxyObject(); |
439 | |
440 | private: |
441 | template <int N> void groups_verify( |
442 | const SingleRoleModel &model, |
443 | QQuickItem *contentItem, |
444 | const int (&mIndex)[N], |
445 | const int (&iIndex)[N], |
446 | const int (&vIndex)[N], |
447 | const int (&sIndex)[N], |
448 | const bool (&vMember)[N], |
449 | const bool (&sMember)[N]); |
450 | |
451 | template <int N> void get_verify( |
452 | const SingleRoleModel &model, |
453 | QQmlDelegateModel *visualModel, |
454 | QQmlDelegateModelGroup *visibleItems, |
455 | QQmlDelegateModelGroup *selectedItems, |
456 | const int (&mIndex)[N], |
457 | const int (&iIndex)[N], |
458 | const int (&vIndex)[N], |
459 | const int (&sIndex)[N], |
460 | const bool (&vMember)[N], |
461 | const bool (&sMember)[N]); |
462 | |
463 | bool failed; |
464 | QQmlIncubationController controller; |
465 | QQmlEngine engine; |
466 | }; |
467 | |
468 | Q_DECLARE_METATYPE(QQmlChangeSet) |
469 | |
470 | template <typename T> static T evaluate(QObject *scope, const QString &expression) |
471 | { |
472 | QQmlExpression expr(qmlContext(scope), scope, expression); |
473 | T result = expr.evaluate().value<T>(); |
474 | if (expr.hasError()) |
475 | qWarning() << expr.error().toString(); |
476 | return result; |
477 | } |
478 | |
479 | template <> void evaluate<void>(QObject *scope, const QString &expression) |
480 | { |
481 | QQmlExpression expr(qmlContext(scope), scope, expression); |
482 | expr.evaluate(); |
483 | if (expr.hasError()) |
484 | qWarning() << expr.error().toString(); |
485 | } |
486 | |
487 | void tst_qquickvisualdatamodel::initTestCase() |
488 | { |
489 | QQmlDataTest::initTestCase(); |
490 | qRegisterMetaType<QQmlChangeSet>(); |
491 | |
492 | qmlRegisterType<SingleRoleModel>(uri: "tst_qquickvisualdatamodel" , versionMajor: 1, versionMinor: 0, qmlName: "SingleRoleModel" ); |
493 | qmlRegisterType<DataObject>(uri: "tst_qquickvisualdatamodel" , versionMajor: 1, versionMinor: 0, qmlName: "DataObject" ); |
494 | qmlRegisterType<StandardItem>(uri: "tst_qquickvisualdatamodel" , versionMajor: 1, versionMinor: 0, qmlName: "StandardItem" ); |
495 | qmlRegisterType<StandardItemModel>(uri: "tst_qquickvisualdatamodel" , versionMajor: 1, versionMinor: 0, qmlName: "StandardItemModel" ); |
496 | |
497 | engine.setIncubationController(&controller); |
498 | } |
499 | |
500 | void tst_qquickvisualdatamodel::cleanupTestCase() |
501 | { |
502 | } |
503 | |
504 | tst_qquickvisualdatamodel::tst_qquickvisualdatamodel() |
505 | { |
506 | } |
507 | |
508 | void tst_qquickvisualdatamodel::rootIndex() |
509 | { |
510 | QQmlEngine engine; |
511 | QQmlComponent c(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
512 | |
513 | QStandardItemModel model; |
514 | initStandardTreeModel(model: &model); |
515 | |
516 | engine.rootContext()->setContextProperty("myModel" , &model); |
517 | |
518 | QQmlDelegateModel *obj = qobject_cast<QQmlDelegateModel*>(object: c.create()); |
519 | QVERIFY(obj != nullptr); |
520 | |
521 | QMetaObject::invokeMethod(obj, member: "setRoot" ); |
522 | QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), model.index(0,0)); |
523 | |
524 | QMetaObject::invokeMethod(obj, member: "setRootToParent" ); |
525 | QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), QModelIndex()); |
526 | |
527 | QMetaObject::invokeMethod(obj, member: "setRoot" ); |
528 | QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), model.index(0,0)); |
529 | model.clear(); // will emit modelReset() |
530 | QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), QModelIndex()); |
531 | |
532 | delete obj; |
533 | } |
534 | |
535 | void tst_qquickvisualdatamodel::updateLayout_data() |
536 | { |
537 | QTest::addColumn<QUrl>(name: "source" ); |
538 | |
539 | QTest::newRow(dataTag: "item delegate" ) << testFileUrl(fileName: "datalist.qml" ); |
540 | QTest::newRow(dataTag: "package delegate" ) << testFileUrl(fileName: "datalist-package.qml" ); |
541 | } |
542 | |
543 | void tst_qquickvisualdatamodel::updateLayout() |
544 | { |
545 | QFETCH(QUrl, source); |
546 | |
547 | QQuickView view; |
548 | |
549 | QStandardItemModel model; |
550 | initStandardTreeModel(model: &model); |
551 | |
552 | view.rootContext()->setContextProperty("myModel" , &model); |
553 | |
554 | view.setSource(source); |
555 | |
556 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
557 | QVERIFY(listview != nullptr); |
558 | |
559 | QQuickItem *contentItem = listview->contentItem(); |
560 | QVERIFY(contentItem != nullptr); |
561 | |
562 | QQuickText *name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 0); |
563 | QVERIFY(name); |
564 | QCOMPARE(name->text(), QString("Row 1 Item" )); |
565 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 1); |
566 | QVERIFY(name); |
567 | QCOMPARE(name->text(), QString("Row 2 Item" )); |
568 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 2); |
569 | QVERIFY(name); |
570 | QCOMPARE(name->text(), QString("Row 3 Item" )); |
571 | |
572 | model.invisibleRootItem()->sortChildren(column: 0, order: Qt::DescendingOrder); |
573 | |
574 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 0); |
575 | QVERIFY(name); |
576 | QCOMPARE(name->text(), QString("Row 3 Item" )); |
577 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 1); |
578 | QVERIFY(name); |
579 | QCOMPARE(name->text(), QString("Row 2 Item" )); |
580 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 2); |
581 | QVERIFY(name); |
582 | QCOMPARE(name->text(), QString("Row 1 Item" )); |
583 | } |
584 | |
585 | void tst_qquickvisualdatamodel::childChanged_data() |
586 | { |
587 | QTest::addColumn<QUrl>(name: "source" ); |
588 | |
589 | QTest::newRow(dataTag: "item delegate" ) << testFileUrl(fileName: "datalist.qml" ); |
590 | QTest::newRow(dataTag: "package delegate" ) << testFileUrl(fileName: "datalist-package.qml" ); |
591 | } |
592 | |
593 | void tst_qquickvisualdatamodel::childChanged() |
594 | { |
595 | QFETCH(QUrl, source); |
596 | |
597 | QQuickView view; |
598 | |
599 | QStandardItemModel model; |
600 | initStandardTreeModel(model: &model); |
601 | |
602 | view.rootContext()->setContextProperty("myModel" , &model); |
603 | |
604 | view.setSource(source); |
605 | |
606 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
607 | QVERIFY(listview != nullptr); |
608 | |
609 | QQuickItem *contentItem = listview->contentItem(); |
610 | QVERIFY(contentItem != nullptr); |
611 | |
612 | QQmlDelegateModel *vdm = listview->findChild<QQmlDelegateModel*>(aName: "visualModel" ); |
613 | vdm->setRootIndex(QVariant::fromValue(value: model.indexFromItem(item: model.item(row: 1,column: 0)))); |
614 | QCOMPARE(listview->count(), 1); |
615 | |
616 | listview->forceLayout(); |
617 | QQuickText *name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 0); |
618 | QVERIFY(name); |
619 | QCOMPARE(name->text(), QString("Row 2 Child Item" )); |
620 | |
621 | model.item(row: 1,column: 0)->child(row: 0,column: 0)->setText("Row 2 updated child" ); |
622 | |
623 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 0); |
624 | QVERIFY(name); |
625 | QCOMPARE(name->text(), QString("Row 2 updated child" )); |
626 | |
627 | model.item(row: 1,column: 0)->appendRow(aitem: new QStandardItem(QLatin1String("Row 2 Child Item 2" ))); |
628 | QCOMPARE(listview->count(), 2); |
629 | |
630 | listview->forceLayout(); |
631 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 1); |
632 | QVERIFY(name != nullptr); |
633 | QCOMPARE(name->text(), QString("Row 2 Child Item 2" )); |
634 | |
635 | model.item(row: 1,column: 0)->takeRow(row: 1); |
636 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 1); |
637 | QVERIFY(!name); |
638 | |
639 | vdm->setRootIndex(QVariant::fromValue(value: QModelIndex())); |
640 | QCOMPARE(listview->count(), 3); |
641 | |
642 | listview->forceLayout(); |
643 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 0); |
644 | QVERIFY(name); |
645 | QCOMPARE(name->text(), QString("Row 1 Item" )); |
646 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 1); |
647 | QVERIFY(name); |
648 | QCOMPARE(name->text(), QString("Row 2 Item" )); |
649 | name = findItem<QQuickText>(parent: contentItem, objectName: "display" , index: 2); |
650 | QVERIFY(name); |
651 | QCOMPARE(name->text(), QString("Row 3 Item" )); |
652 | } |
653 | |
654 | void tst_qquickvisualdatamodel::objectListModel() |
655 | { |
656 | QQuickView view; |
657 | |
658 | QList<QObject*> dataList; |
659 | dataList.append(t: new DataObject("Item 1" , "red" )); |
660 | dataList.append(t: new DataObject("Item 2" , "green" )); |
661 | dataList.append(t: new DataObject("Item 3" , "blue" )); |
662 | dataList.append(t: new DataObject("Item 4" , "yellow" )); |
663 | |
664 | QQmlContext *ctxt = view.rootContext(); |
665 | ctxt->setContextProperty("myModel" , QVariant::fromValue(value: dataList)); |
666 | |
667 | view.setSource(testFileUrl(fileName: "objectlist.qml" )); |
668 | |
669 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
670 | QVERIFY(listview != nullptr); |
671 | |
672 | QQuickItem *contentItem = listview->contentItem(); |
673 | QVERIFY(contentItem != nullptr); |
674 | |
675 | QQuickText *name = findItem<QQuickText>(parent: contentItem, objectName: "name" , index: 0); |
676 | QCOMPARE(name->text(), QString("Item 1" )); |
677 | QCOMPARE(name->property("modelName" ).toString(), QString("Item 1" )); |
678 | |
679 | QQuickText *section = findItem<QQuickText>(parent: contentItem, objectName: "section" , index: 0); |
680 | QCOMPARE(section->text(), QString("Item 1" )); |
681 | |
682 | dataList[0]->setProperty(name: "name" , value: QLatin1String("Changed" )); |
683 | QCOMPARE(name->text(), QString("Changed" )); |
684 | QCOMPARE(name->property("modelName" ).toString(), QString("Changed" )); |
685 | |
686 | // Test resolving nested section property |
687 | DataObject *obj = static_cast<DataObject*>(dataList[0]); |
688 | obj->setSubName("SubItem 1" ); |
689 | |
690 | QMetaObject::invokeMethod(obj: listview, member: "changeSectionProperty" ); |
691 | section = findItem<QQuickText>(parent: contentItem, objectName: "section" , index: 0); |
692 | QCOMPARE(section->text(), QString("SubItem 1" )); |
693 | } |
694 | |
695 | void tst_qquickvisualdatamodel::singleRole() |
696 | { |
697 | QStringList list = QStringList() << "one" << "two" << "three" << "four" ; |
698 | { |
699 | QQuickView view; |
700 | |
701 | SingleRoleModel model(list); |
702 | |
703 | QQmlContext *ctxt = view.rootContext(); |
704 | ctxt->setContextProperty("myModel" , &model); |
705 | |
706 | view.setSource(testFileUrl(fileName: "singlerole1.qml" )); |
707 | |
708 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
709 | QVERIFY(listview != nullptr); |
710 | |
711 | QQuickItem *contentItem = listview->contentItem(); |
712 | QVERIFY(contentItem != nullptr); |
713 | |
714 | QQuickText *name = findItem<QQuickText>(parent: contentItem, objectName: "name" , index: 1); |
715 | QCOMPARE(name->text(), QString("two" )); |
716 | |
717 | model.set(idx: 1, string: "Changed" ); |
718 | QCOMPARE(name->text(), QString("Changed" )); |
719 | } |
720 | { |
721 | QQuickView view; |
722 | |
723 | SingleRoleModel model(list); |
724 | |
725 | QQmlContext *ctxt = view.rootContext(); |
726 | ctxt->setContextProperty("myModel" , &model); |
727 | |
728 | view.setSource(testFileUrl(fileName: "singlerole2.qml" )); |
729 | |
730 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
731 | QVERIFY(listview != nullptr); |
732 | |
733 | QQuickItem *contentItem = listview->contentItem(); |
734 | QVERIFY(contentItem != nullptr); |
735 | |
736 | QQuickText *name = findItem<QQuickText>(parent: contentItem, objectName: "name" , index: 1); |
737 | QCOMPARE(name->text(), QString("two" )); |
738 | |
739 | model.set(idx: 1, string: "Changed" ); |
740 | QCOMPARE(name->text(), QString("Changed" )); |
741 | } |
742 | { |
743 | QQuickView view; |
744 | |
745 | SingleRoleModel model(list, "modelData" ); |
746 | |
747 | QQmlContext *ctxt = view.rootContext(); |
748 | ctxt->setContextProperty("myModel" , &model); |
749 | |
750 | view.setSource(testFileUrl(fileName: "singlerole2.qml" )); |
751 | |
752 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
753 | QVERIFY(listview != nullptr); |
754 | |
755 | QQuickItem *contentItem = listview->contentItem(); |
756 | QVERIFY(contentItem != nullptr); |
757 | |
758 | QQuickText *name = findItem<QQuickText>(parent: contentItem, objectName: "name" , index: 1); |
759 | QCOMPARE(name->text(), QString("two" )); |
760 | |
761 | model.set(idx: 1, string: "Changed" ); |
762 | QCOMPARE(name->text(), QString("Changed" )); |
763 | } |
764 | } |
765 | |
766 | void tst_qquickvisualdatamodel::modelProperties() |
767 | { |
768 | { |
769 | QQuickView view; |
770 | |
771 | SingleRoleModel model(QStringList() << "one" << "two" << "three" << "four" ); |
772 | |
773 | QQmlContext *ctxt = view.rootContext(); |
774 | ctxt->setContextProperty("myModel" , &model); |
775 | |
776 | view.setSource(testFileUrl(fileName: "modelproperties.qml" )); |
777 | |
778 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
779 | QVERIFY(listview != nullptr); |
780 | |
781 | QQuickItem *contentItem = listview->contentItem(); |
782 | QVERIFY(contentItem != nullptr); |
783 | |
784 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: 1); |
785 | QVERIFY(delegate); |
786 | QCOMPARE(delegate->property("test1" ).toString(),QString("two" )); |
787 | QCOMPARE(delegate->property("test2" ).toString(),QString("two" )); |
788 | QCOMPARE(delegate->property("test3" ).toString(),QString("two" )); |
789 | QCOMPARE(delegate->property("test4" ).toString(),QString("two" )); |
790 | QVERIFY(!delegate->property("test9" ).isValid()); |
791 | QCOMPARE(delegate->property("test5" ).toString(),QString("" )); |
792 | QVERIFY(delegate->property("test6" ).value<QObject*>() != 0); |
793 | QCOMPARE(delegate->property("test7" ).toInt(),1); |
794 | QCOMPARE(delegate->property("test8" ).toInt(),1); |
795 | } |
796 | |
797 | { |
798 | QQuickView view; |
799 | |
800 | QList<QObject*> dataList; |
801 | dataList.append(t: new DataObject("Item 1" , "red" )); |
802 | dataList.append(t: new DataObject("Item 2" , "green" )); |
803 | dataList.append(t: new DataObject("Item 3" , "blue" )); |
804 | dataList.append(t: new DataObject("Item 4" , "yellow" )); |
805 | |
806 | QQmlContext *ctxt = view.rootContext(); |
807 | ctxt->setContextProperty("myModel" , QVariant::fromValue(value: dataList)); |
808 | |
809 | view.setSource(testFileUrl(fileName: "modelproperties.qml" )); |
810 | |
811 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
812 | QVERIFY(listview != nullptr); |
813 | |
814 | QQuickItem *contentItem = listview->contentItem(); |
815 | QVERIFY(contentItem != nullptr); |
816 | |
817 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: 1); |
818 | QVERIFY(delegate); |
819 | QCOMPARE(delegate->property("test1" ).toString(),QString("Item 2" )); |
820 | QCOMPARE(delegate->property("test2" ).toString(),QString("Item 2" )); |
821 | QVERIFY(qobject_cast<DataObject*>(delegate->property("test3" ).value<QObject*>()) != 0); |
822 | QVERIFY(qobject_cast<DataObject*>(delegate->property("test4" ).value<QObject*>()) != 0); |
823 | QCOMPARE(delegate->property("test5" ).toString(),QString("Item 2" )); |
824 | QCOMPARE(delegate->property("test9" ).toString(),QString("Item 2" )); |
825 | QVERIFY(delegate->property("test6" ).value<QObject*>() != 0); |
826 | QCOMPARE(delegate->property("test7" ).toInt(),1); |
827 | QCOMPARE(delegate->property("test8" ).toInt(),1); |
828 | } |
829 | |
830 | { |
831 | QQuickView view; |
832 | |
833 | DataObject object("Item 1" , "red" ); |
834 | |
835 | QQmlContext *ctxt = view.rootContext(); |
836 | ctxt->setContextProperty("myModel" , &object); |
837 | |
838 | view.setSource(testFileUrl(fileName: "modelproperties.qml" )); |
839 | |
840 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
841 | QVERIFY(listview != nullptr); |
842 | |
843 | QQuickItem *contentItem = listview->contentItem(); |
844 | QVERIFY(contentItem != nullptr); |
845 | |
846 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: 0); |
847 | QVERIFY(delegate); |
848 | QCOMPARE(delegate->property("test1" ).toString(),QString("Item 1" )); |
849 | QCOMPARE(delegate->property("test2" ).toString(),QString("Item 1" )); |
850 | QVERIFY(qobject_cast<DataObject*>(delegate->property("test3" ).value<QObject*>()) != 0); |
851 | QVERIFY(qobject_cast<DataObject*>(delegate->property("test4" ).value<QObject*>()) != 0); |
852 | QCOMPARE(delegate->property("test5" ).toString(),QString("Item 1" )); |
853 | QCOMPARE(delegate->property("test9" ).toString(),QString("Item 1" )); |
854 | QVERIFY(delegate->property("test6" ).value<QObject*>() != 0); |
855 | QCOMPARE(delegate->property("test7" ).toInt(), 0); |
856 | QCOMPARE(delegate->property("test8" ).toInt(), 0); |
857 | } |
858 | |
859 | { |
860 | QQuickView view; |
861 | |
862 | QStandardItemModel model; |
863 | initStandardTreeModel(model: &model); |
864 | |
865 | view.rootContext()->setContextProperty("myModel" , &model); |
866 | |
867 | QUrl source(testFileUrl(fileName: "modelproperties2.qml" )); |
868 | |
869 | //3 items, 3 i each |
870 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined" ); |
871 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined" ); |
872 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined" ); |
873 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined" ); |
874 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined" ); |
875 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined" ); |
876 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined" ); |
877 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined" ); |
878 | QTest::ignoreMessage(type: QtWarningMsg, message: source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined" ); |
879 | |
880 | view.setSource(source); |
881 | |
882 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
883 | QVERIFY(listview != nullptr); |
884 | |
885 | QQuickItem *contentItem = listview->contentItem(); |
886 | QVERIFY(contentItem != nullptr); |
887 | |
888 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: 1); |
889 | QVERIFY(delegate); |
890 | QCOMPARE(delegate->property("test1" ).toString(),QString("Row 2 Item" )); |
891 | QCOMPARE(delegate->property("test2" ).toString(),QString("Row 2 Item" )); |
892 | QVERIFY(!delegate->property("test3" ).isValid()); |
893 | QVERIFY(!delegate->property("test4" ).isValid()); |
894 | QVERIFY(!delegate->property("test5" ).isValid()); |
895 | QVERIFY(!delegate->property("test9" ).isValid()); |
896 | QVERIFY(delegate->property("test6" ).value<QObject*>() != 0); |
897 | QCOMPARE(delegate->property("test7" ).toInt(),1); |
898 | QCOMPARE(delegate->property("test8" ).toInt(),1); |
899 | } |
900 | //### should also test QStringList and QVariantList |
901 | } |
902 | |
903 | void tst_qquickvisualdatamodel::noDelegate_data() |
904 | { |
905 | QTest::addColumn<QUrl>(name: "source" ); |
906 | |
907 | QTest::newRow(dataTag: "item delegate" ) << testFileUrl(fileName: "datalist.qml" ); |
908 | QTest::newRow(dataTag: "package delegate" ) << testFileUrl(fileName: "datalist-package.qml" ); |
909 | } |
910 | |
911 | void tst_qquickvisualdatamodel::noDelegate() |
912 | { |
913 | QFETCH(QUrl, source); |
914 | |
915 | QQuickView view; |
916 | |
917 | QStandardItemModel model; |
918 | initStandardTreeModel(model: &model); |
919 | |
920 | view.rootContext()->setContextProperty("myModel" , &model); |
921 | |
922 | view.setSource(source); |
923 | |
924 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
925 | QVERIFY(listview != nullptr); |
926 | |
927 | QQmlDelegateModel *vdm = listview->findChild<QQmlDelegateModel*>(aName: "visualModel" ); |
928 | QVERIFY(vdm != nullptr); |
929 | QCOMPARE(vdm->count(), 3); |
930 | |
931 | vdm->setDelegate(nullptr); |
932 | QCOMPARE(vdm->count(), 0); |
933 | } |
934 | |
935 | void tst_qquickvisualdatamodel::itemsDestroyed_data() |
936 | { |
937 | QTest::addColumn<QUrl>(name: "source" ); |
938 | |
939 | QTest::newRow(dataTag: "listView" ) << testFileUrl(fileName: "itemsDestroyed_listView.qml" ); |
940 | QTest::newRow(dataTag: "package" ) << testFileUrl(fileName: "itemsDestroyed_package.qml" ); |
941 | QTest::newRow(dataTag: "pathView" ) << testFileUrl(fileName: "itemsDestroyed_pathView.qml" ); |
942 | QTest::newRow(dataTag: "repeater" ) << testFileUrl(fileName: "itemsDestroyed_repeater.qml" ); |
943 | } |
944 | |
945 | void tst_qquickvisualdatamodel::itemsDestroyed() |
946 | { |
947 | QFETCH(QUrl, source); |
948 | |
949 | QQmlGuard<QQuickItem> delegate; |
950 | |
951 | { |
952 | QQuickView view; |
953 | QStandardItemModel model; |
954 | initStandardTreeModel(model: &model); |
955 | view.rootContext()->setContextProperty("myModel" , &model); |
956 | view.setSource(source); |
957 | |
958 | view.show(); |
959 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
960 | |
961 | QVERIFY(delegate = findItem<QQuickItem>(view.contentItem(), "delegate" , 1)); |
962 | } |
963 | QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete); |
964 | QVERIFY(!delegate); |
965 | } |
966 | |
967 | void tst_qquickvisualdatamodel::packagesDestroyed() |
968 | { |
969 | QStringList list; |
970 | for (int i=0; i<30; i++) |
971 | list << (QLatin1String("item " ) + i); |
972 | SingleRoleModel model(list); |
973 | |
974 | QQuickView view; |
975 | view.rootContext()->setContextProperty("testModel" , &model); |
976 | |
977 | QString filename(testFile(fileName: "packageView.qml" )); |
978 | view.setSource(QUrl::fromLocalFile(localfile: filename)); |
979 | |
980 | qApp->processEvents(); |
981 | |
982 | QQuickListView *leftview = findItem<QQuickListView>(parent: view.rootObject(), objectName: "leftList" ); |
983 | QTRY_VERIFY(leftview != nullptr); |
984 | |
985 | QQuickListView *rightview = findItem<QQuickListView>(parent: view.rootObject(), objectName: "rightList" ); |
986 | QTRY_VERIFY(rightview != nullptr); |
987 | |
988 | QQuickItem *leftContent = leftview->contentItem(); |
989 | QTRY_VERIFY(leftContent != nullptr); |
990 | |
991 | QQuickItem *rightContent = rightview->contentItem(); |
992 | QTRY_VERIFY(rightContent != nullptr); |
993 | |
994 | leftview->forceLayout(); |
995 | rightview->forceLayout(); |
996 | QCOMPARE(leftview->currentIndex(), 0); |
997 | QCOMPARE(rightview->currentIndex(), 0); |
998 | |
999 | rightview->setCurrentIndex(20); |
1000 | QTRY_COMPARE(rightview->contentY(), 100.0); |
1001 | |
1002 | QQmlGuard<QQuickItem> left; |
1003 | QQmlGuard<QQuickItem> right; |
1004 | |
1005 | QVERIFY(findItem<QQuickItem>(leftContent, "wrapper" , 1)); |
1006 | QVERIFY(findItem<QQuickItem>(rightContent, "wrapper" , 1)); |
1007 | |
1008 | QVERIFY(left = findItem<QQuickItem>(leftContent, "wrapper" , 19)); |
1009 | QVERIFY(right = findItem<QQuickItem>(rightContent, "wrapper" , 19)); |
1010 | |
1011 | rightview->setCurrentIndex(0); |
1012 | QCOMPARE(rightview->currentIndex(), 0); |
1013 | |
1014 | QTRY_COMPARE(rightview->contentY(), 0.0); |
1015 | QCoreApplication::sendPostedEvents(); |
1016 | |
1017 | QVERIFY(!left); |
1018 | QVERIFY(!right); |
1019 | |
1020 | QVERIFY(left = findItem<QQuickItem>(leftContent, "wrapper" , 1)); |
1021 | QVERIFY(right = findItem<QQuickItem>(rightContent, "wrapper" , 1)); |
1022 | |
1023 | rightview->setCurrentIndex(20); |
1024 | QTRY_COMPARE(rightview->contentY(), 100.0); |
1025 | |
1026 | QVERIFY(left); |
1027 | QVERIFY(right); |
1028 | |
1029 | QVERIFY(findItem<QQuickItem>(leftContent, "wrapper" , 19)); |
1030 | QVERIFY(findItem<QQuickItem>(rightContent, "wrapper" , 19)); |
1031 | |
1032 | leftview->setCurrentIndex(20); |
1033 | QTRY_COMPARE(leftview->contentY(), 100.0); |
1034 | |
1035 | QVERIFY(!left); |
1036 | QVERIFY(!right); |
1037 | } |
1038 | |
1039 | void tst_qquickvisualdatamodel::qaimRowsMoved() |
1040 | { |
1041 | // Test parameters passed in QAIM::rowsMoved() signal are converted correctly |
1042 | // when translated to (from, to count) semantics. |
1043 | QFETCH(int, sourceFirst); |
1044 | QFETCH(int, sourceLast); |
1045 | QFETCH(int, destinationChild); |
1046 | QFETCH(int, expectFrom); |
1047 | QFETCH(int, expectTo); |
1048 | QFETCH(int, expectCount); |
1049 | |
1050 | QQmlEngine engine; |
1051 | QQmlComponent c(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
1052 | |
1053 | QStringList list; |
1054 | for (int i=0; i<30; i++) |
1055 | list << (QLatin1String("item " ) + i); |
1056 | SingleRoleModel model(list); |
1057 | engine.rootContext()->setContextProperty("myModel" , &model); |
1058 | |
1059 | QQmlDelegateModel *obj = qobject_cast<QQmlDelegateModel*>(object: c.create()); |
1060 | QVERIFY(obj != nullptr); |
1061 | |
1062 | QSignalSpy spy(obj, SIGNAL(modelUpdated(QQmlChangeSet,bool))); |
1063 | model.emitMove(sourceFirst, sourceLast, destinationChild); |
1064 | QCOMPARE(spy.count(), 1); |
1065 | |
1066 | QCOMPARE(spy[0].count(), 2); |
1067 | QQmlChangeSet changeSet = spy[0][0].value<QQmlChangeSet>(); |
1068 | QCOMPARE(changeSet.removes().count(), 1); |
1069 | QCOMPARE(changeSet.removes().at(0).index, expectFrom); |
1070 | QCOMPARE(changeSet.removes().at(0).count, expectCount); |
1071 | QCOMPARE(changeSet.inserts().count(), 1); |
1072 | QCOMPARE(changeSet.inserts().at(0).index, expectTo); |
1073 | QCOMPARE(changeSet.inserts().at(0).count, expectCount); |
1074 | QCOMPARE(changeSet.removes().at(0).moveId, changeSet.inserts().at(0).moveId); |
1075 | QCOMPARE(spy[0][1].toBool(), false); |
1076 | |
1077 | delete obj; |
1078 | } |
1079 | |
1080 | void tst_qquickvisualdatamodel::qaimRowsMoved_data() |
1081 | { |
1082 | QTest::addColumn<int>(name: "sourceFirst" ); |
1083 | QTest::addColumn<int>(name: "sourceLast" ); |
1084 | QTest::addColumn<int>(name: "destinationChild" ); |
1085 | QTest::addColumn<int>(name: "expectFrom" ); |
1086 | QTest::addColumn<int>(name: "expectTo" ); |
1087 | QTest::addColumn<int>(name: "expectCount" ); |
1088 | |
1089 | QTest::newRow(dataTag: "move 1 forward" ) |
1090 | << 1 << 1 << 6 |
1091 | << 1 << 5 << 1; |
1092 | |
1093 | QTest::newRow(dataTag: "move 1 backwards" ) |
1094 | << 4 << 4 << 1 |
1095 | << 4 << 1 << 1; |
1096 | |
1097 | QTest::newRow(dataTag: "move multiple forwards" ) |
1098 | << 0 << 2 << 13 |
1099 | << 0 << 10 << 3; |
1100 | |
1101 | QTest::newRow(dataTag: "move multiple forwards, with same to" ) |
1102 | << 0 << 1 << 3 |
1103 | << 0 << 1 << 2; |
1104 | |
1105 | QTest::newRow(dataTag: "move multiple backwards" ) |
1106 | << 10 << 14 << 1 |
1107 | << 10 << 1 << 5; |
1108 | } |
1109 | |
1110 | void tst_qquickvisualdatamodel::subtreeRowsMoved() |
1111 | { |
1112 | SingleRoleModel model(QStringList() << "one" << "two" << "three" << "four" ); |
1113 | model.insert(parent: model.index(row: 0, column: 0), index: 0, data: QStringList() << "a" << "b" << "c" << "d" << "e" ); |
1114 | model.insert(parent: model.index(row: 2, column: 0), index: 0, data: QStringList() << "A" << "B" << "C" ); |
1115 | |
1116 | QQmlEngine engine; |
1117 | engine.rootContext()->setContextProperty("myModel" , &model); |
1118 | |
1119 | QQmlComponent component(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
1120 | |
1121 | QScopedPointer<QObject> object(component.create()); |
1122 | QQmlDelegateModel *vdm = qobject_cast<QQmlDelegateModel*>(object: object.data()); |
1123 | QVERIFY(vdm); |
1124 | |
1125 | QSignalSpy spy(vdm, SIGNAL(modelUpdated(QQmlChangeSet,bool))); |
1126 | QQmlChangeSet changeSet; |
1127 | |
1128 | QCOMPARE(vdm->count(), 4); |
1129 | |
1130 | // Move items from the current root index to a sub tree. |
1131 | model.move(fromParent: QModelIndex(), from: 1, toParent: model.index(row: 0, column: 0), to: 3, count: 2); |
1132 | QCOMPARE(vdm->count(), 2); |
1133 | QCOMPARE(spy.count(), 1); |
1134 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1135 | QCOMPARE(changeSet.removes().count(), 1); |
1136 | QCOMPARE(changeSet.removes().at(0).index, 1); |
1137 | QCOMPARE(changeSet.removes().at(0).count, 2); |
1138 | QCOMPARE(changeSet.inserts().count(), 0); |
1139 | |
1140 | // Move items from a sub tree to the current root index. |
1141 | model.move(fromParent: model.index(row: 0, column: 0), from: 4, toParent: QModelIndex(), to: 2, count: 1); |
1142 | QCOMPARE(vdm->count(), 3); |
1143 | QCOMPARE(spy.count(), 2); |
1144 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1145 | QCOMPARE(changeSet.removes().count(), 0); |
1146 | QCOMPARE(changeSet.inserts().count(), 1); |
1147 | QCOMPARE(changeSet.inserts().at(0).index, 2); |
1148 | QCOMPARE(changeSet.inserts().at(0).count, 1); |
1149 | |
1150 | vdm->setRootIndex(QVariant::fromValue(value: model.index(row: 2, column: 0))); |
1151 | QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(2, 0)); |
1152 | QCOMPARE(vdm->count(), 3); |
1153 | QCOMPARE(spy.count(), 4); |
1154 | changeSet = spy.at(i: 2).at(i: 0).value<QQmlChangeSet>(); |
1155 | QCOMPARE(changeSet.removes().count(), 1); |
1156 | QCOMPARE(changeSet.removes().at(0).index, 0); |
1157 | QCOMPARE(changeSet.removes().at(0).count, 3); |
1158 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1159 | QCOMPARE(changeSet.inserts().count(), 1); |
1160 | QCOMPARE(changeSet.inserts().at(0).index, 0); |
1161 | QCOMPARE(changeSet.inserts().at(0).count, 3); |
1162 | |
1163 | // Move the current root index without changing its parent. |
1164 | model.move(fromParent: QModelIndex(), from: 2, toParent: QModelIndex(), to: 0, count: 1); |
1165 | QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(0, 0)); |
1166 | QCOMPARE(vdm->count(), 3); |
1167 | QCOMPARE(spy.count(), 4); |
1168 | |
1169 | // Move the current root index, changing its parent. |
1170 | model.move(fromParent: QModelIndex(), from: 0, toParent: model.index(row: 1, column: 0), to: 0, count: 1); |
1171 | QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(0, 0, model.index(0, 0))); |
1172 | QCOMPARE(vdm->count(), 3); |
1173 | QCOMPARE(spy.count(), 4); |
1174 | |
1175 | model.insert(parent: model.index(row: 0, column: 0), index: 0, data: QStringList() << "new1" << "new2" ); |
1176 | QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(2, 0, model.index(0, 0))); |
1177 | QCOMPARE(vdm->count(), 3); |
1178 | QCOMPARE(spy.count(), 4); |
1179 | |
1180 | model.remove(parent: model.index(row: 0, column: 0), index: 1, count: 1); |
1181 | QCOMPARE(vdm->rootIndex().value<QModelIndex>(), model.index(1, 0, model.index(0, 0))); |
1182 | QCOMPARE(vdm->count(), 3); |
1183 | QCOMPARE(spy.count(), 4); |
1184 | |
1185 | model.remove(parent: model.index(row: 0, column: 0), index: 1, count: 1); |
1186 | QCOMPARE(vdm->rootIndex().value<QModelIndex>(), QModelIndex()); |
1187 | QCOMPARE(vdm->count(), 0); |
1188 | QCOMPARE(spy.count(), 5); |
1189 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1190 | QCOMPARE(changeSet.removes().count(), 1); |
1191 | QCOMPARE(changeSet.removes().at(0).index, 0); |
1192 | QCOMPARE(changeSet.removes().at(0).count, 3); |
1193 | QCOMPARE(changeSet.inserts().count(), 0); |
1194 | |
1195 | vdm->setRootIndex(QVariant::fromValue(value: QModelIndex())); |
1196 | QCOMPARE(vdm->rootIndex().value<QModelIndex>(), QModelIndex()); |
1197 | QCOMPARE(vdm->count(), 2); |
1198 | QCOMPARE(spy.count(), 6); |
1199 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1200 | QCOMPARE(changeSet.removes().count(), 0); |
1201 | QCOMPARE(changeSet.inserts().count(), 1); |
1202 | QCOMPARE(changeSet.inserts().at(0).index, 0); |
1203 | QCOMPARE(changeSet.inserts().at(0).count, 2); |
1204 | } |
1205 | |
1206 | void tst_qquickvisualdatamodel::watchedRoles() |
1207 | { |
1208 | QaimModel model; |
1209 | for (int i = 0; i < 30; i++) |
1210 | model.addItem(name: "Item" + QString::number(i), number: "" ); |
1211 | |
1212 | QQmlEngine engine; |
1213 | engine.rootContext()->setContextProperty("myModel" , &model); |
1214 | |
1215 | QQmlComponent component(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
1216 | |
1217 | QScopedPointer<QObject> object(component.create()); |
1218 | QQmlDelegateModel *vdm = qobject_cast<QQmlDelegateModel*>(object: object.data()); |
1219 | QVERIFY(vdm); |
1220 | |
1221 | // DelegateModel doesn't initialize model data until the first item is requested. |
1222 | QQuickItem *item = qobject_cast<QQuickItem*>(object: vdm->object(index: 0)); |
1223 | QVERIFY(item); |
1224 | vdm->release(object: item); |
1225 | QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete); // Ensure released items are deleted before test exits. |
1226 | |
1227 | QSignalSpy spy(vdm, SIGNAL(modelUpdated(QQmlChangeSet,bool))); |
1228 | QQmlChangeSet changeSet; |
1229 | |
1230 | QCOMPARE(vdm->count(), 30); |
1231 | |
1232 | emit model.dataChanged(topLeft: model.index(row: 0), bottomRight: model.index(row: 4)); |
1233 | QCOMPARE(spy.count(), 0); |
1234 | |
1235 | emit model.dataChanged(topLeft: model.index(row: 0), bottomRight: model.index(row: 4), roles: QVector<int>() << QaimModel::Name); |
1236 | QCOMPARE(spy.count(), 0); |
1237 | |
1238 | emit model.dataChanged(topLeft: model.index(row: 0), bottomRight: model.index(row: 4), roles: QVector<int>() << QaimModel::Number); |
1239 | QCOMPARE(spy.count(), 0); |
1240 | |
1241 | vdm->setWatchedRoles(QList<QByteArray>() << "name" << "dummy" ); |
1242 | |
1243 | emit model.dataChanged(topLeft: model.index(row: 0), bottomRight: model.index(row: 4)); |
1244 | QCOMPARE(spy.count(), 1); |
1245 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1246 | QCOMPARE(changeSet.changes().at(0).index, 0); |
1247 | QCOMPARE(changeSet.changes().at(0).count, 5); |
1248 | |
1249 | emit model.dataChanged(topLeft: model.index(row: 1), bottomRight: model.index(row: 6), roles: QVector<int>() << QaimModel::Name); |
1250 | QCOMPARE(spy.count(), 2); |
1251 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1252 | QCOMPARE(changeSet.changes().at(0).index, 1); |
1253 | QCOMPARE(changeSet.changes().at(0).count, 6); |
1254 | |
1255 | emit model.dataChanged(topLeft: model.index(row: 8), bottomRight: model.index(row: 8), roles: QVector<int>() << QaimModel::Number); |
1256 | QCOMPARE(spy.count(), 2); |
1257 | |
1258 | vdm->setWatchedRoles(QList<QByteArray>() << "number" << "dummy" ); |
1259 | |
1260 | emit model.dataChanged(topLeft: model.index(row: 0), bottomRight: model.index(row: 4)); |
1261 | QCOMPARE(spy.count(), 3); |
1262 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1263 | QCOMPARE(changeSet.changes().at(0).index, 0); |
1264 | QCOMPARE(changeSet.changes().at(0).count, 5); |
1265 | |
1266 | emit model.dataChanged(topLeft: model.index(row: 1), bottomRight: model.index(row: 6), roles: QVector<int>() << QaimModel::Name); |
1267 | QCOMPARE(spy.count(), 3); |
1268 | |
1269 | emit model.dataChanged(topLeft: model.index(row: 8), bottomRight: model.index(row: 8), roles: QVector<int>() << QaimModel::Number); |
1270 | QCOMPARE(spy.count(), 4); |
1271 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1272 | QCOMPARE(changeSet.changes().at(0).index, 8); |
1273 | QCOMPARE(changeSet.changes().at(0).count, 1); |
1274 | |
1275 | vdm->setWatchedRoles(QList<QByteArray>() << "number" << "name" ); |
1276 | |
1277 | emit model.dataChanged(topLeft: model.index(row: 0), bottomRight: model.index(row: 4)); |
1278 | QCOMPARE(spy.count(), 5); |
1279 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1280 | QCOMPARE(changeSet.changes().at(0).index, 0); |
1281 | QCOMPARE(changeSet.changes().at(0).count, 5); |
1282 | |
1283 | emit model.dataChanged(topLeft: model.index(row: 1), bottomRight: model.index(row: 6), roles: QVector<int>() << QaimModel::Name); |
1284 | QCOMPARE(spy.count(), 6); |
1285 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1286 | QCOMPARE(changeSet.changes().at(0).index, 1); |
1287 | QCOMPARE(changeSet.changes().at(0).count, 6); |
1288 | |
1289 | emit model.dataChanged(topLeft: model.index(row: 8), bottomRight: model.index(row: 8), roles: QVector<int>() << QaimModel::Number); |
1290 | QCOMPARE(spy.count(), 7); |
1291 | changeSet = spy.last().at(i: 0).value<QQmlChangeSet>(); |
1292 | QCOMPARE(changeSet.changes().at(0).index, 8); |
1293 | QCOMPARE(changeSet.changes().at(0).count, 1); |
1294 | } |
1295 | |
1296 | void tst_qquickvisualdatamodel::hasModelChildren() |
1297 | { |
1298 | SingleRoleModel model(QStringList() << "one" << "two" << "three" << "four" ); |
1299 | model.insert(parent: model.index(row: 0, column: 0), index: 0, data: QStringList() << "a" << "b" << "c" << "d" << "e" ); |
1300 | model.insert(parent: model.index(row: 2, column: 0), index: 0, data: QStringList() << "A" << "B" << "C" ); |
1301 | |
1302 | QQmlEngine engine; |
1303 | engine.rootContext()->setContextProperty("myModel" , &model); |
1304 | |
1305 | QQmlComponent component(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
1306 | |
1307 | QScopedPointer<QObject> object(component.create()); |
1308 | QQmlDelegateModel *vdm = qobject_cast<QQmlDelegateModel*>(object: object.data()); |
1309 | QVERIFY(vdm); |
1310 | |
1311 | QCOMPARE(vdm->count(), 4); |
1312 | |
1313 | QQuickItem *item = nullptr; |
1314 | |
1315 | item = qobject_cast<QQuickItem*>(object: vdm->object(index: 0)); |
1316 | QVERIFY(item); |
1317 | QCOMPARE(item->property("modelChildren" ).toBool(), true); |
1318 | vdm->release(object: item); |
1319 | |
1320 | item = qobject_cast<QQuickItem*>(object: vdm->object(index: 1)); |
1321 | QVERIFY(item); |
1322 | QCOMPARE(item->property("modelChildren" ).toBool(), false); |
1323 | vdm->release(object: item); |
1324 | |
1325 | item = qobject_cast<QQuickItem*>(object: vdm->object(index: 2)); |
1326 | QVERIFY(item); |
1327 | QCOMPARE(item->property("modelChildren" ).toBool(), true); |
1328 | vdm->release(object: item); |
1329 | |
1330 | item = qobject_cast<QQuickItem*>(object: vdm->object(index: 3)); |
1331 | QVERIFY(item); |
1332 | QCOMPARE(item->property("modelChildren" ).toBool(), false); |
1333 | vdm->release(object: item); |
1334 | QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete); // Ensure released items are deleted before test exits. |
1335 | |
1336 | QCOMPARE(vdm->stringValue(0, QLatin1String("hasModelChildren" )), QVariant(true).toString()); |
1337 | QCOMPARE(vdm->stringValue(1, QLatin1String("hasModelChildren" )), QVariant(false).toString()); |
1338 | QCOMPARE(vdm->stringValue(2, QLatin1String("hasModelChildren" )), QVariant(true).toString()); |
1339 | QCOMPARE(vdm->stringValue(3, QLatin1String("hasModelChildren" )), QVariant(false).toString()); |
1340 | |
1341 | QCOMPARE(evaluate<bool>(vdm, "items.get(0).model.hasModelChildren" ), true); |
1342 | QCOMPARE(evaluate<bool>(vdm, "items.get(1).model.hasModelChildren" ), false); |
1343 | QCOMPARE(evaluate<bool>(vdm, "items.get(2).model.hasModelChildren" ), true); |
1344 | QCOMPARE(evaluate<bool>(vdm, "items.get(3).model.hasModelChildren" ), false); |
1345 | } |
1346 | |
1347 | void tst_qquickvisualdatamodel::setValue() |
1348 | { |
1349 | QStandardItemModel model; |
1350 | initStandardTreeModel(model: &model); |
1351 | |
1352 | QQmlEngine engine; |
1353 | engine.rootContext()->setContextProperty("myModel" , &model); |
1354 | |
1355 | QQmlComponent component(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
1356 | |
1357 | QScopedPointer<QObject> object(component.create()); |
1358 | QQmlDelegateModel *vdm = qobject_cast<QQmlDelegateModel*>(object: object.data()); |
1359 | QVERIFY(vdm); |
1360 | |
1361 | QCOMPARE(vdm->count(), 3); |
1362 | |
1363 | QQuickItem *item = nullptr; |
1364 | |
1365 | item = qobject_cast<QQuickItem*>(object: vdm->object(index: 0)); |
1366 | QVERIFY(item); |
1367 | QCOMPARE(evaluate<QString>(item, "display" ), QString("Row 1 Item" )); |
1368 | evaluate<void>(scope: item, expression: "display = 'Changed Item 1'" ); |
1369 | QCOMPARE(evaluate<QString>(item, "display" ), QString("Changed Item 1" )); |
1370 | QCOMPARE(model.item(0)->text(), QString("Changed Item 1" )); |
1371 | |
1372 | vdm->release(object: item); |
1373 | |
1374 | QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete); // Ensure released items are deleted before test exits. |
1375 | } |
1376 | |
1377 | void tst_qquickvisualdatamodel::remove_data() |
1378 | { |
1379 | QTest::addColumn<QUrl>(name: "source" ); |
1380 | QTest::addColumn<QString>(name: "package delegate" ); |
1381 | |
1382 | QTest::newRow(dataTag: "item delegate" ) |
1383 | << testFileUrl(fileName: "groups.qml" ) |
1384 | << QString(); |
1385 | QTest::newRow(dataTag: "package" ) |
1386 | << testFileUrl(fileName: "groups-package.qml" ) |
1387 | << QString("package." ); |
1388 | } |
1389 | |
1390 | void tst_qquickvisualdatamodel::remove() |
1391 | { |
1392 | QQuickView view; |
1393 | |
1394 | SingleRoleModel model(QStringList() |
1395 | << "one" |
1396 | << "two" |
1397 | << "three" |
1398 | << "four" |
1399 | << "five" |
1400 | << "six" |
1401 | << "seven" |
1402 | << "eight" |
1403 | << "nine" |
1404 | << "ten" |
1405 | << "eleven" |
1406 | << "twelve" ); |
1407 | |
1408 | QQmlContext *ctxt = view.rootContext(); |
1409 | ctxt->setContextProperty("myModel" , &model); |
1410 | |
1411 | view.setSource(testFileUrl(fileName: "groups.qml" )); |
1412 | |
1413 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
1414 | QVERIFY(listview != nullptr); |
1415 | |
1416 | QQuickItem *contentItem = listview->contentItem(); |
1417 | QVERIFY(contentItem != nullptr); |
1418 | |
1419 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(object: qvariant_cast<QObject *>(v: listview->model())); |
1420 | QVERIFY(visualModel); |
1421 | |
1422 | { |
1423 | QCOMPARE(listview->count(), 12); |
1424 | QCOMPARE(visualModel->items()->count(), 12); |
1425 | static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1426 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1427 | |
1428 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1429 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1430 | QVERIFY(delegate); |
1431 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1432 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1433 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1434 | } |
1435 | } { |
1436 | evaluate<void>(scope: visualModel, expression: "items.remove(2)" ); |
1437 | QCOMPARE(listview->count(), 11); |
1438 | QCOMPARE(visualModel->items()->count(), 11); |
1439 | static const int mIndex[] = { 0, 1, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1440 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10 }; |
1441 | |
1442 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1443 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1444 | QVERIFY(delegate); |
1445 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1446 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1447 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1448 | } |
1449 | } { |
1450 | evaluate<void>(scope: visualModel, expression: "items.remove(1, 4)" ); |
1451 | QCOMPARE(listview->count(), 7); |
1452 | QCOMPARE(visualModel->items()->count(), 7); |
1453 | static const int mIndex[] = { 0, 6, 7, 8, 9,10,11 }; |
1454 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6 }; |
1455 | |
1456 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1457 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1458 | QVERIFY(delegate); |
1459 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1460 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1461 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1462 | } |
1463 | } { |
1464 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*remove: index out of range" )); |
1465 | evaluate<void>(scope: visualModel, expression: "items.remove(-8, 4)" ); |
1466 | QCOMPARE(listview->count(), 7); |
1467 | QCOMPARE(visualModel->items()->count(), 7); |
1468 | } { |
1469 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*remove: index out of range" )); |
1470 | evaluate<void>(scope: visualModel, expression: "items.remove(12, 2)" ); |
1471 | QCOMPARE(listview->count(), 7); |
1472 | QCOMPARE(visualModel->items()->count(), 7); |
1473 | } { |
1474 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*remove: invalid count" )); |
1475 | evaluate<void>(scope: visualModel, expression: "items.remove(5, 3)" ); |
1476 | QCOMPARE(listview->count(), 7); |
1477 | QCOMPARE(visualModel->items()->count(), 7); |
1478 | } { |
1479 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*remove: invalid count" )); |
1480 | evaluate<void>(scope: visualModel, expression: "items.remove(5, -2)" ); |
1481 | QCOMPARE(listview->count(), 7); |
1482 | QCOMPARE(visualModel->items()->count(), 7); |
1483 | } |
1484 | } |
1485 | |
1486 | void tst_qquickvisualdatamodel::move_data() |
1487 | { |
1488 | QTest::addColumn<QUrl>(name: "source" ); |
1489 | QTest::addColumn<QString>(name: "package delegate" ); |
1490 | |
1491 | QTest::newRow(dataTag: "item delegate" ) |
1492 | << testFileUrl(fileName: "groups.qml" ) |
1493 | << QString(); |
1494 | QTest::newRow(dataTag: "package" ) |
1495 | << testFileUrl(fileName: "groups-package.qml" ) |
1496 | << QString("package." ); |
1497 | } |
1498 | |
1499 | void tst_qquickvisualdatamodel::move() |
1500 | { |
1501 | QQuickView view; |
1502 | |
1503 | SingleRoleModel model(QStringList() |
1504 | << "one" |
1505 | << "two" |
1506 | << "three" |
1507 | << "four" |
1508 | << "five" |
1509 | << "six" |
1510 | << "seven" |
1511 | << "eight" |
1512 | << "nine" |
1513 | << "ten" |
1514 | << "eleven" |
1515 | << "twelve" ); |
1516 | |
1517 | QQmlContext *ctxt = view.rootContext(); |
1518 | ctxt->setContextProperty("myModel" , &model); |
1519 | |
1520 | view.setSource(testFileUrl(fileName: "groups.qml" )); |
1521 | |
1522 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
1523 | QVERIFY(listview != nullptr); |
1524 | |
1525 | QQuickItem *contentItem = listview->contentItem(); |
1526 | QVERIFY(contentItem != nullptr); |
1527 | |
1528 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(object: qvariant_cast<QObject *>(v: listview->model())); |
1529 | QVERIFY(visualModel); |
1530 | |
1531 | { |
1532 | QCOMPARE(listview->count(), 12); |
1533 | QCOMPARE(visualModel->items()->count(), 12); |
1534 | static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1535 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1536 | |
1537 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1538 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1539 | QVERIFY(delegate); |
1540 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1541 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1542 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1543 | } |
1544 | } { |
1545 | evaluate<void>(scope: visualModel, expression: "items.move(2, 4)" ); |
1546 | QCOMPARE(listview->count(), 12); |
1547 | QCOMPARE(visualModel->items()->count(), 12); |
1548 | static const int mIndex[] = { 0, 1, 3, 4, 2, 5, 6, 7, 8, 9,10,11 }; |
1549 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1550 | |
1551 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1552 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1553 | QVERIFY(delegate); |
1554 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1555 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1556 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1557 | } |
1558 | } { |
1559 | evaluate<void>(scope: visualModel, expression: "items.move(4, 2)" ); |
1560 | QCOMPARE(listview->count(), 12); |
1561 | QCOMPARE(visualModel->items()->count(), 12); |
1562 | static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1563 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1564 | |
1565 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1566 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1567 | QVERIFY(delegate); |
1568 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1569 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1570 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1571 | } |
1572 | } { |
1573 | evaluate<void>(scope: visualModel, expression: "items.move(8, 0, 4)" ); |
1574 | QCOMPARE(listview->count(), 12); |
1575 | QCOMPARE(visualModel->items()->count(), 12); |
1576 | static const int mIndex[] = { 8, 9,10,11, 0, 1, 2, 3, 4, 5, 6, 7 }; |
1577 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1578 | |
1579 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1580 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1581 | QVERIFY(delegate); |
1582 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1583 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1584 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1585 | } |
1586 | } { |
1587 | evaluate<void>(scope: visualModel, expression: "items.move(3, 4, 5)" ); |
1588 | QCOMPARE(listview->count(), 12); |
1589 | QCOMPARE(visualModel->items()->count(), 12); |
1590 | static const int mIndex[] = { 8, 9,10,4, 11, 0, 1, 2, 3, 5, 6, 7 }; |
1591 | static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1592 | |
1593 | for (int i = 0; i < lengthOf(mIndex); ++i) { |
1594 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: mIndex[i]); |
1595 | QVERIFY(delegate); |
1596 | QCOMPARE(delegate->property("test1" ).toString(), model.at(mIndex[i])); |
1597 | QCOMPARE(delegate->property("test2" ).toInt(), mIndex[i]); |
1598 | QCOMPARE(delegate->property("test3" ).toInt(), iIndex[i]); |
1599 | } |
1600 | } { |
1601 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*move: invalid count" )); |
1602 | evaluate<void>(scope: visualModel, expression: "items.move(5, 2, -2)" ); |
1603 | QCOMPARE(listview->count(), 12); |
1604 | QCOMPARE(visualModel->items()->count(), 12); |
1605 | } { |
1606 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*move: from index out of range" )); |
1607 | evaluate<void>(scope: visualModel, expression: "items.move(-6, 2, 1)" ); |
1608 | QCOMPARE(listview->count(), 12); |
1609 | QCOMPARE(visualModel->items()->count(), 12); |
1610 | } { |
1611 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*move: from index out of range" )); |
1612 | evaluate<void>(scope: visualModel, expression: "items.move(15, 2, 1)" ); |
1613 | QCOMPARE(listview->count(), 12); |
1614 | QCOMPARE(visualModel->items()->count(), 12); |
1615 | } { |
1616 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*move: from index out of range" )); |
1617 | evaluate<void>(scope: visualModel, expression: "items.move(11, 1, 3)" ); |
1618 | QCOMPARE(listview->count(), 12); |
1619 | QCOMPARE(visualModel->items()->count(), 12); |
1620 | } { |
1621 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*move: to index out of range" )); |
1622 | evaluate<void>(scope: visualModel, expression: "items.move(2, -5, 1)" ); |
1623 | QCOMPARE(listview->count(), 12); |
1624 | QCOMPARE(visualModel->items()->count(), 12); |
1625 | } { |
1626 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*move: to index out of range" )); |
1627 | evaluate<void>(scope: visualModel, expression: "items.move(2, 14, 1)" ); |
1628 | QCOMPARE(listview->count(), 12); |
1629 | QCOMPARE(visualModel->items()->count(), 12); |
1630 | } { |
1631 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*move: to index out of range" )); |
1632 | evaluate<void>(scope: visualModel, expression: "items.move(2, 11, 4)" ); |
1633 | QCOMPARE(listview->count(), 12); |
1634 | QCOMPARE(visualModel->items()->count(), 12); |
1635 | } |
1636 | } |
1637 | |
1638 | void tst_qquickvisualdatamodel::groups_data() |
1639 | { |
1640 | QTest::addColumn<QUrl>(name: "source" ); |
1641 | QTest::addColumn<QString>(name: "part" ); |
1642 | |
1643 | QTest::newRow(dataTag: "item delegate" ) |
1644 | << testFileUrl(fileName: "groups.qml" ) |
1645 | << QString(); |
1646 | QTest::newRow(dataTag: "package" ) |
1647 | << testFileUrl(fileName: "groups-package.qml" ) |
1648 | << QString("visualModel.parts.package." ); |
1649 | } |
1650 | |
1651 | template <int N> void tst_qquickvisualdatamodel::groups_verify( |
1652 | const SingleRoleModel &model, |
1653 | QQuickItem *contentItem, |
1654 | const int (&mIndex)[N], |
1655 | const int (&iIndex)[N], |
1656 | const int (&vIndex)[N], |
1657 | const int (&sIndex)[N], |
1658 | const bool (&vMember)[N], |
1659 | const bool (&sMember)[N]) |
1660 | { |
1661 | failed = true; |
1662 | for (int i = 0; i < N; ++i) { |
1663 | QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate" , mIndex[i]); |
1664 | QVERIFY(delegate); |
1665 | QCOMPARE(evaluate<QString>(delegate, "test1" ), model.at(mIndex[i])); |
1666 | QCOMPARE(evaluate<int>(delegate, "test2" ) , mIndex[i]); |
1667 | QCOMPARE(evaluate<int>(delegate, "test3" ) , iIndex[i]); |
1668 | QCOMPARE(evaluate<bool>(delegate, "test4" ), true); |
1669 | QCOMPARE(evaluate<int>(delegate, "test5" ) , vIndex[i]); |
1670 | QCOMPARE(evaluate<bool>(delegate, "test6" ), vMember[i]); |
1671 | QCOMPARE(evaluate<int>(delegate, "test7" ) , sIndex[i]); |
1672 | QCOMPARE(evaluate<bool>(delegate, "test8" ), sMember[i]); |
1673 | QCOMPARE(evaluate<QStringList>(delegate, "test9" ).contains("items" ) , bool(true)); |
1674 | QCOMPARE(evaluate<QStringList>(delegate, "test9" ).contains("visible" ) , bool(vMember[i])); |
1675 | QCOMPARE(evaluate<QStringList>(delegate, "test9" ).contains("selected" ), bool(sMember[i])); |
1676 | } |
1677 | failed = false; |
1678 | } |
1679 | |
1680 | #define VERIFY_GROUPS \ |
1681 | groups_verify(model, contentItem, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \ |
1682 | QVERIFY(!failed) |
1683 | |
1684 | |
1685 | void tst_qquickvisualdatamodel::groups() |
1686 | { |
1687 | QFETCH(QUrl, source); |
1688 | QFETCH(QString, part); |
1689 | |
1690 | QQuickView view; |
1691 | |
1692 | SingleRoleModel model(QStringList() |
1693 | << "one" |
1694 | << "two" |
1695 | << "three" |
1696 | << "four" |
1697 | << "five" |
1698 | << "six" |
1699 | << "seven" |
1700 | << "eight" |
1701 | << "nine" |
1702 | << "ten" |
1703 | << "eleven" |
1704 | << "twelve" ); |
1705 | |
1706 | QQmlContext *ctxt = view.rootContext(); |
1707 | ctxt->setContextProperty("myModel" , &model); |
1708 | |
1709 | view.setSource(source); |
1710 | |
1711 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
1712 | QVERIFY(listview != nullptr); |
1713 | |
1714 | QQuickItem *contentItem = listview->contentItem(); |
1715 | QVERIFY(contentItem != nullptr); |
1716 | |
1717 | QQmlDelegateModel *visualModel = listview->findChild<QQmlDelegateModel *>(aName: "visualModel" ); |
1718 | QVERIFY(visualModel); |
1719 | |
1720 | QQmlDelegateModelGroup *visibleItems = listview->findChild<QQmlDelegateModelGroup *>(aName: "visibleItems" ); |
1721 | QVERIFY(visibleItems); |
1722 | |
1723 | QQmlDelegateModelGroup *selectedItems = listview->findChild<QQmlDelegateModelGroup *>(aName: "selectedItems" ); |
1724 | QVERIFY(selectedItems); |
1725 | |
1726 | const bool f = false; |
1727 | const bool t = true; |
1728 | |
1729 | { |
1730 | QCOMPARE(listview->count(), 12); |
1731 | QCOMPARE(visualModel->items()->count(), 12); |
1732 | QCOMPARE(visibleItems->count(), 12); |
1733 | QCOMPARE(selectedItems->count(), 0); |
1734 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1735 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1736 | static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1737 | static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t }; |
1738 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
1739 | static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f }; |
1740 | VERIFY_GROUPS; |
1741 | } { |
1742 | evaluate<void>(scope: visualModel, expression: "items.addGroups(8, \"selected\")" ); |
1743 | QCOMPARE(listview->count(), 12); |
1744 | QCOMPARE(visualModel->items()->count(), 12); |
1745 | QCOMPARE(visibleItems->count(), 12); |
1746 | QCOMPARE(selectedItems->count(), 1); |
1747 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1748 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1749 | static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1750 | static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t }; |
1751 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 }; |
1752 | static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f }; |
1753 | VERIFY_GROUPS; |
1754 | } { |
1755 | evaluate<void>(scope: visualModel, expression: "items.addGroups(6, 4, [\"visible\", \"selected\"])" ); |
1756 | QCOMPARE(listview->count(), 12); |
1757 | QCOMPARE(visualModel->items()->count(), 12); |
1758 | QCOMPARE(visibleItems->count(), 12); |
1759 | QCOMPARE(selectedItems->count(), 4); |
1760 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1761 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1762 | static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1763 | static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t }; |
1764 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 }; |
1765 | static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f }; |
1766 | VERIFY_GROUPS; |
1767 | } { |
1768 | evaluate<void>(scope: visualModel, expression: "items.setGroups(2, [\"items\", \"selected\"])" ); |
1769 | QCOMPARE(listview->count(), 12); |
1770 | QCOMPARE(visualModel->items()->count(), 12); |
1771 | QCOMPARE(visibleItems->count(), 11); |
1772 | QCOMPARE(selectedItems->count(), 5); |
1773 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1774 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1775 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 }; |
1776 | static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t }; |
1777 | static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 }; |
1778 | static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f }; |
1779 | VERIFY_GROUPS; |
1780 | } { |
1781 | evaluate<void>(scope: selectedItems, expression: "setGroups(0, 3, \"items\")" ); |
1782 | QCOMPARE(listview->count(), 12); |
1783 | QCOMPARE(visualModel->items()->count(), 12); |
1784 | QCOMPARE(visibleItems->count(), 9); |
1785 | QCOMPARE(selectedItems->count(), 2); |
1786 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1787 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1788 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 }; |
1789 | static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t }; |
1790 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 }; |
1791 | static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f }; |
1792 | VERIFY_GROUPS; |
1793 | } { |
1794 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*addGroups: invalid count" )); |
1795 | evaluate<void>(scope: visualModel, expression: "items.addGroups(11, -4, \"items\")" ); |
1796 | QCOMPARE(listview->count(), 12); |
1797 | QCOMPARE(visualModel->items()->count(), 12); |
1798 | QCOMPARE(visibleItems->count(), 9); |
1799 | QCOMPARE(selectedItems->count(), 2); |
1800 | } { |
1801 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*addGroups: index out of range" )); |
1802 | evaluate<void>(scope: visualModel, expression: "items.addGroups(-1, 3, \"items\")" ); |
1803 | QCOMPARE(listview->count(), 12); |
1804 | QCOMPARE(visualModel->items()->count(), 12); |
1805 | QCOMPARE(visibleItems->count(), 9); |
1806 | QCOMPARE(selectedItems->count(), 2); |
1807 | } { |
1808 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*addGroups: index out of range" )); |
1809 | evaluate<void>(scope: visualModel, expression: "items.addGroups(14, 3, \"items\")" ); |
1810 | QCOMPARE(listview->count(), 12); |
1811 | QCOMPARE(visualModel->items()->count(), 12); |
1812 | QCOMPARE(visibleItems->count(), 9); |
1813 | QCOMPARE(selectedItems->count(), 2); |
1814 | } { |
1815 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*addGroups: invalid count" )); |
1816 | evaluate<void>(scope: visualModel, expression: "items.addGroups(11, 5, \"items\")" ); |
1817 | QCOMPARE(listview->count(), 12); |
1818 | QCOMPARE(visualModel->items()->count(), 12); |
1819 | QCOMPARE(visibleItems->count(), 9); |
1820 | QCOMPARE(selectedItems->count(), 2); |
1821 | } { |
1822 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*setGroups: invalid count" )); |
1823 | evaluate<void>(scope: visualModel, expression: "items.setGroups(11, -4, \"items\")" ); |
1824 | QCOMPARE(listview->count(), 12); |
1825 | QCOMPARE(visualModel->items()->count(), 12); |
1826 | QCOMPARE(visibleItems->count(), 9); |
1827 | QCOMPARE(selectedItems->count(), 2); |
1828 | } { |
1829 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*setGroups: index out of range" )); |
1830 | evaluate<void>(scope: visualModel, expression: "items.setGroups(-1, 3, \"items\")" ); |
1831 | QCOMPARE(listview->count(), 12); |
1832 | QCOMPARE(visualModel->items()->count(), 12); |
1833 | QCOMPARE(visibleItems->count(), 9); |
1834 | QCOMPARE(selectedItems->count(), 2); |
1835 | } { |
1836 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*setGroups: index out of range" )); |
1837 | evaluate<void>(scope: visualModel, expression: "items.setGroups(14, 3, \"items\")" ); |
1838 | QCOMPARE(listview->count(), 12); |
1839 | QCOMPARE(visualModel->items()->count(), 12); |
1840 | QCOMPARE(visibleItems->count(), 9); |
1841 | QCOMPARE(selectedItems->count(), 2); |
1842 | } { |
1843 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*setGroups: invalid count" )); |
1844 | evaluate<void>(scope: visualModel, expression: "items.setGroups(11, 5, \"items\")" ); |
1845 | QCOMPARE(listview->count(), 12); |
1846 | QCOMPARE(visualModel->items()->count(), 12); |
1847 | QCOMPARE(visibleItems->count(), 9); |
1848 | QCOMPARE(selectedItems->count(), 2); |
1849 | } { |
1850 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*removeGroups: invalid count" )); |
1851 | evaluate<void>(scope: visualModel, expression: "items.removeGroups(11, -4, \"items\")" ); |
1852 | QCOMPARE(listview->count(), 12); |
1853 | QCOMPARE(visualModel->items()->count(), 12); |
1854 | } { |
1855 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*removeGroups: index out of range" )); |
1856 | evaluate<void>(scope: visualModel, expression: "items.removeGroups(-1, 3, \"items\")" ); |
1857 | QCOMPARE(listview->count(), 12); |
1858 | QCOMPARE(visualModel->items()->count(), 12); |
1859 | QCOMPARE(visibleItems->count(), 9); |
1860 | QCOMPARE(selectedItems->count(), 2); |
1861 | } { |
1862 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*removeGroups: index out of range" )); |
1863 | evaluate<void>(scope: visualModel, expression: "items.removeGroups(14, 3, \"items\")" ); |
1864 | QCOMPARE(listview->count(), 12); |
1865 | QCOMPARE(visualModel->items()->count(), 12); |
1866 | QCOMPARE(visibleItems->count(), 9); |
1867 | QCOMPARE(selectedItems->count(), 2); |
1868 | } { |
1869 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*removeGroups: invalid count" )); |
1870 | evaluate<void>(scope: visualModel, expression: "items.removeGroups(11, 5, \"items\")" ); |
1871 | QCOMPARE(listview->count(), 12); |
1872 | QCOMPARE(visualModel->items()->count(), 12); |
1873 | QCOMPARE(visibleItems->count(), 9); |
1874 | QCOMPARE(selectedItems->count(), 2); |
1875 | } { |
1876 | evaluate<void>(scope: visualModel, expression: part + "filterOnGroup = \"visible\"" ); |
1877 | QCOMPARE(listview->count(), 9); |
1878 | QCOMPARE(visualModel->items()->count(), 12); |
1879 | QCOMPARE(visibleItems->count(), 9); |
1880 | QCOMPARE(selectedItems->count(), 2); |
1881 | QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup" ), QString("visible" )); |
1882 | } { |
1883 | evaluate<void>(scope: visualModel, expression: part + "filterOnGroup = \"selected\"" ); |
1884 | QCOMPARE(listview->count(), 2); |
1885 | QCOMPARE(visualModel->items()->count(), 12); |
1886 | QCOMPARE(visibleItems->count(), 9); |
1887 | QCOMPARE(selectedItems->count(), 2); |
1888 | QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup" ), QString("selected" )); |
1889 | } { |
1890 | evaluate<void>(scope: visualModel, expression: part + "filterOnGroup = undefined" ); |
1891 | QCOMPARE(listview->count(), 12); |
1892 | QCOMPARE(visualModel->items()->count(), 12); |
1893 | QCOMPARE(visibleItems->count(), 9); |
1894 | QCOMPARE(selectedItems->count(), 2); |
1895 | QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup" ), QString("items" )); |
1896 | } { |
1897 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: 5); |
1898 | QVERIFY(delegate); |
1899 | |
1900 | evaluate<void>(scope: delegate, expression: "hide()" ); |
1901 | QCOMPARE(listview->count(), 12); |
1902 | QCOMPARE(visualModel->items()->count(), 12); |
1903 | QCOMPARE(visibleItems->count(), 8); |
1904 | QCOMPARE(selectedItems->count(), 2); |
1905 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1906 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1907 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 }; |
1908 | static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t }; |
1909 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 }; |
1910 | static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f }; |
1911 | VERIFY_GROUPS; |
1912 | } { |
1913 | QQuickItem *delegate = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: 5); |
1914 | QVERIFY(delegate); |
1915 | |
1916 | evaluate<void>(scope: delegate, expression: "select()" ); |
1917 | QCOMPARE(listview->count(), 12); |
1918 | QCOMPARE(visualModel->items()->count(), 12); |
1919 | QCOMPARE(visibleItems->count(), 8); |
1920 | QCOMPARE(selectedItems->count(), 3); |
1921 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1922 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1923 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 }; |
1924 | static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t }; |
1925 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 }; |
1926 | static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f }; |
1927 | VERIFY_GROUPS; |
1928 | } { |
1929 | evaluate<void>(scope: visualModel, expression: "items.move(2, 6, 3)" ); |
1930 | QCOMPARE(listview->count(), 12); |
1931 | QCOMPARE(visualModel->items()->count(), 12); |
1932 | QCOMPARE(visibleItems->count(), 8); |
1933 | QCOMPARE(selectedItems->count(), 3); |
1934 | static const int mIndex [] = { 0, 1, 5, 6, 7, 8, 2, 3, 4, 9,10,11 }; |
1935 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
1936 | static const int vIndex [] = { 0, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 7 }; |
1937 | static const bool vMember[] = { t, t, f, f, f, t, f, t, t, t, t, t }; |
1938 | static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3 }; |
1939 | static const bool sMember[] = { f, f, t, f, f, t, f, f, f, t, f, f }; |
1940 | VERIFY_GROUPS; |
1941 | } |
1942 | } |
1943 | |
1944 | template <int N> void tst_qquickvisualdatamodel::get_verify( |
1945 | const SingleRoleModel &model, |
1946 | QQmlDelegateModel *visualModel, |
1947 | QQmlDelegateModelGroup *visibleItems, |
1948 | QQmlDelegateModelGroup *selectedItems, |
1949 | const int (&mIndex)[N], |
1950 | const int (&iIndex)[N], |
1951 | const int (&vIndex)[N], |
1952 | const int (&sIndex)[N], |
1953 | const bool (&vMember)[N], |
1954 | const bool (&sMember)[N]) |
1955 | { |
1956 | failed = true; |
1957 | for (int i = 0; i < N; ++i) { |
1958 | QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.name" ).arg(i)), model.at(mIndex[i])); |
1959 | QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.modelData" ).arg(i)), model.at(mIndex[i])); |
1960 | QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).model.index" ).arg(i)), mIndex[i]); |
1961 | QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).itemsIndex" ).arg(i)), iIndex[i]); |
1962 | QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inItems" ).arg(i)), true); |
1963 | QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).visibleIndex" ).arg(i)), vIndex[i]); |
1964 | QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inVisible" ).arg(i)), vMember[i]); |
1965 | QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).selectedIndex" ).arg(i)), sIndex[i]); |
1966 | QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inSelected" ).arg(i)), sMember[i]); |
1967 | QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"items\")" ).arg(i)), true); |
1968 | QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"visible\")" ).arg(i)), vMember[i]); |
1969 | QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"selected\")" ).arg(i)), sMember[i]); |
1970 | |
1971 | if (vMember[i]) { |
1972 | QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.name" ).arg(vIndex[i])), model.at(mIndex[i])); |
1973 | QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.modelData" ).arg(vIndex[i])), model.at(mIndex[i])); |
1974 | QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).model.index" ).arg(vIndex[i])), mIndex[i]); |
1975 | QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).itemsIndex" ).arg(vIndex[i])), iIndex[i]); |
1976 | QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inItems" ).arg(vIndex[i])), true); |
1977 | QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).visibleIndex" ).arg(vIndex[i])), vIndex[i]); |
1978 | QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inVisible" ).arg(vIndex[i])), vMember[i]); |
1979 | QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).selectedIndex" ).arg(vIndex[i])), sIndex[i]); |
1980 | QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inSelected" ).arg(vIndex[i])), sMember[i]); |
1981 | |
1982 | QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"items\")" ).arg(vIndex[i])), true); |
1983 | QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"visible\")" ).arg(vIndex[i])), vMember[i]); |
1984 | QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"selected\")" ).arg(vIndex[i])), sMember[i]); |
1985 | } |
1986 | if (sMember[i]) { |
1987 | QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.name" ).arg(sIndex[i])), model.at(mIndex[i])); |
1988 | QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.modelData" ).arg(sIndex[i])), model.at(mIndex[i])); |
1989 | QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).model.index" ).arg(sIndex[i])), mIndex[i]); |
1990 | QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).itemsIndex" ).arg(sIndex[i])), iIndex[i]); |
1991 | QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inItems" ).arg(sIndex[i])), true); |
1992 | QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).visibleIndex" ).arg(sIndex[i])), vIndex[i]); |
1993 | QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inVisible" ).arg(sIndex[i])), vMember[i]); |
1994 | QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).selectedIndex" ).arg(sIndex[i])), sIndex[i]); |
1995 | QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inSelected" ).arg(sIndex[i])), sMember[i]); |
1996 | QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"items\")" ).arg(sIndex[i])), true); |
1997 | QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"visible\")" ).arg(sIndex[i])), vMember[i]); |
1998 | QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"selected\")" ).arg(sIndex[i])), sMember[i]); |
1999 | } |
2000 | } |
2001 | failed = false; |
2002 | } |
2003 | |
2004 | #define VERIFY_GET \ |
2005 | get_verify(model, visualModel, visibleItems, selectedItems, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \ |
2006 | QVERIFY(!failed) |
2007 | |
2008 | void tst_qquickvisualdatamodel::get() |
2009 | { |
2010 | QQuickView view; |
2011 | |
2012 | SingleRoleModel model(QStringList() |
2013 | << "one" |
2014 | << "two" |
2015 | << "three" |
2016 | << "four" |
2017 | << "five" |
2018 | << "six" |
2019 | << "seven" |
2020 | << "eight" |
2021 | << "nine" |
2022 | << "ten" |
2023 | << "eleven" |
2024 | << "twelve" ); |
2025 | |
2026 | QQmlContext *ctxt = view.rootContext(); |
2027 | ctxt->setContextProperty("myModel" , &model); |
2028 | |
2029 | view.setSource(testFileUrl(fileName: "groups.qml" )); |
2030 | |
2031 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
2032 | QVERIFY(listview != nullptr); |
2033 | |
2034 | QQuickItem *contentItem = listview->contentItem(); |
2035 | QVERIFY(contentItem != nullptr); |
2036 | |
2037 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(object: qvariant_cast<QObject *>(v: listview->model())); |
2038 | QVERIFY(visualModel); |
2039 | |
2040 | QQmlDelegateModelGroup *visibleItems = visualModel->findChild<QQmlDelegateModelGroup *>(aName: "visibleItems" ); |
2041 | QVERIFY(visibleItems); |
2042 | |
2043 | QQmlDelegateModelGroup *selectedItems = visualModel->findChild<QQmlDelegateModelGroup *>(aName: "selectedItems" ); |
2044 | QVERIFY(selectedItems); |
2045 | |
2046 | const bool f = false; |
2047 | const bool t = true; |
2048 | |
2049 | { |
2050 | QCOMPARE(listview->count(), 12); |
2051 | QCOMPARE(visualModel->items()->count(), 12); |
2052 | QCOMPARE(visibleItems->count(), 12); |
2053 | QCOMPARE(selectedItems->count(), 0); |
2054 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2055 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2056 | static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2057 | static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t }; |
2058 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
2059 | static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f }; |
2060 | VERIFY_GET; |
2061 | } { |
2062 | evaluate<void>(scope: visualModel, expression: "items.addGroups(8, \"selected\")" ); |
2063 | QCOMPARE(listview->count(), 12); |
2064 | QCOMPARE(visualModel->items()->count(), 12); |
2065 | QCOMPARE(visibleItems->count(), 12); |
2066 | QCOMPARE(selectedItems->count(), 1); |
2067 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2068 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2069 | static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2070 | static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t }; |
2071 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 }; |
2072 | static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f }; |
2073 | VERIFY_GET; |
2074 | } { |
2075 | evaluate<void>(scope: visualModel, expression: "items.addGroups(6, 4, [\"visible\", \"selected\"])" ); |
2076 | QCOMPARE(listview->count(), 12); |
2077 | QCOMPARE(visualModel->items()->count(), 12); |
2078 | QCOMPARE(visibleItems->count(), 12); |
2079 | QCOMPARE(selectedItems->count(), 4); |
2080 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2081 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2082 | static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2083 | static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t }; |
2084 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 }; |
2085 | static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f }; |
2086 | VERIFY_GET; |
2087 | } { |
2088 | evaluate<void>(scope: visualModel, expression: "items.setGroups(2, [\"items\", \"selected\"])" ); |
2089 | QCOMPARE(listview->count(), 12); |
2090 | QCOMPARE(visualModel->items()->count(), 12); |
2091 | QCOMPARE(visibleItems->count(), 11); |
2092 | QCOMPARE(selectedItems->count(), 5); |
2093 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2094 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2095 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 }; |
2096 | static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t }; |
2097 | static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 }; |
2098 | static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f }; |
2099 | VERIFY_GET; |
2100 | } { |
2101 | evaluate<void>(scope: selectedItems, expression: "setGroups(0, 3, \"items\")" ); |
2102 | QCOMPARE(listview->count(), 12); |
2103 | QCOMPARE(visualModel->items()->count(), 12); |
2104 | QCOMPARE(visibleItems->count(), 9); |
2105 | QCOMPARE(selectedItems->count(), 2); |
2106 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2107 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2108 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 }; |
2109 | static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t }; |
2110 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 }; |
2111 | static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f }; |
2112 | VERIFY_GET; |
2113 | } { |
2114 | evaluate<void>(scope: visualModel, expression: "items.get(5).inVisible = false" ); |
2115 | QCOMPARE(listview->count(), 12); |
2116 | QCOMPARE(visualModel->items()->count(), 12); |
2117 | QCOMPARE(visibleItems->count(), 8); |
2118 | QCOMPARE(selectedItems->count(), 2); |
2119 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2120 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2121 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 }; |
2122 | static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t }; |
2123 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 }; |
2124 | static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f }; |
2125 | VERIFY_GET; |
2126 | } { |
2127 | evaluate<void>(scope: visualModel, expression: "items.get(5).inSelected = true" ); |
2128 | QCOMPARE(listview->count(), 12); |
2129 | QCOMPARE(visualModel->items()->count(), 12); |
2130 | QCOMPARE(visibleItems->count(), 8); |
2131 | QCOMPARE(selectedItems->count(), 3); |
2132 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2133 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2134 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 }; |
2135 | static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t }; |
2136 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 }; |
2137 | static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f }; |
2138 | VERIFY_GET; |
2139 | } { |
2140 | evaluate<void>(scope: visualModel, expression: "items.get(5).groups = [\"visible\", \"items\"]" ); |
2141 | QCOMPARE(listview->count(), 12); |
2142 | QCOMPARE(visualModel->items()->count(), 12); |
2143 | QCOMPARE(visibleItems->count(), 9); |
2144 | QCOMPARE(selectedItems->count(), 2); |
2145 | static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2146 | static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }; |
2147 | static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 }; |
2148 | static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t }; |
2149 | static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 }; |
2150 | static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f }; |
2151 | VERIFY_GET; |
2152 | } |
2153 | } |
2154 | |
2155 | void tst_qquickvisualdatamodel::invalidGroups() |
2156 | { |
2157 | QUrl source = testFileUrl(fileName: "groups-invalid.qml" ); |
2158 | QTest::ignoreMessage(type: QtWarningMsg, message: (source.toString() + ":13:9: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr(s: "Group names must start with a lower case letter" )).toUtf8()); |
2159 | |
2160 | QQmlComponent component(&engine, source); |
2161 | QScopedPointer<QObject> object(component.create()); |
2162 | QVERIFY(object); |
2163 | |
2164 | QCOMPARE(evaluate<int>(object.data(), "groups.length" ), 4); |
2165 | QCOMPARE(evaluate<QString>(object.data(), "groups[0].name" ), QString("items" )); |
2166 | QCOMPARE(evaluate<QString>(object.data(), "groups[1].name" ), QString("persistedItems" )); |
2167 | QCOMPARE(evaluate<QString>(object.data(), "groups[2].name" ), QString("visible" )); |
2168 | QCOMPARE(evaluate<QString>(object.data(), "groups[3].name" ), QString("selected" )); |
2169 | } |
2170 | |
2171 | void tst_qquickvisualdatamodel::onChanged_data() |
2172 | { |
2173 | QTest::addColumn<QString>(name: "expression" ); |
2174 | QTest::addColumn<QStringList>(name: "tests" ); |
2175 | |
2176 | QTest::newRow(dataTag: "item appended" ) |
2177 | << QString("listModel.append({\"number\": \"five\"})" ) |
2178 | << (QStringList() |
2179 | << "verify(vm.removed, [], [], [])" |
2180 | << "verify(vm.inserted, [4], [1], [undefined])" |
2181 | << "verify(vi.removed, [], [], [])" |
2182 | << "verify(vi.inserted, [4], [1], [undefined])" |
2183 | << "verify(si.removed, [], [], [])" |
2184 | << "verify(si.inserted, [], [], [])" ); |
2185 | QTest::newRow(dataTag: "item prepended" ) |
2186 | << QString("listModel.insert(0, {\"number\": \"five\"})" ) |
2187 | << (QStringList() |
2188 | << "verify(vm.removed, [], [], [])" |
2189 | << "verify(vm.inserted, [0], [1], [undefined])" |
2190 | << "verify(vi.removed, [], [], [])" |
2191 | << "verify(vi.inserted, [0], [1], [undefined])" |
2192 | << "verify(si.removed, [], [], [])" |
2193 | << "verify(si.inserted, [], [], [])" ); |
2194 | QTest::newRow(dataTag: "item inserted" ) |
2195 | << QString("listModel.insert(2, {\"number\": \"five\"})" ) |
2196 | << (QStringList() |
2197 | << "verify(vm.removed, [], [], [])" |
2198 | << "verify(vm.inserted, [2], [1], [undefined])" |
2199 | << "verify(vi.removed, [], [], [])" |
2200 | << "verify(vi.inserted, [2], [1], [undefined])" |
2201 | << "verify(si.removed, [], [], [])" |
2202 | << "verify(si.inserted, [], [], [])" ); |
2203 | |
2204 | QTest::newRow(dataTag: "item removed tail" ) |
2205 | << QString("listModel.remove(3)" ) |
2206 | << (QStringList() |
2207 | << "verify(vm.removed, [3], [1], [undefined])" |
2208 | << "verify(vm.inserted, [], [], [])" |
2209 | << "verify(vi.removed, [3], [1], [undefined])" |
2210 | << "verify(vi.inserted, [], [], [])" |
2211 | << "verify(si.removed, [], [], [])" |
2212 | << "verify(si.inserted, [], [], [])" ); |
2213 | QTest::newRow(dataTag: "item removed head" ) |
2214 | << QString("listModel.remove(0)" ) |
2215 | << (QStringList() |
2216 | << "verify(vm.removed, [0], [1], [undefined])" |
2217 | << "verify(vm.inserted, [], [], [])" |
2218 | << "verify(vi.removed, [0], [1], [undefined])" |
2219 | << "verify(vi.inserted, [], [], [])" |
2220 | << "verify(si.removed, [], [], [])" |
2221 | << "verify(si.inserted, [], [], [])" ); |
2222 | QTest::newRow(dataTag: "item removed middle" ) |
2223 | << QString("listModel.remove(1)" ) |
2224 | << (QStringList() |
2225 | << "verify(vm.removed, [1], [1], [undefined])" |
2226 | << "verify(vm.inserted, [], [], [])" |
2227 | << "verify(vi.removed, [1], [1], [undefined])" |
2228 | << "verify(vi.inserted, [], [], [])" |
2229 | << "verify(si.removed, [], [], [])" |
2230 | << "verify(si.inserted, [], [], [])" ); |
2231 | |
2232 | |
2233 | QTest::newRow(dataTag: "item moved from tail" ) |
2234 | << QString("listModel.move(3, 0, 1)" ) |
2235 | << (QStringList() |
2236 | << "verify(vm.removed, [3], [1], [vm.inserted[0].moveId])" |
2237 | << "verify(vm.inserted, [0], [1], [vm.removed[0].moveId])" |
2238 | << "verify(vi.removed, [3], [1], [vi.inserted[0].moveId])" |
2239 | << "verify(vi.inserted, [0], [1], [vi.removed[0].moveId])" |
2240 | << "verify(si.removed, [], [], [])" |
2241 | << "verify(si.inserted, [], [], [])" ); |
2242 | QTest::newRow(dataTag: "item moved from head" ) |
2243 | << QString("listModel.move(0, 2, 2)" ) |
2244 | << (QStringList() |
2245 | << "verify(vm.removed, [0], [2], [vm.inserted[0].moveId])" |
2246 | << "verify(vm.inserted, [2], [2], [vm.removed[0].moveId])" |
2247 | << "verify(vi.removed, [0], [2], [vi.inserted[0].moveId])" |
2248 | << "verify(vi.inserted, [2], [2], [vi.removed[0].moveId])" |
2249 | << "verify(si.removed, [], [], [])" |
2250 | << "verify(si.inserted, [], [], [])" ); |
2251 | |
2252 | QTest::newRow(dataTag: "groups changed" ) |
2253 | << QString("items.setGroups(1, 2, [\"items\", \"selected\"])" ) |
2254 | << (QStringList() |
2255 | << "verify(vm.inserted, [], [], [])" |
2256 | << "verify(vm.removed, [], [], [])" |
2257 | << "verify(vi.removed, [1], [2], [undefined])" |
2258 | << "verify(vi.inserted, [], [], [])" |
2259 | << "verify(si.removed, [], [], [])" |
2260 | << "verify(si.inserted, [0], [2], [undefined])" ); |
2261 | |
2262 | QTest::newRow(dataTag: "multiple removes" ) |
2263 | << QString("{ vi.remove(1, 1); " |
2264 | "vi.removeGroups(0, 2, \"items\") }" ) |
2265 | << (QStringList() |
2266 | << "verify(vm.removed, [0, 1], [1, 1], [undefined, undefined])" |
2267 | << "verify(vm.inserted, [], [], [])" |
2268 | << "verify(vi.removed, [1], [1], [undefined])" |
2269 | << "verify(vi.inserted, [], [], [])" |
2270 | << "verify(si.removed, [], [], [])" |
2271 | << "verify(si.inserted, [], [], [])" ); |
2272 | } |
2273 | |
2274 | void tst_qquickvisualdatamodel::onChanged() |
2275 | { |
2276 | QFETCH(QString, expression); |
2277 | QFETCH(QStringList, tests); |
2278 | |
2279 | QQmlComponent component(&engine, testFileUrl(fileName: "onChanged.qml" )); |
2280 | QScopedPointer<QObject> object(component.create()); |
2281 | QVERIFY(object); |
2282 | |
2283 | evaluate<void>(scope: object.data(), expression); |
2284 | |
2285 | foreach (const QString &test, tests) { |
2286 | bool passed = evaluate<bool>(scope: object.data(), expression: test); |
2287 | if (!passed) |
2288 | qWarning() << test; |
2289 | QVERIFY(passed); |
2290 | } |
2291 | } |
2292 | |
2293 | void tst_qquickvisualdatamodel::create() |
2294 | { |
2295 | QQuickView view; |
2296 | |
2297 | SingleRoleModel model(QStringList() |
2298 | << "one" |
2299 | << "two" |
2300 | << "three" |
2301 | << "four" |
2302 | << "five" |
2303 | << "six" |
2304 | << "seven" |
2305 | << "eight" |
2306 | << "nine" |
2307 | << "ten" |
2308 | << "eleven" |
2309 | << "twelve" |
2310 | << "thirteen" |
2311 | << "fourteen" |
2312 | << "fifteen" |
2313 | << "sixteen" |
2314 | << "seventeen" |
2315 | << "eighteen" |
2316 | << "nineteen" |
2317 | << "twenty" ); |
2318 | |
2319 | QQmlContext *ctxt = view.rootContext(); |
2320 | ctxt->setContextProperty("myModel" , &model); |
2321 | |
2322 | view.setSource(testFileUrl(fileName: "create.qml" )); |
2323 | |
2324 | QQuickListView *listview = qobject_cast<QQuickListView*>(object: view.rootObject()); |
2325 | QVERIFY(listview != nullptr); |
2326 | |
2327 | QQuickItem *contentItem = listview->contentItem(); |
2328 | QVERIFY(contentItem != nullptr); |
2329 | |
2330 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(object: qvariant_cast<QObject *>(v: listview->model())); |
2331 | QVERIFY(visualModel); |
2332 | |
2333 | QCOMPARE(listview->count(), 20); |
2334 | |
2335 | QQmlGuard<QQuickItem> delegate; |
2336 | |
2337 | // persistedItems.includeByDefault is true, so all items belong to persistedItems initially. |
2338 | QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate" , 1)); |
2339 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), true); |
2340 | |
2341 | // changing include by default doesn't remove persistance. |
2342 | evaluate<void>(scope: visualModel, expression: "persistedItems.includeByDefault = false" ); |
2343 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), true); |
2344 | |
2345 | // removing from persistedItems does. |
2346 | evaluate<void>(scope: visualModel, expression: "persistedItems.remove(0, 20)" ); |
2347 | QCOMPARE(listview->count(), 20); |
2348 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), false); |
2349 | |
2350 | // Request an item instantiated by the view. |
2351 | QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(1)" ))); |
2352 | QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate" , 1)); |
2353 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), true); |
2354 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 1); |
2355 | |
2356 | evaluate<void>(scope: delegate, expression: "DelegateModel.inPersistedItems = false" ); |
2357 | QCOMPARE(listview->count(), 20); |
2358 | QCoreApplication::sendPostedEvents(receiver: delegate, event_type: QEvent::DeferredDelete); |
2359 | QVERIFY(delegate); |
2360 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), false); |
2361 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 0); |
2362 | |
2363 | // Request an item not instantiated by the view. |
2364 | QVERIFY(!findItem<QQuickItem>(contentItem, "delegate" , 15)); |
2365 | QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(15)" ))); |
2366 | QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate" , 15)); |
2367 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), true); |
2368 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 1); |
2369 | |
2370 | evaluate<void>(scope: visualModel, expression: "persistedItems.remove(0)" ); |
2371 | QCoreApplication::sendPostedEvents(receiver: delegate, event_type: QEvent::DeferredDelete); |
2372 | QVERIFY(!delegate); |
2373 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 0); |
2374 | |
2375 | // Request an item not instantiated by the view, then scroll the view so it will request it. |
2376 | QVERIFY(!findItem<QQuickItem>(contentItem, "delegate" , 16)); |
2377 | QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(16)" ))); |
2378 | QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate" , 16)); |
2379 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), true); |
2380 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 1); |
2381 | |
2382 | evaluate<void>(scope: listview, expression: "positionViewAtIndex(19, ListView.End)" ); |
2383 | QCOMPARE(listview->count(), 20); |
2384 | evaluate<void>(scope: delegate, expression: "DelegateModel.groups = [\"items\"]" ); |
2385 | QCoreApplication::sendPostedEvents(receiver: delegate, event_type: QEvent::DeferredDelete); |
2386 | QVERIFY(delegate); |
2387 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), false); |
2388 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 0); |
2389 | |
2390 | // Request and release an item instantiated by the view, then scroll the view so it releases it. |
2391 | QVERIFY(findItem<QQuickItem>(contentItem, "delegate" , 17)); |
2392 | QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(17)" ))); |
2393 | QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate" , 17)); |
2394 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), true); |
2395 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 1); |
2396 | |
2397 | evaluate<void>(scope: visualModel, expression: "items.removeGroups(17, \"persistedItems\")" ); |
2398 | QCoreApplication::sendPostedEvents(receiver: delegate, event_type: QEvent::DeferredDelete); |
2399 | QVERIFY(delegate); |
2400 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), false); |
2401 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 0); |
2402 | evaluate<void>(scope: listview, expression: "positionViewAtIndex(1, ListView.Beginning)" ); |
2403 | QCOMPARE(listview->count(), 20); |
2404 | QCoreApplication::sendPostedEvents(receiver: delegate, event_type: QEvent::DeferredDelete); |
2405 | QVERIFY(!delegate); |
2406 | |
2407 | // Adding an item to the persistedItems group won't instantiate it, but if later requested by |
2408 | // the view it will be persisted. |
2409 | evaluate<void>(scope: visualModel, expression: "items.addGroups(18, \"persistedItems\")" ); |
2410 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 1); |
2411 | QVERIFY(!findItem<QQuickItem>(contentItem, "delegate" , 18)); |
2412 | evaluate<void>(scope: listview, expression: "positionViewAtIndex(19, ListView.End)" ); |
2413 | QCOMPARE(listview->count(), 20); |
2414 | QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate" , 18)); |
2415 | QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems" ), true); |
2416 | QCoreApplication::sendPostedEvents(receiver: delegate, event_type: QEvent::DeferredDelete); |
2417 | QVERIFY(delegate); |
2418 | evaluate<void>(scope: listview, expression: "positionViewAtIndex(1, ListView.Beginning)" ); |
2419 | QCOMPARE(listview->count(), 20); |
2420 | QCoreApplication::sendPostedEvents(receiver: delegate, event_type: QEvent::DeferredDelete); |
2421 | QVERIFY(delegate); |
2422 | |
2423 | // Remove an uninstantiated but cached item from the persistedItems group. |
2424 | evaluate<void>(scope: visualModel, expression: "items.addGroups(19, \"persistedItems\")" ); |
2425 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), 2); |
2426 | QVERIFY(!findItem<QQuickItem>(contentItem, "delegate" , 19)); |
2427 | // Store a reference to the item so it is retained in the cache. |
2428 | evaluate<void>(scope: visualModel, expression: "persistentHandle = items.get(19)" ); |
2429 | QCOMPARE(evaluate<bool>(visualModel, "persistentHandle.inPersistedItems" ), true); |
2430 | evaluate<void>(scope: visualModel, expression: "items.removeGroups(19, \"persistedItems\")" ); |
2431 | QCOMPARE(evaluate<bool>(visualModel, "persistentHandle.inPersistedItems" ), false); |
2432 | } |
2433 | |
2434 | void tst_qquickvisualdatamodel::incompleteModel() |
2435 | { |
2436 | // DelegateModel is first populated in componentComplete. Verify various functions are |
2437 | // harmlessly ignored until then. |
2438 | |
2439 | QQmlComponent component(&engine); |
2440 | component.setData("import QtQuick 2.0\nimport QtQml.Models 2.2\nDelegateModel {}" , baseUrl: testFileUrl(fileName: "" )); |
2441 | |
2442 | QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); |
2443 | |
2444 | QQmlDelegateModel *model = qobject_cast<QQmlDelegateModel *>(object: object.data()); |
2445 | QVERIFY(model); |
2446 | |
2447 | QSignalSpy itemsSpy(model->items(), SIGNAL(countChanged())); |
2448 | QSignalSpy persistedItemsSpy(model->items(), SIGNAL(countChanged())); |
2449 | |
2450 | evaluate<void>(scope: model, expression: "items.removeGroups(0, items.count, \"items\")" ); |
2451 | QCOMPARE(itemsSpy.count(), 0); |
2452 | QCOMPARE(persistedItemsSpy.count(), 0); |
2453 | |
2454 | evaluate<void>(scope: model, expression: "items.setGroups(0, items.count, \"persistedItems\")" ); |
2455 | QCOMPARE(itemsSpy.count(), 0); |
2456 | QCOMPARE(persistedItemsSpy.count(), 0); |
2457 | |
2458 | evaluate<void>(scope: model, expression: "items.addGroups(0, items.count, \"persistedItems\")" ); |
2459 | QCOMPARE(itemsSpy.count(), 0); |
2460 | QCOMPARE(persistedItemsSpy.count(), 0); |
2461 | |
2462 | evaluate<void>(scope: model, expression: "items.remove(0, items.count)" ); |
2463 | QCOMPARE(itemsSpy.count(), 0); |
2464 | QCOMPARE(persistedItemsSpy.count(), 0); |
2465 | |
2466 | evaluate<void>(scope: model, expression: "items.insert([ \"color\": \"blue\" ])" ); |
2467 | QCOMPARE(itemsSpy.count(), 0); |
2468 | QCOMPARE(persistedItemsSpy.count(), 0); |
2469 | |
2470 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*get: index out of range" )); |
2471 | QVERIFY(evaluate<bool>(model, "items.get(0) === undefined" )); |
2472 | |
2473 | component.completeCreate(); |
2474 | } |
2475 | |
2476 | void tst_qquickvisualdatamodel::insert_data() |
2477 | { |
2478 | QTest::addColumn<QUrl>(name: "source" ); |
2479 | QTest::addColumn<QString>(name: "expression" ); |
2480 | QTest::addColumn<int>(name: "modelCount" ); |
2481 | QTest::addColumn<int>(name: "visualCount" ); |
2482 | QTest::addColumn<int>(name: "index" ); |
2483 | QTest::addColumn<bool>(name: "inItems" ); |
2484 | QTest::addColumn<bool>(name: "persisted" ); |
2485 | QTest::addColumn<bool>(name: "visible" ); |
2486 | QTest::addColumn<bool>(name: "selected" ); |
2487 | QTest::addColumn<bool>(name: "modelData" ); |
2488 | QTest::addColumn<QString>(name: "property" ); |
2489 | QTest::addColumn<QStringList>(name: "propertyData" ); |
2490 | |
2491 | const QUrl listModelSource[] = { |
2492 | testFileUrl(fileName: "listmodelproperties.qml" ), |
2493 | testFileUrl(fileName: "listmodelproperties-package.qml" ) }; |
2494 | const QUrl singleRoleSource[] = { |
2495 | testFileUrl(fileName: "singleroleproperties.qml" ), |
2496 | testFileUrl(fileName: "singleroleproperties-package.qml" ) }; |
2497 | const QUrl multipleRoleSource[] = { |
2498 | testFileUrl(fileName: "multipleroleproperties.qml" ), |
2499 | testFileUrl(fileName: "multipleroleproperties-package.qml" ) }; |
2500 | const QUrl stringListSource[] = { |
2501 | testFileUrl(fileName: "stringlistproperties.qml" ), |
2502 | testFileUrl(fileName: "stringlistproperties-package.qml" ) }; |
2503 | const QUrl objectListSource[] = { |
2504 | testFileUrl(fileName: "objectlistproperties.qml" ), |
2505 | testFileUrl(fileName: "objectlistproperties-package.qml" ) }; |
2506 | |
2507 | for (int i = 0; i < 2; ++i) { |
2508 | // List Model. |
2509 | QTest::newRow(dataTag: "ListModel.items prepend" ) |
2510 | << listModelSource[i] |
2511 | << QString("items.insert(0, {\"number\": \"eight\"})" ) |
2512 | << 4 << 5 << 0 << true << false << false << false << true |
2513 | << QString("number" ) |
2514 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2515 | |
2516 | QTest::newRow(dataTag: "ListModel.items append" ) |
2517 | << listModelSource[i] |
2518 | << QString("items.insert({\"number\": \"eight\"})" ) |
2519 | << 4 << 5 << 4 << true << false << false << false << true |
2520 | << QString("number" ) |
2521 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2522 | |
2523 | QTest::newRow(dataTag: "ListModel.items insert at 2" ) |
2524 | << listModelSource[i] |
2525 | << QString("items.insert(2, {\"number\": \"eight\"})" ) |
2526 | << 4 << 5 << 2 << true << false << false << false << true |
2527 | << QString("number" ) |
2528 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2529 | |
2530 | QTest::newRow(dataTag: "ListModel.items insert at items.get(2)" ) |
2531 | << listModelSource[i] |
2532 | << QString("items.insert(items.get(2), {\"number\": \"eight\"})" ) |
2533 | << 4 << 5 << 2 << true << false << false << false << true |
2534 | << QString("number" ) |
2535 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2536 | |
2537 | QTest::newRow(dataTag: "ListModel.items insert at visibleItems.get(2)" ) |
2538 | << listModelSource[i] |
2539 | << QString("items.insert(visibleItems.get(2), {\"number\": \"eight\"})" ) |
2540 | << 4 << 5 << 2 << true << false << false << false << true |
2541 | << QString("number" ) |
2542 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2543 | |
2544 | QTest::newRow(dataTag: "ListModel.selectedItems insert at items.get(2)" ) |
2545 | << listModelSource[i] |
2546 | << QString("selectedItems.insert(items.get(2), {\"number\": \"eight\"})" ) |
2547 | << 4 << 5 << 2 << false << false << false << true << true |
2548 | << QString("number" ) |
2549 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2550 | |
2551 | QTest::newRow(dataTag: "ListModel.selectedItems insert at visibleItems.get(2)" ) |
2552 | << listModelSource[i] |
2553 | << QString("selectedItems.insert(visibleItems.get(2), {\"number\": \"eight\"})" ) |
2554 | << 4 << 5 << 2 << false << false << false << true << true |
2555 | << QString("number" ) |
2556 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2557 | |
2558 | QTest::newRow(dataTag: "ListModel.items prepend modelData" ) |
2559 | << listModelSource[i] |
2560 | << QString("items.insert(0, {\"modelData\": \"eight\"})" ) |
2561 | << 4 << 5 << 0 << true << false << false << false << true |
2562 | << QString("number" ) |
2563 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2564 | |
2565 | QTest::newRow(dataTag: "ListModel.items prepend, edit number" ) |
2566 | << listModelSource[i] |
2567 | << QString("{ " |
2568 | "items.insert(0, {\"number\": \"eight\"}); " |
2569 | "items.get(0).model.number = \"seven\"; }" ) |
2570 | << 4 << 5 << 0 << true << false << false << false << true |
2571 | << QString("number" ) |
2572 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2573 | |
2574 | QTest::newRow(dataTag: "ListModel.items prepend, edit modelData" ) |
2575 | << listModelSource[i] |
2576 | << QString("{ " |
2577 | "items.insert(0, {\"number\": \"eight\"}); " |
2578 | "items.get(0).model.modelData = \"seven\"; }" ) |
2579 | << 4 << 5 << 0 << true << false << false << false << true |
2580 | << QString("number" ) |
2581 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2582 | |
2583 | QTest::newRow(dataTag: "ListModel.items prepend, edit resolved" ) |
2584 | << listModelSource[i] |
2585 | << QString("{ " |
2586 | "items.insert(0, {\"number\": \"eight\"}); " |
2587 | "items.get(2).model.number = \"seven\"; }" ) |
2588 | << 4 << 5 << 0 << true << false << false << false << true |
2589 | << QString("number" ) |
2590 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2591 | |
2592 | QTest::newRow(dataTag: "ListModel.items prepend with groups" ) |
2593 | << listModelSource[i] |
2594 | << QString("items.insert(0, {\"number\": \"eight\"}, [\"visible\", \"truncheon\"])" ) |
2595 | << 4 << 5 << 0 << true << false << true << false << true |
2596 | << QString("number" ) |
2597 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2598 | |
2599 | QTest::newRow(dataTag: "ListModel.items append with groups" ) |
2600 | << listModelSource[i] |
2601 | << QString("items.insert({\"number\": \"eight\"}, [\"visible\", \"selected\"])" ) |
2602 | << 4 << 5 << 4 << true << false << true << true << true |
2603 | << QString("number" ) |
2604 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2605 | |
2606 | QTest::newRow(dataTag: "ListModel.items insert at 2 with groups" ) |
2607 | << listModelSource[i] |
2608 | << QString("items.insert(2, {\"number\": \"eight\"}, \"visible\")" ) |
2609 | << 4 << 5 << 2 << true << false << true << false << true |
2610 | << QString("number" ) |
2611 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2612 | |
2613 | // create ListModel |
2614 | QTest::newRow(dataTag: "ListModel.items prepend" ) |
2615 | << listModelSource[i] |
2616 | << QString("items.create(0, {\"number\": \"eight\"})" ) |
2617 | << 4 << 5 << 0 << true << true << false << false << true |
2618 | << QString("number" ) |
2619 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2620 | |
2621 | QTest::newRow(dataTag: "ListModel.items append" ) |
2622 | << listModelSource[i] |
2623 | << QString("items.create({\"number\": \"eight\"})" ) |
2624 | << 4 << 5 << 4 << true << true << false << false << true |
2625 | << QString("number" ) |
2626 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2627 | |
2628 | QTest::newRow(dataTag: "ListModel.items create at 2" ) |
2629 | << listModelSource[i] |
2630 | << QString("items.create(2, {\"number\": \"eight\"})" ) |
2631 | << 4 << 5 << 2 << true << true << false << false << true |
2632 | << QString("number" ) |
2633 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2634 | |
2635 | QTest::newRow(dataTag: "ListModel.items create at items.get(2)" ) |
2636 | << listModelSource[i] |
2637 | << QString("items.create(items.get(2), {\"number\": \"eight\"})" ) |
2638 | << 4 << 5 << 2 << true << true << false << false << true |
2639 | << QString("number" ) |
2640 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2641 | |
2642 | QTest::newRow(dataTag: "ListModel.items create at visibleItems.get(2)" ) |
2643 | << listModelSource[i] |
2644 | << QString("items.create(visibleItems.get(2), {\"number\": \"eight\"})" ) |
2645 | << 4 << 5 << 2 << true << true << false << false << true |
2646 | << QString("number" ) |
2647 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2648 | |
2649 | QTest::newRow(dataTag: "ListModel.selectedItems create at items.get(2)" ) |
2650 | << listModelSource[i] |
2651 | << QString("selectedItems.create(items.get(2), {\"number\": \"eight\"})" ) |
2652 | << 4 << 5 << 2 << false << true << false << true << true |
2653 | << QString("number" ) |
2654 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2655 | |
2656 | QTest::newRow(dataTag: "ListModel.selectedItems create at visibleItems.get(2)" ) |
2657 | << listModelSource[i] |
2658 | << QString("selectedItems.create(visibleItems.get(2), {\"number\": \"eight\"})" ) |
2659 | << 4 << 5 << 2 << false << true << false << true << true |
2660 | << QString("number" ) |
2661 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2662 | |
2663 | QTest::newRow(dataTag: "ListModel.items create prepended" ) |
2664 | << listModelSource[i] |
2665 | << QString("items.create(0, {\"number\": \"eight\"})" ) |
2666 | << 4 << 5 << 0 << true << true << false << false << true |
2667 | << QString("number" ) |
2668 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2669 | |
2670 | QTest::newRow(dataTag: "ListModel.items create appended" ) |
2671 | << listModelSource[i] |
2672 | << QString("items.create({\"number\": \"eight\"})" ) |
2673 | << 4 << 5 << 4 << true << true << false << false << true |
2674 | << QString("number" ) |
2675 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2676 | |
2677 | QTest::newRow(dataTag: "ListModel.items create at 2" ) |
2678 | << listModelSource[i] |
2679 | << QString("items.create(2, {\"number\": \"eight\"})" ) |
2680 | << 4 << 5 << 2 << true << true << false << false << true |
2681 | << QString("number" ) |
2682 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2683 | |
2684 | QTest::newRow(dataTag: "ListModel.items create at items.get(2)" ) |
2685 | << listModelSource[i] |
2686 | << QString("items.create(items.get(2), {\"number\": \"eight\"})" ) |
2687 | << 4 << 5 << 2 << true << true << false << false << true |
2688 | << QString("number" ) |
2689 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2690 | |
2691 | QTest::newRow(dataTag: "ListModel.items create at visibleItems.get(2)" ) |
2692 | << listModelSource[i] |
2693 | << QString("items.create(visibleItems.get(2), {\"number\": \"eight\"})" ) |
2694 | << 4 << 5 << 2 << true << true << false << false << true |
2695 | << QString("number" ) |
2696 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2697 | |
2698 | QTest::newRow(dataTag: "ListModel.create prepend modelData" ) |
2699 | << listModelSource[i] |
2700 | << QString("items.create(0, {\"modelData\": \"eight\"})" ) |
2701 | << 4 << 5 << 0 << true << true << false << false << true |
2702 | << QString("number" ) |
2703 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2704 | |
2705 | QTest::newRow(dataTag: "ListModel.items create prepended, edit number" ) |
2706 | << listModelSource[i] |
2707 | << QString("{ " |
2708 | "var item = items.create(0, {\"number\": \"eight\"}); " |
2709 | "item.setTest3(\"seven\"); }" ) |
2710 | << 4 << 5 << 0 << true << true << false << false << true |
2711 | << QString("number" ) |
2712 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2713 | |
2714 | QTest::newRow(dataTag: "ListModel.items create prepended, edit model.number" ) |
2715 | << listModelSource[i] |
2716 | << QString("{ " |
2717 | "var item = items.create(0, {\"number\": \"eight\"}); " |
2718 | "item.setTest4(\"seven\"); }" ) |
2719 | << 4 << 5 << 0 << true << true << false << false << true |
2720 | << QString("number" ) |
2721 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2722 | |
2723 | QTest::newRow(dataTag: "ListModel.items create prepended, edit modelData" ) |
2724 | << listModelSource[i] |
2725 | << QString("{ " |
2726 | "var item = items.create(0, {\"number\": \"eight\"}); " |
2727 | "item.setTest5(\"seven\"); }" ) |
2728 | << 4 << 5 << 0 << true << true << false << false << true |
2729 | << QString("number" ) |
2730 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2731 | |
2732 | QTest::newRow(dataTag: "ListModel.items create prepended, edit model.modelData" ) |
2733 | << listModelSource[i] |
2734 | << QString("{ " |
2735 | "var item = items.create(0, {\"number\": \"eight\"}); " |
2736 | "item.setTest6(\"seven\"); }" ) |
2737 | << 4 << 5 << 0 << true << true << false << false << true |
2738 | << QString("number" ) |
2739 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2740 | |
2741 | QTest::newRow(dataTag: "ListModel.items create prepended with groups" ) |
2742 | << listModelSource[i] |
2743 | << QString("items.create(0, {\"number\": \"eight\"}, [\"visible\", \"truncheon\"])" ) |
2744 | << 4 << 5 << 0 << true << true << true << false << true |
2745 | << QString("number" ) |
2746 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2747 | |
2748 | QTest::newRow(dataTag: "ListModel.items create appended with groups" ) |
2749 | << listModelSource[i] |
2750 | << QString("items.create({\"number\": \"eight\"}, [\"visible\", \"selected\"])" ) |
2751 | << 4 << 5 << 4 << true << true << true << true << true |
2752 | << QString("number" ) |
2753 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2754 | |
2755 | QTest::newRow(dataTag: "ListModel.items create inserted with groups" ) |
2756 | << listModelSource[i] |
2757 | << QString("items.create(2, {\"number\": \"eight\"}, \"visible\")" ) |
2758 | << 4 << 5 << 2 << true << true << true << false << true |
2759 | << QString("number" ) |
2760 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2761 | |
2762 | QTest::newRow(dataTag: "ListModel.items create prepended clear persistence" ) |
2763 | << listModelSource[i] |
2764 | << QString("{ items.create(0, {\"number\": \"eight\"}); " |
2765 | "items.get(0).inPersistedItems = false }" ) |
2766 | << 4 << 5 << 0 << true << false << false << false << true |
2767 | << QString("number" ) |
2768 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2769 | |
2770 | QTest::newRow(dataTag: "ListModel.items create appended clear persistence" ) |
2771 | << listModelSource[i] |
2772 | << QString("{ items.create({\"number\": \"eight\"}); " |
2773 | "items.get(4).inPersistedItems = false }" ) |
2774 | << 4 << 5 << 4 << true << false << false << false << true |
2775 | << QString("number" ) |
2776 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2777 | |
2778 | QTest::newRow(dataTag: "ListModel.items create inserted clear persistence" ) |
2779 | << listModelSource[i] |
2780 | << QString("{ items.create(2, {\"number\": \"eight\"}); " |
2781 | "items.get(2).inPersistedItems = false }" ) |
2782 | << 4 << 5 << 2 << true << false << false << false << true |
2783 | << QString("number" ) |
2784 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2785 | |
2786 | // AbstractItemModel (Single Role). |
2787 | QTest::newRow(dataTag: "AbstractItemModel.items prepend" ) |
2788 | << singleRoleSource[i] |
2789 | << QString("items.insert(0, {\"name\": \"eight\"})" ) |
2790 | << 4 << 5 << 0 << true << false << false << false << true |
2791 | << QString("name" ) |
2792 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2793 | |
2794 | QTest::newRow(dataTag: "AbstractItemModel.items append" ) |
2795 | << singleRoleSource[i] |
2796 | << QString("items.insert({\"name\": \"eight\"})" ) |
2797 | << 4 << 5 << 4 << true << false << false << false << true |
2798 | << QString("name" ) |
2799 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2800 | |
2801 | QTest::newRow(dataTag: "AbstractItemModel.items insert at 2" ) |
2802 | << singleRoleSource[i] |
2803 | << QString("items.insert(2, {\"name\": \"eight\"})" ) |
2804 | << 4 << 5 << 2 << true << false << false << false << true |
2805 | << QString("name" ) |
2806 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2807 | |
2808 | QTest::newRow(dataTag: "AbstractItemModel.items prepend modelData" ) |
2809 | << singleRoleSource[i] |
2810 | << QString("items.insert(0, {\"modelData\": \"eight\"})" ) |
2811 | << 4 << 5 << 0 << true << false << false << false << true |
2812 | << QString("name" ) |
2813 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2814 | |
2815 | QTest::newRow(dataTag: "AbstractItemModel.items prepend, edit name" ) |
2816 | << singleRoleSource[i] |
2817 | << QString("{ " |
2818 | "items.insert(0, {\"name\": \"eight\"}); " |
2819 | "items.get(0).model.name = \"seven\"; }" ) |
2820 | << 4 << 5 << 0 << true << false << false << false << true |
2821 | << QString("name" ) |
2822 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2823 | |
2824 | QTest::newRow(dataTag: "AbstractItemModel.items prepend, edit modelData" ) |
2825 | << singleRoleSource[i] |
2826 | << QString("{ " |
2827 | "items.insert(0, {\"name\": \"eight\"}); " |
2828 | "items.get(0).model.modelData = \"seven\"; }" ) |
2829 | << 4 << 5 << 0 << true << false << false << false << true |
2830 | << QString("name" ) |
2831 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2832 | |
2833 | QTest::newRow(dataTag: "AbstractItemModel.items prepend, edit resolved" ) |
2834 | << singleRoleSource[i] |
2835 | << QString("{ " |
2836 | "items.insert(0, {\"name\": \"eight\"}); " |
2837 | "items.get(2).model.name = \"seven\"; }" ) |
2838 | << 4 << 5 << 0 << true << false << false << false << true |
2839 | << QString("name" ) |
2840 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2841 | |
2842 | QTest::newRow(dataTag: "AbstractItemModel.create prepend modelData" ) |
2843 | << singleRoleSource[i] |
2844 | << QString("items.create(0, {\"modelData\": \"eight\"})" ) |
2845 | << 4 << 5 << 0 << true << true << false << false << true |
2846 | << QString("name" ) |
2847 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2848 | |
2849 | QTest::newRow(dataTag: "AbstractItemModel.items create prepended, edit name" ) |
2850 | << singleRoleSource[i] |
2851 | << QString("{ " |
2852 | "var item = items.create(0, {\"name\": \"eight\"}); " |
2853 | "item.setTest3(\"seven\"); }" ) |
2854 | << 4 << 5 << 0 << true << true << false << false << true |
2855 | << QString("name" ) |
2856 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2857 | |
2858 | QTest::newRow(dataTag: "AbstractItemModel.items create prepended, edit model.name" ) |
2859 | << singleRoleSource[i] |
2860 | << QString("{ " |
2861 | "var item = items.create(0, {\"name\": \"eight\"}); " |
2862 | "item.setTest4(\"seven\"); }" ) |
2863 | << 4 << 5 << 0 << true << true << false << false << true |
2864 | << QString("name" ) |
2865 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2866 | |
2867 | QTest::newRow(dataTag: "AbstractItemModel.items create prepended, edit modelData" ) |
2868 | << singleRoleSource[i] |
2869 | << QString("{ " |
2870 | "var item = items.create(0, {\"name\": \"eight\"}); " |
2871 | "item.setTest5(\"seven\"); }" ) |
2872 | << 4 << 5 << 0 << true << true << false << false << true |
2873 | << QString("name" ) |
2874 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2875 | |
2876 | QTest::newRow(dataTag: "AbstractItemModel.items create prepended, edit model.modelData" ) |
2877 | << singleRoleSource[i] |
2878 | << QString("{ " |
2879 | "var item = items.create(0, {\"name\": \"eight\"}); " |
2880 | "item.setTest6(\"seven\"); }" ) |
2881 | << 4 << 5 << 0 << true << true << false << false << true |
2882 | << QString("name" ) |
2883 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2884 | |
2885 | // AbstractItemModel (Multiple Roles). |
2886 | QTest::newRow(dataTag: "StandardItemModel.items prepend" ) |
2887 | << multipleRoleSource[i] |
2888 | << QString("items.insert(0, {\"display\": \"Row 8 Item\"})" ) |
2889 | << 4 << 5 << 0 << true << false << false << false << false |
2890 | << QString("display" ) |
2891 | << (QStringList() << "Row 8 Item" << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2892 | |
2893 | QTest::newRow(dataTag: "StandardItemModel.items append" ) |
2894 | << multipleRoleSource[i] |
2895 | << QString("items.insert({\"display\": \"Row 8 Item\"})" ) |
2896 | << 4 << 5 << 4 << true << false << false << false << false |
2897 | << QString("display" ) |
2898 | << (QStringList() << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" << "Row 8 Item" ); |
2899 | |
2900 | QTest::newRow(dataTag: "StandardItemModel.items insert at 2" ) |
2901 | << multipleRoleSource[i] |
2902 | << QString("items.insert(2, {\"display\": \"Row 8 Item\"})" ) |
2903 | << 4 << 5 << 2 << true << false << false << false << false |
2904 | << QString("display" ) |
2905 | << (QStringList() << "Row 1 Item" << "Row 2 Item" << "Row 8 Item" << "Row 3 Item" << "Row 4 Item" ); |
2906 | |
2907 | QTest::newRow(dataTag: "StandardItemModel.items prepend modelData" ) |
2908 | << multipleRoleSource[i] |
2909 | << QString("items.insert(0, {\"modelData\": \"Row 8 Item\"})" ) |
2910 | << 4 << 5 << 0 << true << false << false << false << false |
2911 | << QString("display" ) |
2912 | << (QStringList() << QString() << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2913 | |
2914 | QTest::newRow(dataTag: "StandardItemModel.items prepend, edit display" ) |
2915 | << multipleRoleSource[i] |
2916 | << QString("{ " |
2917 | "items.insert(0, {\"display\": \"Row 8 Item\"}); " |
2918 | "items.get(0).model.display = \"Row 7 Item\"; }" ) |
2919 | << 4 << 5 << 0 << true << false << false << false << false |
2920 | << QString("display" ) |
2921 | << (QStringList() << "Row 7 Item" << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2922 | |
2923 | QTest::newRow(dataTag: "StandardItemModel.items prepend, edit modelData" ) |
2924 | << multipleRoleSource[i] |
2925 | << QString("{ " |
2926 | "items.insert(0, {\"display\": \"Row 8 Item\"}); " |
2927 | "items.get(0).model.modelData = \"Row 7 Item\"; }" ) |
2928 | << 4 << 5 << 0 << true << false << false << false << false |
2929 | << QString("display" ) |
2930 | << (QStringList() << "Row 8 Item" << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2931 | |
2932 | QTest::newRow(dataTag: "StandardItemModel.items prepend, edit resolved" ) |
2933 | << multipleRoleSource[i] |
2934 | << QString("{ " |
2935 | "items.insert(0, {\"display\": \"Row 8 Item\"}); " |
2936 | "items.get(2).model.display = \"Row 7 Item\"; }" ) |
2937 | << 4 << 5 << 0 << true << false << false << false << false |
2938 | << QString("display" ) |
2939 | << (QStringList() << "Row 8 Item" << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2940 | |
2941 | QTest::newRow(dataTag: "StandardItemModel.create prepend modelData" ) |
2942 | << multipleRoleSource[i] |
2943 | << QString("items.create(0, {\"modelData\": \"Row 8 Item\"})" ) |
2944 | << 4 << 5 << 0 << true << true << false << false << false |
2945 | << QString("display" ) |
2946 | << (QStringList() << QString() << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2947 | |
2948 | QTest::newRow(dataTag: "StandardItemModel.items create prepended, edit display" ) |
2949 | << multipleRoleSource[i] |
2950 | << QString("{ " |
2951 | "var item = items.create(0, {\"display\": \"Row 8 Item\"}); " |
2952 | "item.setTest3(\"Row 7 Item\"); }" ) |
2953 | << 4 << 5 << 0 << true << true << false << false << false |
2954 | << QString("display" ) |
2955 | << (QStringList() << "Row 7 Item" << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2956 | |
2957 | QTest::newRow(dataTag: "StandardItemModel.items create prepended, edit model.display" ) |
2958 | << multipleRoleSource[i] |
2959 | << QString("{ " |
2960 | "var item = items.create(0, {\"display\": \"Row 8 Item\"}); " |
2961 | "item.setTest4(\"Row 7 Item\"); }" ) |
2962 | << 4 << 5 << 0 << true << true << false << false << false |
2963 | << QString("display" ) |
2964 | << (QStringList() << "Row 7 Item" << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
2965 | |
2966 | // StringList. |
2967 | QTest::newRow(dataTag: "StringList.items prepend" ) |
2968 | << stringListSource[i] |
2969 | << QString("items.insert(0, {\"modelData\": \"eight\"})" ) |
2970 | << 4 << 5 << 0 << true << false << false << false << false |
2971 | << QString("modelData" ) |
2972 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
2973 | |
2974 | QTest::newRow(dataTag: "StringList.items append" ) |
2975 | << stringListSource[i] |
2976 | << QString("items.insert({\"modelData\": \"eight\"})" ) |
2977 | << 4 << 5 << 4 << true << false << false << false << false |
2978 | << QString("modelData" ) |
2979 | << (QStringList() << "one" << "two" << "three" << "four" << "eight" ); |
2980 | |
2981 | QTest::newRow(dataTag: "StringList.items insert at 2" ) |
2982 | << stringListSource[i] |
2983 | << QString("items.insert(2, {\"modelData\": \"eight\"})" ) |
2984 | << 4 << 5 << 2 << true << false << false << false << false |
2985 | << QString("modelData" ) |
2986 | << (QStringList() << "one" << "two" << "eight" << "three" << "four" ); |
2987 | |
2988 | QTest::newRow(dataTag: "StringList.items prepend, edit modelData" ) |
2989 | << stringListSource[i] |
2990 | << QString("{ " |
2991 | "items.insert(0, {\"modelData\": \"eight\"}); " |
2992 | "items.get(0).model.modelData = \"seven\"; }" ) |
2993 | << 4 << 5 << 0 << true << false << false << false << false |
2994 | << QString("modelData" ) |
2995 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
2996 | |
2997 | QTest::newRow(dataTag: "StringList.items prepend, edit resolved" ) |
2998 | << stringListSource[i] |
2999 | << QString("{ " |
3000 | "items.insert(0, {\"modelData\": \"eight\"}); " |
3001 | "items.get(2).model.modelData = \"seven\"; }" ) |
3002 | << 4 << 5 << 0 << true << false << false << false << false |
3003 | << QString("modelData" ) |
3004 | << (QStringList() << "eight" << "one" << "seven" << "three" << "four" ); |
3005 | |
3006 | QTest::newRow(dataTag: "StringList.create prepend modelData" ) |
3007 | << stringListSource[i] |
3008 | << QString("items.create(0, {\"modelData\": \"eight\"})" ) |
3009 | << 4 << 5 << 0 << true << true << false << false << false |
3010 | << QString("modelData" ) |
3011 | << (QStringList() << "eight" << "one" << "two" << "three" << "four" ); |
3012 | |
3013 | QTest::newRow(dataTag: "StringList.items create prepended, edit modelData" ) |
3014 | << stringListSource[i] |
3015 | << QString("{ " |
3016 | "var item = items.create(0, {\"modelData\": \"eight\"}); " |
3017 | "item.setTest3(\"seven\"); }" ) |
3018 | << 4 << 5 << 0 << true << true << false << false << false |
3019 | << QString("modelData" ) |
3020 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3021 | |
3022 | QTest::newRow(dataTag: "StringList.items create prepended, edit model.modelData" ) |
3023 | << stringListSource[i] |
3024 | << QString("{ " |
3025 | "var item = items.create(0, {\"modelData\": \"eight\"}); " |
3026 | "item.setTest4(\"seven\"); }" ) |
3027 | << 4 << 5 << 0 << true << true << false << false << false |
3028 | << QString("modelData" ) |
3029 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3030 | |
3031 | // ObjectList |
3032 | QTest::newRow(dataTag: "ObjectList.items prepend" ) |
3033 | << objectListSource[i] |
3034 | << QString("items.insert(0, {\"name\": \"Item 8\"})" ) |
3035 | << 4 << 4 << 4 << false << false << false << false << false |
3036 | << QString("name" ) |
3037 | << (QStringList() << "Item 1" << "Item 2" << "Item 3" << "Item 4" ); |
3038 | |
3039 | QTest::newRow(dataTag: "ObjectList.items append" ) |
3040 | << objectListSource[i] |
3041 | << QString("items.insert({\"name\": \"Item 8\"})" ) |
3042 | << 4 << 4 << 4 << false << false << false << false << false |
3043 | << QString("name" ) |
3044 | << (QStringList() << "Item 1" << "Item 2" << "Item 3" << "Item 4" ); |
3045 | |
3046 | QTest::newRow(dataTag: "ObjectList.items insert at 2" ) |
3047 | << objectListSource[i] |
3048 | << QString("items.insert(2, {\"name\": \"Item 8\"})" ) |
3049 | << 4 << 4 << 4 << false << false << false << false << false |
3050 | << QString("name" ) |
3051 | << (QStringList() << "Item 1" << "Item 2" << "Item 3" << "Item 4" ); |
3052 | } |
3053 | } |
3054 | |
3055 | void tst_qquickvisualdatamodel::insert() |
3056 | { |
3057 | QFETCH(QUrl, source); |
3058 | QFETCH(QString, expression); |
3059 | QFETCH(int, modelCount); |
3060 | QFETCH(int, visualCount); |
3061 | QFETCH(int, index); |
3062 | QFETCH(bool, inItems); |
3063 | QFETCH(bool, persisted); |
3064 | QFETCH(bool, visible); |
3065 | QFETCH(bool, selected); |
3066 | QFETCH(bool, modelData); |
3067 | QFETCH(QString, property); |
3068 | QFETCH(QStringList, propertyData); |
3069 | |
3070 | QQuickWindow window; |
3071 | |
3072 | QQmlComponent component(&engine); |
3073 | component.loadUrl(url: source); |
3074 | QScopedPointer<QObject> object(component.create()); |
3075 | QQuickListView *listView = qobject_cast<QQuickListView *>(object: object.data()); |
3076 | QVERIFY(listView); |
3077 | listView->setParentItem(window.contentItem()); |
3078 | |
3079 | QQuickItem *contentItem = listView->contentItem(); |
3080 | QVERIFY(contentItem); |
3081 | |
3082 | QObject *visualModel = listView->findChild<QObject *>(aName: "visualModel" ); |
3083 | QVERIFY(visualModel); |
3084 | |
3085 | evaluate<void>(scope: visualModel, expression); |
3086 | |
3087 | QCOMPARE(evaluate<int>(listView, "count" ), inItems ? visualCount : modelCount); |
3088 | QCOMPARE(evaluate<int>(visualModel, "count" ), inItems ? visualCount : modelCount); |
3089 | QCOMPARE(evaluate<int>(visualModel, "items.count" ), inItems ? visualCount : modelCount); |
3090 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), persisted ? 1 : 0); |
3091 | QCOMPARE(evaluate<int>(visualModel, "visibleItems.count" ), visible ? visualCount : modelCount); |
3092 | QCOMPARE(evaluate<int>(visualModel, "selectedItems.count" ), selected ? 1 : 0); |
3093 | |
3094 | QCOMPARE(propertyData.count(), visualCount); |
3095 | for (int i = 0; i < visualCount; ++i) { |
3096 | int modelIndex = i; |
3097 | if (modelIndex > index) |
3098 | modelIndex -= 1; |
3099 | else if (modelIndex == index) |
3100 | modelIndex = -1; |
3101 | |
3102 | const int itemsIndex = inItems || i <= index ? i : i - 1; |
3103 | QString get; |
3104 | |
3105 | if (i != index) { |
3106 | get = QString("items.get(%1)" ).arg(a: itemsIndex); |
3107 | |
3108 | QQuickItem *item = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: modelIndex); |
3109 | QVERIFY(item); |
3110 | |
3111 | QCOMPARE(evaluate<int>(item, "test1" ), modelIndex); |
3112 | QCOMPARE(evaluate<int>(item, "test2" ), modelIndex); |
3113 | QCOMPARE(evaluate<QString>(item, "test3" ), propertyData.at(i)); |
3114 | QCOMPARE(evaluate<QString>(item, "test4" ), propertyData.at(i)); |
3115 | |
3116 | if (modelData) { |
3117 | QCOMPARE(evaluate<QString>(item, "test5" ), propertyData.at(i)); |
3118 | QCOMPARE(evaluate<QString>(item, "test6" ), propertyData.at(i)); |
3119 | } |
3120 | |
3121 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems" ), true); |
3122 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems" ), false); |
3123 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible" ), true); |
3124 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected" ), false); |
3125 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved" ), false); |
3126 | |
3127 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex" ), itemsIndex); |
3128 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex" ), persisted && i > index ? 1 : 0); |
3129 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex" ), visible || i <= index ? i : i - 1); |
3130 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex" ), selected && i > index ? 1 : 0); |
3131 | } else if (inItems) { |
3132 | get = QString("items.get(%1)" ).arg(a: index); |
3133 | } else if (persisted) { |
3134 | get = "persistedItems.get(0)" ; |
3135 | } else if (visible) { |
3136 | get = QString("visibleItems.get(%1)" ).arg(a: index); |
3137 | } else if (selected) { |
3138 | get = "selectedItems.get(0)" ; |
3139 | } else { |
3140 | continue; |
3141 | } |
3142 | |
3143 | QCOMPARE(evaluate<int>(visualModel, get + ".model.index" ), modelIndex); |
3144 | |
3145 | QCOMPARE(evaluate<QString>(visualModel, get + ".model." + property), propertyData.at(i)); |
3146 | |
3147 | QCOMPARE(evaluate<bool>(visualModel, get + ".inItems" ), inItems || i != index); |
3148 | QCOMPARE(evaluate<bool>(visualModel, get + ".inPersistedItems" ), persisted && i == index); |
3149 | QCOMPARE(evaluate<bool>(visualModel, get + ".inVisible" ), visible || i != index); |
3150 | QCOMPARE(evaluate<bool>(visualModel, get + ".inSelected" ), selected && i == index); |
3151 | QCOMPARE(evaluate<bool>(visualModel, get + ".isUnresolved" ), i == index); |
3152 | |
3153 | QCOMPARE(evaluate<int>(visualModel, get + ".itemsIndex" ), inItems || i <= index ? i : i - 1); |
3154 | QCOMPARE(evaluate<int>(visualModel, get + ".persistedItemsIndex" ), persisted && i > index ? 1 : 0); |
3155 | QCOMPARE(evaluate<int>(visualModel, get + ".visibleIndex" ), visible || i <= index ? i : i - 1); |
3156 | QCOMPARE(evaluate<int>(visualModel, get + ".selectedIndex" ), selected && i > index ? 1 : 0); |
3157 | } |
3158 | |
3159 | QObject *item = nullptr; |
3160 | |
3161 | if (inItems) |
3162 | item = evaluate<QObject *>(scope: visualModel, expression: QString("items.create(%1)" ).arg(a: index)); |
3163 | else if (persisted) |
3164 | item = evaluate<QObject *>(scope: visualModel, expression: QString("persistedItems.create(%1)" ).arg(a: 0)); |
3165 | else if (visible) |
3166 | item = evaluate<QObject *>(scope: visualModel, expression: QString("visibleItems.create(%1)" ).arg(a: index)); |
3167 | else if (selected) |
3168 | item = evaluate<QObject *>(scope: visualModel, expression: QString("selectedItems.create(%1)" ).arg(a: 0)); |
3169 | else |
3170 | return; |
3171 | |
3172 | QVERIFY(item); |
3173 | |
3174 | QCOMPARE(evaluate<int>(item, "test1" ), -1); |
3175 | QCOMPARE(evaluate<int>(item, "test2" ), -1); |
3176 | QCOMPARE(evaluate<QString>(item, "test3" ), propertyData.at(index)); |
3177 | QCOMPARE(evaluate<QString>(item, "test4" ), propertyData.at(index)); |
3178 | |
3179 | if (modelData) { |
3180 | QCOMPARE(evaluate<QString>(item, "test5" ), propertyData.at(index)); |
3181 | QCOMPARE(evaluate<QString>(item, "test6" ), propertyData.at(index)); |
3182 | } |
3183 | |
3184 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems" ), inItems); |
3185 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems" ), true); |
3186 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible" ), visible); |
3187 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected" ), selected); |
3188 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved" ), true); |
3189 | |
3190 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex" ), index); |
3191 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex" ), 0); |
3192 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex" ), index); |
3193 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex" ), 0); |
3194 | } |
3195 | |
3196 | void tst_qquickvisualdatamodel::resolve_data() |
3197 | { |
3198 | QTest::addColumn<QUrl>(name: "source" ); |
3199 | QTest::addColumn<QString>(name: "setupExpression" ); |
3200 | QTest::addColumn<QString>(name: "resolveExpression" ); |
3201 | QTest::addColumn<int>(name: "unresolvedCount" ); |
3202 | QTest::addColumn<int>(name: "modelCount" ); |
3203 | QTest::addColumn<int>(name: "visualCount" ); |
3204 | QTest::addColumn<int>(name: "index" ); |
3205 | QTest::addColumn<bool>(name: "inItems" ); |
3206 | QTest::addColumn<bool>(name: "persisted" ); |
3207 | QTest::addColumn<bool>(name: "visible" ); |
3208 | QTest::addColumn<bool>(name: "selected" ); |
3209 | QTest::addColumn<bool>(name: "modelData" ); |
3210 | QTest::addColumn<QString>(name: "property" ); |
3211 | QTest::addColumn<QStringList>(name: "propertyData" ); |
3212 | |
3213 | const QUrl listModelSource[] = { |
3214 | testFileUrl(fileName: "listmodelproperties.qml" ), |
3215 | testFileUrl(fileName: "listmodelproperties-package.qml" ) }; |
3216 | const QUrl singleRoleSource[] = { |
3217 | testFileUrl(fileName: "singleroleproperties.qml" ), |
3218 | testFileUrl(fileName: "singleroleproperties-package.qml" ) }; |
3219 | const QUrl multipleRoleSource[] = { |
3220 | testFileUrl(fileName: "multipleroleproperties.qml" ), |
3221 | testFileUrl(fileName: "multipleroleproperties-package.qml" ) }; |
3222 | const QUrl stringListSource[] = { |
3223 | testFileUrl(fileName: "stringlistproperties.qml" ), |
3224 | testFileUrl(fileName: "stringlistproperties-package.qml" ) }; |
3225 | |
3226 | for (int i = 0; i < 2; ++i) { |
3227 | // List Model. |
3228 | QTest::newRow(dataTag: "ListModel.items prepend, resolve prepended" ) |
3229 | << listModelSource[i] |
3230 | << QString("items.insert(0, {\"number\": \"eight\"})" ) |
3231 | << QString("{ listModel.insert(0, {\"number\": \"seven\"}); items.resolve(0, 1) }" ) |
3232 | << 5 << 5 << 5 << 0 << true << false << true << false << true |
3233 | << QString("number" ) |
3234 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3235 | |
3236 | QTest::newRow(dataTag: "ListModel.items prepend, resolve appended" ) |
3237 | << listModelSource[i] |
3238 | << QString("items.insert(0, {\"number\": \"eight\"})" ) |
3239 | << QString("{ listModel.append({\"number\": \"seven\"}); items.resolve(0, 5) }" ) |
3240 | << 5 << 5 << 5 << 4 << true << false << true << false << true |
3241 | << QString("number" ) |
3242 | << (QStringList() << "one" << "two" << "three" << "four" << "seven" ); |
3243 | |
3244 | QTest::newRow(dataTag: "ListModel.items prepend, resolve inserted" ) |
3245 | << listModelSource[i] |
3246 | << QString("items.insert(0, {\"number\": \"eight\"})" ) |
3247 | << QString("{ listModel.insert(2, {\"number\": \"seven\"}); items.resolve(0, 3) }" ) |
3248 | << 5 << 5 << 5 << 2 << true << false << true << false << true |
3249 | << QString("number" ) |
3250 | << (QStringList() << "one" << "two" << "seven" << "three" << "four" ); |
3251 | |
3252 | QTest::newRow(dataTag: "ListModel.items append, resolve prepended" ) |
3253 | << listModelSource[i] |
3254 | << QString("items.insert({\"number\": \"eight\"})" ) |
3255 | << QString("{ listModel.insert(0, {\"number\": \"seven\"}); items.resolve(5, 0) }" ) |
3256 | << 5 << 5 << 5 << 0 << true << false << true << false << true |
3257 | << QString("number" ) |
3258 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3259 | |
3260 | QTest::newRow(dataTag: "ListModel.items append, resolve appended" ) |
3261 | << listModelSource[i] |
3262 | << QString("items.insert({\"number\": \"eight\"})" ) |
3263 | << QString("{ listModel.append({\"number\": \"seven\"}); items.resolve(5, 4) }" ) |
3264 | << 5 << 5 << 5 << 4 << true << false << true << false << true |
3265 | << QString("number" ) |
3266 | << (QStringList() << "one" << "two" << "three" << "four" << "seven" ); |
3267 | |
3268 | QTest::newRow(dataTag: "ListModel.items append, resolve inserted" ) |
3269 | << listModelSource[i] |
3270 | << QString("items.insert({\"number\": \"eight\"})" ) |
3271 | << QString("{ listModel.insert(2, {\"number\": \"seven\"}); items.resolve(5, 2) }" ) |
3272 | << 5 << 5 << 5 << 2 << true << false << true << false << true |
3273 | << QString("number" ) |
3274 | << (QStringList() << "one" << "two" << "seven" << "three" << "four" ); |
3275 | |
3276 | QTest::newRow(dataTag: "ListModel.items insert, resolve prepended" ) |
3277 | << listModelSource[i] |
3278 | << QString("items.insert(2, {\"number\": \"eight\"})" ) |
3279 | << QString("{ listModel.insert(0, {\"number\": \"seven\"}); items.resolve(3, 0) }" ) |
3280 | << 5 << 5 << 5 << 0 << true << false << true << false << true |
3281 | << QString("number" ) |
3282 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3283 | |
3284 | QTest::newRow(dataTag: "ListModel.items insert, resolve appended" ) |
3285 | << listModelSource[i] |
3286 | << QString("items.insert(2, {\"number\": \"eight\"})" ) |
3287 | << QString("{ listModel.append({\"number\": \"seven\"}); items.resolve(2, 5) }" ) |
3288 | << 5 << 5 << 5 << 4 << true << false << true << false << true |
3289 | << QString("number" ) |
3290 | << (QStringList() << "one" << "two" << "three" << "four" << "seven" ); |
3291 | |
3292 | QTest::newRow(dataTag: "ListModel.items insert, resolve inserted" ) |
3293 | << listModelSource[i] |
3294 | << QString("items.insert(2, {\"number\": \"eight\"})" ) |
3295 | << QString("{ listModel.insert(2, {\"number\": \"seven\"}); items.resolve(2, 3) }" ) |
3296 | << 5 << 5 << 5 << 2 << true << false << true << false << true |
3297 | << QString("number" ) |
3298 | << (QStringList() << "one" << "two" << "seven" << "three" << "four" ); |
3299 | |
3300 | QTest::newRow(dataTag: "ListModel.items prepend, move resolved" ) |
3301 | << listModelSource[i] |
3302 | << QString("items.insert(0, {\"number\": \"eight\"})" ) |
3303 | << QString("{ listModel.insert(0, {\"number\": \"seven\"}); " |
3304 | "items.resolve(0, 1); " |
3305 | "listModel.move(0, 2, 1) }" ) |
3306 | << 5 << 5 << 5 << 2 << true << false << true << false << true |
3307 | << QString("number" ) |
3308 | << (QStringList() << "one" << "two" << "seven" << "three" << "four" ); |
3309 | |
3310 | QTest::newRow(dataTag: "ListModel.items append, move resolved" ) |
3311 | << listModelSource[i] |
3312 | << QString("items.insert({\"number\": \"eight\"})" ) |
3313 | << QString("{ listModel.append({\"number\": \"seven\"}); " |
3314 | "items.resolve(5, 4); " |
3315 | "listModel.move(4, 2, 1) }" ) |
3316 | << 5 << 5 << 5 << 2 << true << false << true << false << true |
3317 | << QString("number" ) |
3318 | << (QStringList() << "one" << "two" << "seven" << "three" << "four" ); |
3319 | |
3320 | QTest::newRow(dataTag: "ListModel.items insert, move resolved" ) |
3321 | << listModelSource[i] |
3322 | << QString("items.insert(2, {\"number\": \"eight\"})" ) |
3323 | << QString("{ listModel.insert(2, {\"number\": \"seven\"}); " |
3324 | "items.resolve(2, 3);" |
3325 | "listModel.move(2, 0, 1) }" ) |
3326 | << 5 << 5 << 5 << 0 << true << false << true << false << true |
3327 | << QString("number" ) |
3328 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3329 | |
3330 | QTest::newRow(dataTag: "ListModel.items prepend, remove resolved" ) |
3331 | << listModelSource[i] |
3332 | << QString("items.insert(0, {\"number\": \"eight\"})" ) |
3333 | << QString("{ listModel.insert(0, {\"number\": \"seven\"}); " |
3334 | "items.resolve(0, 1); " |
3335 | "listModel.remove(0, 1) }" ) |
3336 | << 5 << 4 << 4 << 4 << false << false << false << false << true |
3337 | << QString("number" ) |
3338 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3339 | |
3340 | QTest::newRow(dataTag: "ListModel.items append, remove resolved" ) |
3341 | << listModelSource[i] |
3342 | << QString("items.insert({\"number\": \"eight\"})" ) |
3343 | << QString("{ listModel.append({\"number\": \"seven\"}); " |
3344 | "items.resolve(5, 4); " |
3345 | "listModel.remove(4, 1) }" ) |
3346 | << 5 << 4 << 4 << 4 << false << false << false << false << true |
3347 | << QString("number" ) |
3348 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3349 | |
3350 | QTest::newRow(dataTag: "ListModel.items insert, remove resolved" ) |
3351 | << listModelSource[i] |
3352 | << QString("items.insert(2, {\"number\": \"eight\"})" ) |
3353 | << QString("{ listModel.insert(2, {\"number\": \"seven\"}); " |
3354 | "items.resolve(2, 3);" |
3355 | "listModel.remove(2, 1) }" ) |
3356 | << 5 << 4 << 4 << 4 << false << false << false << false << true |
3357 | << QString("number" ) |
3358 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3359 | |
3360 | QTest::newRow(dataTag: "ListModel.selectedItems prepend, resolve prepended" ) |
3361 | << listModelSource[i] |
3362 | << QString("selectedItems.insert(0, {\"number\": \"eight\"})" ) |
3363 | << QString("{ listModel.insert(0, {\"number\": \"seven\"}); " |
3364 | "selectedItems.resolve(selectedItems.get(0), items.get(0)) }" ) |
3365 | << 4 << 5 << 5 << 0 << true << false << true << true << true |
3366 | << QString("number" ) |
3367 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3368 | |
3369 | QTest::newRow(dataTag: "ListModel.selectedItems prepend, resolve appended" ) |
3370 | << listModelSource[i] |
3371 | << QString("selectedItems.insert(0, {\"number\": \"eight\"})" ) |
3372 | << QString("{ listModel.append({\"number\": \"seven\"}); " |
3373 | "selectedItems.resolve(selectedItems.get(0), items.get(4)) }" ) |
3374 | << 4 << 5 << 5 << 4 << true << false << true << true << true |
3375 | << QString("number" ) |
3376 | << (QStringList() << "one" << "two" << "three" << "four" << "seven" ); |
3377 | |
3378 | QTest::newRow(dataTag: "ListModel.selectedItems prepend, resolve inserted" ) |
3379 | << listModelSource[i] |
3380 | << QString("selectedItems.insert(0, {\"number\": \"eight\"})" ) |
3381 | << QString("{ listModel.insert(2, {\"number\": \"seven\"}); " |
3382 | "selectedItems.resolve(selectedItems.get(0), items.get(2)) }" ) |
3383 | << 4 << 5 << 5 << 2 << true << false << true << true << true |
3384 | << QString("number" ) |
3385 | << (QStringList() << "one" << "two" << "seven" << "three" << "four" ); |
3386 | |
3387 | QTest::newRow(dataTag: "ListModel.selectedItems append, resolve prepended" ) |
3388 | << listModelSource[i] |
3389 | << QString("selectedItems.insert({\"number\": \"eight\"})" ) |
3390 | << QString("{ listModel.insert(0, {\"number\": \"seven\"}); " |
3391 | "selectedItems.resolve(selectedItems.get(0), items.get(0)) }" ) |
3392 | << 4 << 5 << 5 << 0 << true << false << true << true << true |
3393 | << QString("number" ) |
3394 | << (QStringList() << "seven" << "one" << "two" << "three" << "four" ); |
3395 | |
3396 | QTest::newRow(dataTag: "ListModel.selectedItems append, resolve appended" ) |
3397 | << listModelSource[i] |
3398 | << QString("selectedItems.insert({\"number\": \"eight\"})" ) |
3399 | << QString("{ listModel.append({\"number\": \"seven\"}); " |
3400 | "selectedItems.resolve(selectedItems.get(0), items.get(4)) }" ) |
3401 | << 4 << 5 << 5 << 4 << true << false << true << true << true |
3402 | << QString("number" ) |
3403 | << (QStringList() << "one" << "two" << "three" << "four" << "seven" ); |
3404 | |
3405 | QTest::newRow(dataTag: "ListModel.selectedItems append, resolve inserted" ) |
3406 | << listModelSource[i] |
3407 | << QString("selectedItems.insert({\"number\": \"eight\"})" ) |
3408 | << QString("{ listModel.insert(2, {\"number\": \"seven\"}); " |
3409 | "selectedItems.resolve(selectedItems.get(0), items.get(2)) }" ) |
3410 | << 4 << 5 << 5 << 2 << true << false << true << true << true |
3411 | << QString("number" ) |
3412 | << (QStringList() << "one" << "two" << "seven" << "three" << "four" ); |
3413 | |
3414 | // AbstractItemModel (Single Role) |
3415 | QTest::newRow(dataTag: "ListModel.items prepend, resolve prepended" ) |
3416 | << singleRoleSource[i] |
3417 | << QString("items.insert(0, {\"name\": \"eight\"})" ) |
3418 | << QString("{ items.resolve(0, 1) }" ) |
3419 | << 5 << 4 << 4 << 0 << true << false << true << false << true |
3420 | << QString("name" ) |
3421 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3422 | |
3423 | |
3424 | QTest::newRow(dataTag: "ListModel.items append, resolve appended" ) |
3425 | << singleRoleSource[i] |
3426 | << QString("items.insert({\"name\": \"eight\"})" ) |
3427 | << QString("{ items.resolve(4, 3) }" ) |
3428 | << 5 << 4 << 4 << 3 << true << false << true << false << true |
3429 | << QString("name" ) |
3430 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3431 | |
3432 | QTest::newRow(dataTag: "ListModel.items insert, resolve inserted" ) |
3433 | << singleRoleSource[i] |
3434 | << QString("items.insert(2, {\"name\": \"eight\"})" ) |
3435 | << QString("{ items.resolve(2, 3) }" ) |
3436 | << 5 << 4 << 4 << 2 << true << false << true << false << true |
3437 | << QString("name" ) |
3438 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3439 | |
3440 | // AbstractItemModel (Single Role) |
3441 | QTest::newRow(dataTag: "AbstractItemModel.items prepend, resolve prepended" ) |
3442 | << singleRoleSource[i] |
3443 | << QString("items.insert(0, {\"name\": \"eight\"})" ) |
3444 | << QString("{ items.resolve(0, 1) }" ) |
3445 | << 5 << 4 << 4 << 0 << true << false << true << false << true |
3446 | << QString("name" ) |
3447 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3448 | |
3449 | QTest::newRow(dataTag: "AbstractItemModel.items append, resolve appended" ) |
3450 | << singleRoleSource[i] |
3451 | << QString("items.insert({\"name\": \"eight\"})" ) |
3452 | << QString("{ items.resolve(4, 3) }" ) |
3453 | << 5 << 4 << 4 << 3 << true << false << true << false << true |
3454 | << QString("name" ) |
3455 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3456 | |
3457 | QTest::newRow(dataTag: "AbstractItemModel.items insert, resolve inserted" ) |
3458 | << singleRoleSource[i] |
3459 | << QString("items.insert(2, {\"name\": \"eight\"})" ) |
3460 | << QString("{ items.resolve(2, 3) }" ) |
3461 | << 5 << 4 << 4 << 2 << true << false << true << false << true |
3462 | << QString("name" ) |
3463 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3464 | |
3465 | // AbstractItemModel (Multiple Roles) |
3466 | QTest::newRow(dataTag: "StandardItemModel.items prepend, resolve prepended" ) |
3467 | << multipleRoleSource[i] |
3468 | << QString("items.insert(0, {\"display\": \"Row 8 Item\"})" ) |
3469 | << QString("{ items.resolve(0, 1) }" ) |
3470 | << 5 << 4 << 4 << 0 << true << false << true << false << false |
3471 | << QString("display" ) |
3472 | << (QStringList() << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
3473 | |
3474 | QTest::newRow(dataTag: "StandardItemModel.items append, resolve appended" ) |
3475 | << multipleRoleSource[i] |
3476 | << QString("items.insert({\"display\": \"Row 8 Item\"})" ) |
3477 | << QString("{ items.resolve(4, 3) }" ) |
3478 | << 5 << 4 << 4 << 3 << true << false << true << false << false |
3479 | << QString("display" ) |
3480 | << (QStringList() << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
3481 | |
3482 | QTest::newRow(dataTag: "StandardItemModel.items insert, resolve inserted" ) |
3483 | << multipleRoleSource[i] |
3484 | << QString("items.insert(2, {\"display\": \"Row 8 Item\"})" ) |
3485 | << QString("{ items.resolve(2, 3) }" ) |
3486 | << 5 << 4 << 4 << 2 << true << false << true << false << false |
3487 | << QString("display" ) |
3488 | << (QStringList() << "Row 1 Item" << "Row 2 Item" << "Row 3 Item" << "Row 4 Item" ); |
3489 | |
3490 | // StringList |
3491 | QTest::newRow(dataTag: "StringList.items prepend, resolve prepended" ) |
3492 | << stringListSource[i] |
3493 | << QString("items.insert(0, {\"modelData\": \"eight\"})" ) |
3494 | << QString("{ items.resolve(0, 1) }" ) |
3495 | << 5 << 4 << 4 << 0 << true << false << true << false << false |
3496 | << QString("modelData" ) |
3497 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3498 | |
3499 | QTest::newRow(dataTag: "StringList.items append, resolve appended" ) |
3500 | << stringListSource[i] |
3501 | << QString("items.insert({\"modelData\": \"eight\"})" ) |
3502 | << QString("{ items.resolve(4, 3) }" ) |
3503 | << 5 << 4 << 4 << 3 << true << false << true << false << false |
3504 | << QString("modelData" ) |
3505 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3506 | |
3507 | QTest::newRow(dataTag: "StringList.items insert, resolve inserted" ) |
3508 | << stringListSource[i] |
3509 | << QString("items.insert(2, {\"modelData\": \"eight\"})" ) |
3510 | << QString("{ items.resolve(2, 3) }" ) |
3511 | << 5 << 4 << 4 << 2 << true << false << true << false << false |
3512 | << QString("modelData" ) |
3513 | << (QStringList() << "one" << "two" << "three" << "four" ); |
3514 | } |
3515 | } |
3516 | |
3517 | void tst_qquickvisualdatamodel::resolve() |
3518 | { |
3519 | QFETCH(QUrl, source); |
3520 | QFETCH(QString, setupExpression); |
3521 | QFETCH(QString, resolveExpression); |
3522 | QFETCH(int, unresolvedCount); |
3523 | QFETCH(int, modelCount); |
3524 | QFETCH(int, visualCount); |
3525 | QFETCH(int, index); |
3526 | QFETCH(bool, inItems); |
3527 | QFETCH(bool, persisted); |
3528 | QFETCH(bool, visible); |
3529 | QFETCH(bool, selected); |
3530 | QFETCH(bool, modelData); |
3531 | QFETCH(QString, property); |
3532 | QFETCH(QStringList, propertyData); |
3533 | |
3534 | QQuickWindow window; |
3535 | |
3536 | QQmlComponent component(&engine); |
3537 | component.loadUrl(url: source); |
3538 | QScopedPointer<QObject> object(component.create()); |
3539 | QQuickListView *listView = qobject_cast<QQuickListView *>(object: object.data()); |
3540 | QVERIFY(listView); |
3541 | listView->setParentItem(window.contentItem()); |
3542 | |
3543 | QQuickItem *contentItem = listView->contentItem(); |
3544 | QVERIFY(contentItem); |
3545 | |
3546 | QObject *visualModel = listView->findChild<QObject *>(aName: "visualModel" ); |
3547 | QVERIFY(visualModel); |
3548 | |
3549 | evaluate<void>(scope: visualModel, expression: setupExpression); |
3550 | QCOMPARE(evaluate<int>(listView, "count" ), unresolvedCount); |
3551 | |
3552 | listView->forceLayout(); |
3553 | evaluate<void>(scope: visualModel, expression: resolveExpression); |
3554 | |
3555 | QCOMPARE(evaluate<int>(listView, "count" ), inItems ? visualCount : modelCount); |
3556 | QCOMPARE(evaluate<int>(visualModel, "count" ), inItems ? visualCount : modelCount); |
3557 | QCOMPARE(evaluate<int>(visualModel, "items.count" ), inItems ? visualCount : modelCount); |
3558 | QCOMPARE(evaluate<int>(visualModel, "persistedItems.count" ), persisted ? 1 : 0); |
3559 | QCOMPARE(evaluate<int>(visualModel, "visibleItems.count" ), visible ? visualCount : modelCount); |
3560 | QCOMPARE(evaluate<int>(visualModel, "selectedItems.count" ), selected ? 1 : 0); |
3561 | |
3562 | QCOMPARE(propertyData.count(), visualCount); |
3563 | for (int i = 0; i < visualCount; ++i) { |
3564 | int modelIndex = i; |
3565 | |
3566 | const int itemsIndex = inItems || i <= index ? i : i - 1; |
3567 | QString get; |
3568 | |
3569 | if (i != index) { |
3570 | get = QString("items.get(%1)" ).arg(a: itemsIndex); |
3571 | |
3572 | QQuickItem *item = findItem<QQuickItem>(parent: contentItem, objectName: "delegate" , index: modelIndex); |
3573 | QVERIFY(item); |
3574 | |
3575 | QCOMPARE(evaluate<int>(item, "test1" ), modelIndex); |
3576 | QCOMPARE(evaluate<int>(item, "test2" ), modelIndex); |
3577 | QCOMPARE(evaluate<QString>(item, "test3" ), propertyData.at(i)); |
3578 | QCOMPARE(evaluate<QString>(item, "test4" ), propertyData.at(i)); |
3579 | |
3580 | if (modelData) { |
3581 | QCOMPARE(evaluate<QString>(item, "test5" ), propertyData.at(i)); |
3582 | QCOMPARE(evaluate<QString>(item, "test6" ), propertyData.at(i)); |
3583 | } |
3584 | |
3585 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems" ), true); |
3586 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems" ), false); |
3587 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible" ), true); |
3588 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected" ), false); |
3589 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved" ), false); |
3590 | |
3591 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex" ), itemsIndex); |
3592 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex" ), persisted && i > index ? 1 : 0); |
3593 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex" ), visible || i <= index ? i : i - 1); |
3594 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex" ), selected && i > index ? 1 : 0); |
3595 | } else if (inItems) { |
3596 | get = QString("items.get(%1)" ).arg(a: index); |
3597 | } else if (persisted) { |
3598 | get = "persistedItems.get(0)" ; |
3599 | } else if (visible) { |
3600 | get = QString("visibleItems.get(%1)" ).arg(a: index); |
3601 | } else if (selected) { |
3602 | get = "selectedItems.get(0)" ; |
3603 | } else { |
3604 | continue; |
3605 | } |
3606 | |
3607 | QCOMPARE(evaluate<int>(visualModel, get + ".model.index" ), modelIndex); |
3608 | |
3609 | QCOMPARE(evaluate<QString>(visualModel, get + ".model." + property), propertyData.at(i)); |
3610 | |
3611 | QCOMPARE(evaluate<bool>(visualModel, get + ".inItems" ), inItems || i != index); |
3612 | QCOMPARE(evaluate<bool>(visualModel, get + ".inPersistedItems" ), persisted && i == index); |
3613 | QCOMPARE(evaluate<bool>(visualModel, get + ".inVisible" ), visible || i != index); |
3614 | QCOMPARE(evaluate<bool>(visualModel, get + ".inSelected" ), selected && i == index); |
3615 | QCOMPARE(evaluate<bool>(visualModel, get + ".isUnresolved" ), false); |
3616 | |
3617 | QCOMPARE(evaluate<int>(visualModel, get + ".itemsIndex" ), inItems || i <= index ? i : i - 1); |
3618 | QCOMPARE(evaluate<int>(visualModel, get + ".persistedItemsIndex" ), persisted && i > index ? 1 : 0); |
3619 | QCOMPARE(evaluate<int>(visualModel, get + ".visibleIndex" ), visible || i <= index ? i : i - 1); |
3620 | QCOMPARE(evaluate<int>(visualModel, get + ".selectedIndex" ), selected && i > index ? 1 : 0); |
3621 | } |
3622 | |
3623 | QObject *item = nullptr; |
3624 | |
3625 | if (inItems) |
3626 | item = evaluate<QObject *>(scope: visualModel, expression: QString("items.create(%1)" ).arg(a: index)); |
3627 | else if (persisted) |
3628 | item = evaluate<QObject *>(scope: visualModel, expression: QString("persistedItems.create(%1)" ).arg(a: 0)); |
3629 | else if (visible) |
3630 | item = evaluate<QObject *>(scope: visualModel, expression: QString("visibleItems.create(%1)" ).arg(a: index)); |
3631 | else if (selected) |
3632 | item = evaluate<QObject *>(scope: visualModel, expression: QString("selectedItems.create(%1)" ).arg(a: 0)); |
3633 | else |
3634 | return; |
3635 | |
3636 | QVERIFY(item); |
3637 | |
3638 | QCOMPARE(evaluate<int>(item, "test1" ), index); |
3639 | QCOMPARE(evaluate<int>(item, "test2" ), index); |
3640 | QCOMPARE(evaluate<QString>(item, "test3" ), propertyData.at(index)); |
3641 | QCOMPARE(evaluate<QString>(item, "test4" ), propertyData.at(index)); |
3642 | |
3643 | if (modelData) { |
3644 | QCOMPARE(evaluate<QString>(item, "test5" ), propertyData.at(index)); |
3645 | QCOMPARE(evaluate<QString>(item, "test6" ), propertyData.at(index)); |
3646 | } |
3647 | |
3648 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems" ), inItems); |
3649 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems" ), true); |
3650 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible" ), visible); |
3651 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected" ), selected); |
3652 | QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved" ), false); |
3653 | |
3654 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex" ), index); |
3655 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex" ), 0); |
3656 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex" ), index); |
3657 | QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex" ), 0); |
3658 | } |
3659 | |
3660 | void tst_qquickvisualdatamodel::warnings_data() |
3661 | { |
3662 | QTest::addColumn<QUrl>(name: "source" ); |
3663 | QTest::addColumn<QString>(name: "expression" ); |
3664 | QTest::addColumn<QRegularExpression>(name: "warning" ); |
3665 | QTest::addColumn<int>(name: "count" ); |
3666 | |
3667 | QTest::newRow(dataTag: "insert < 0" ) |
3668 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3669 | << QString("items.insert(-2, {\"number\": \"eight\"})" ) |
3670 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "insert: index out of range" )) |
3671 | << 4; |
3672 | |
3673 | QTest::newRow(dataTag: "insert > length" ) |
3674 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3675 | << QString("items.insert(8, {\"number\": \"eight\"})" ) |
3676 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "insert: index out of range" )) |
3677 | << 4; |
3678 | |
3679 | QTest::newRow(dataTag: "create < 0" ) |
3680 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3681 | << QString("items.create(-2, {\"number\": \"eight\"})" ) |
3682 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "create: index out of range" )) |
3683 | << 4; |
3684 | |
3685 | QTest::newRow(dataTag: "create > length" ) |
3686 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3687 | << QString("items.create(8, {\"number\": \"eight\"})" ) |
3688 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "create: index out of range" )) |
3689 | << 4; |
3690 | |
3691 | QTest::newRow(dataTag: "resolve from < 0" ) |
3692 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3693 | << QString("items.resolve(-2, 3)" ) |
3694 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: from index out of range" )) |
3695 | << 4; |
3696 | |
3697 | QTest::newRow(dataTag: "resolve from > length" ) |
3698 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3699 | << QString("items.resolve(8, 3)" ) |
3700 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: from index out of range" )) |
3701 | << 4; |
3702 | |
3703 | QTest::newRow(dataTag: "resolve to < 0" ) |
3704 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3705 | << QString("items.resolve(3, -2)" ) |
3706 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: to index out of range" )) |
3707 | << 4; |
3708 | |
3709 | QTest::newRow(dataTag: "resolve to > length" ) |
3710 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3711 | << QString("items.resolve(3, 8)" ) |
3712 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: to index out of range" )) |
3713 | << 4; |
3714 | |
3715 | QTest::newRow(dataTag: "resolve from invalid index" ) |
3716 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3717 | << QString("items.resolve(\"two\", 3)" ) |
3718 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: from index invalid" )) |
3719 | << 4; |
3720 | |
3721 | QTest::newRow(dataTag: "resolve to invalid index" ) |
3722 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3723 | << QString("items.resolve(3, \"two\")" ) |
3724 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: to index invalid" )) |
3725 | << 4; |
3726 | |
3727 | QTest::newRow(dataTag: "resolve already resolved item" ) |
3728 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3729 | << QString("items.resolve(3, 2)" ) |
3730 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: from is not an unresolved item" )) |
3731 | << 4; |
3732 | |
3733 | QTest::newRow(dataTag: "resolve already resolved item" ) |
3734 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3735 | << QString("{ items.insert(0, {\"number\": \"eight\"});" |
3736 | "items.insert(1, {\"number\": \"seven\"});" |
3737 | "items.resolve(0, 1)}" ) |
3738 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "resolve: to is not a model item" )) |
3739 | << 6; |
3740 | |
3741 | QTest::newRow(dataTag: "remove index < 0" ) |
3742 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3743 | << QString("items.remove(-2, 1)" ) |
3744 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "remove: index out of range" )) |
3745 | << 4; |
3746 | |
3747 | QTest::newRow(dataTag: "remove index == length" ) |
3748 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3749 | << QString("items.remove(4, 1)" ) |
3750 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "remove: index out of range" )) |
3751 | << 4; |
3752 | |
3753 | QTest::newRow(dataTag: "remove index > length" ) |
3754 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3755 | << QString("items.remove(9, 1)" ) |
3756 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "remove: index out of range" )) |
3757 | << 4; |
3758 | |
3759 | QTest::newRow(dataTag: "remove invalid index" ) |
3760 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3761 | << QString("items.remove(\"nine\", 1)" ) |
3762 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "remove: invalid index" )) |
3763 | << 4; |
3764 | |
3765 | QTest::newRow(dataTag: "remove count < 0" ) |
3766 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3767 | << QString("items.remove(1, -2)" ) |
3768 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "remove: invalid count" )) |
3769 | << 4; |
3770 | |
3771 | QTest::newRow(dataTag: "remove index + count > length" ) |
3772 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3773 | << QString("items.remove(2, 4, \"selected\")" ) |
3774 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "remove: invalid count" )) |
3775 | << 4; |
3776 | |
3777 | QTest::newRow(dataTag: "addGroups index < 0" ) |
3778 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3779 | << QString("items.addGroups(-2, 1, \"selected\")" ) |
3780 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "addGroups: index out of range" )) |
3781 | << 4; |
3782 | |
3783 | QTest::newRow(dataTag: "addGroups index == length" ) |
3784 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3785 | << QString("items.addGroups(4, 1, \"selected\")" ) |
3786 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "addGroups: index out of range" )) |
3787 | << 4; |
3788 | |
3789 | QTest::newRow(dataTag: "addGroups index > length" ) |
3790 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3791 | << QString("items.addGroups(9, 1, \"selected\")" ) |
3792 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "addGroups: index out of range" )) |
3793 | << 4; |
3794 | |
3795 | QTest::newRow(dataTag: "addGroups count < 0" ) |
3796 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3797 | << QString("items.addGroups(1, -2, \"selected\")" ) |
3798 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "addGroups: invalid count" )) |
3799 | << 4; |
3800 | |
3801 | QTest::newRow(dataTag: "addGroups index + count > length" ) |
3802 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3803 | << QString("items.addGroups(2, 4, \"selected\")" ) |
3804 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "addGroups: invalid count" )) |
3805 | << 4; |
3806 | |
3807 | QTest::newRow(dataTag: "removeGroups index < 0" ) |
3808 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3809 | << QString("items.removeGroups(-2, 1, \"selected\")" ) |
3810 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "removeGroups: index out of range" )) |
3811 | << 4; |
3812 | |
3813 | QTest::newRow(dataTag: "removeGroups index == length" ) |
3814 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3815 | << QString("items.removeGroups(4, 1, \"selected\")" ) |
3816 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "removeGroups: index out of range" )) |
3817 | << 4; |
3818 | |
3819 | QTest::newRow(dataTag: "removeGroups index > length" ) |
3820 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3821 | << QString("items.removeGroups(9, 1, \"selected\")" ) |
3822 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "removeGroups: index out of range" )) |
3823 | << 4; |
3824 | |
3825 | QTest::newRow(dataTag: "removeGroups count < 0" ) |
3826 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3827 | << QString("items.removeGroups(1, -2, \"selected\")" ) |
3828 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "removeGroups: invalid count" )) |
3829 | << 4; |
3830 | |
3831 | QTest::newRow(dataTag: "removeGroups index + count > length" ) |
3832 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3833 | << QString("items.removeGroups(2, 4, \"selected\")" ) |
3834 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "removeGroups: invalid count" )) |
3835 | << 4; |
3836 | |
3837 | QTest::newRow(dataTag: "setGroups index < 0" ) |
3838 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3839 | << QString("items.setGroups(-2, 1, \"selected\")" ) |
3840 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "setGroups: index out of range" )) |
3841 | << 4; |
3842 | |
3843 | QTest::newRow(dataTag: "setGroups index == length" ) |
3844 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3845 | << QString("items.setGroups(4, 1, \"selected\")" ) |
3846 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "setGroups: index out of range" )) |
3847 | << 4; |
3848 | |
3849 | QTest::newRow(dataTag: "setGroups index > length" ) |
3850 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3851 | << QString("items.setGroups(9, 1, \"selected\")" ) |
3852 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "setGroups: index out of range" )) |
3853 | << 4; |
3854 | |
3855 | QTest::newRow(dataTag: "setGroups count < 0" ) |
3856 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3857 | << QString("items.setGroups(1, -2, \"selected\")" ) |
3858 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "setGroups: invalid count" )) |
3859 | << 4; |
3860 | |
3861 | QTest::newRow(dataTag: "setGroups index + count > length" ) |
3862 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3863 | << QString("items.setGroups(2, 4, \"selected\")" ) |
3864 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "setGroups: invalid count" )) |
3865 | << 4; |
3866 | |
3867 | QTest::newRow(dataTag: "move from < 0" ) |
3868 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3869 | << QString("items.move(-2, 1, 1)" ) |
3870 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: from index out of range" )) |
3871 | << 4; |
3872 | |
3873 | QTest::newRow(dataTag: "move from == length" ) |
3874 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3875 | << QString("items.move(4, 1, 1)" ) |
3876 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: from index out of range" )) |
3877 | << 4; |
3878 | |
3879 | QTest::newRow(dataTag: "move from > length" ) |
3880 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3881 | << QString("items.move(9, 1, 1)" ) |
3882 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: from index out of range" )) |
3883 | << 4; |
3884 | |
3885 | QTest::newRow(dataTag: "move invalid from" ) |
3886 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3887 | << QString("items.move(\"nine\", 1, 1)" ) |
3888 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: invalid from index" )) |
3889 | << 4; |
3890 | |
3891 | QTest::newRow(dataTag: "move to < 0" ) |
3892 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3893 | << QString("items.move(1, -2, 1)" ) |
3894 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: to index out of range" )) |
3895 | << 4; |
3896 | |
3897 | QTest::newRow(dataTag: "move to == length" ) |
3898 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3899 | << QString("items.move(1, 4, 1)" ) |
3900 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: to index out of range" )) |
3901 | << 4; |
3902 | |
3903 | QTest::newRow(dataTag: "move to > length" ) |
3904 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3905 | << QString("items.move(1, 9, 1)" ) |
3906 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: to index out of range" )) |
3907 | << 4; |
3908 | |
3909 | QTest::newRow(dataTag: "move invalid to" ) |
3910 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3911 | << QString("items.move(1, \"nine\", 1)" ) |
3912 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: invalid to index" )) |
3913 | << 4; |
3914 | |
3915 | QTest::newRow(dataTag: "move count < 0" ) |
3916 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3917 | << QString("items.move(1, 1, -2)" ) |
3918 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: invalid count" )) |
3919 | << 4; |
3920 | |
3921 | QTest::newRow(dataTag: "move from + count > length" ) |
3922 | << testFileUrl(fileName: "listmodelproperties.qml" ) |
3923 | << QString("items.move(2, 1, 4)" ) |
3924 | << QRegularExpression(".*" + QQmlDelegateModelGroup::tr(s: "move: from index out of range" )) |
3925 | << 4; |
3926 | } |
3927 | |
3928 | void tst_qquickvisualdatamodel::warnings() |
3929 | { |
3930 | QFETCH(QUrl, source); |
3931 | QFETCH(QString, expression); |
3932 | QFETCH(QRegularExpression, warning); |
3933 | QFETCH(int, count); |
3934 | |
3935 | QQuickWindow window; |
3936 | |
3937 | QQmlComponent component(&engine); |
3938 | component.loadUrl(url: source); |
3939 | QScopedPointer<QObject> object(component.create()); |
3940 | QQuickListView *listView = qobject_cast<QQuickListView *>(object: object.data()); |
3941 | QVERIFY(listView); |
3942 | listView->setParentItem(window.contentItem()); |
3943 | |
3944 | QQuickItem *contentItem = listView->contentItem(); |
3945 | QVERIFY(contentItem); |
3946 | |
3947 | QObject *visualModel = evaluate<QObject *>(scope: listView, expression: "model" ); |
3948 | QVERIFY(visualModel); |
3949 | |
3950 | QTest::ignoreMessage(type: QtWarningMsg, messagePattern: warning); |
3951 | |
3952 | evaluate<void>(scope: visualModel, expression); |
3953 | QCOMPARE(evaluate<int>(listView, "count" ), count); |
3954 | } |
3955 | |
3956 | void tst_qquickvisualdatamodel::invalidAttachment() |
3957 | { |
3958 | QQmlComponent component(&engine); |
3959 | component.loadUrl(url: testFileUrl(fileName: "invalidAttachment.qml" )); |
3960 | |
3961 | QScopedPointer<QObject> object(component.create()); |
3962 | QVERIFY(object); |
3963 | QCOMPARE(component.errors().count(), 0); |
3964 | |
3965 | QVariant property = object->property(name: "invalidVdm" ); |
3966 | QCOMPARE(property.userType(), qMetaTypeId<QQmlDelegateModel *>()); |
3967 | QVERIFY(!property.value<QQmlDelegateModel *>()); |
3968 | |
3969 | QQuickItem *item = findItem<QQuickItem>(parent: static_cast<QQuickItem *>(object.data()), objectName: "delegate" ); |
3970 | QVERIFY(item); |
3971 | |
3972 | property = item->property(name: "validVdm" ); |
3973 | QCOMPARE(property.userType(), qMetaTypeId<QQmlDelegateModel *>()); |
3974 | QVERIFY(property.value<QQmlDelegateModel *>()); |
3975 | |
3976 | property = item->property(name: "invalidVdm" ); |
3977 | QCOMPARE(property.userType(), qMetaTypeId<QQmlDelegateModel *>()); |
3978 | QVERIFY(!property.value<QQmlDelegateModel *>()); |
3979 | } |
3980 | |
3981 | void tst_qquickvisualdatamodel::asynchronousInsert_data() |
3982 | { |
3983 | QTest::addColumn<int>(name: "requestIndex" ); |
3984 | QTest::addColumn<int>(name: "insertIndex" ); |
3985 | QTest::addColumn<int>(name: "insertCount" ); |
3986 | QTest::addColumn<int>(name: "completeIndex" ); |
3987 | |
3988 | QTest::newRow(dataTag: "insert before" ) << 4 << 1 << 3 << 7; |
3989 | QTest::newRow(dataTag: "insert after" ) << 4 << 6 << 3 << 4; |
3990 | QTest::newRow(dataTag: "insert at" ) << 4 << 4 << 3 << 7; |
3991 | } |
3992 | |
3993 | void tst_qquickvisualdatamodel::asynchronousInsert() |
3994 | { |
3995 | QFETCH(int, requestIndex); |
3996 | QFETCH(int, insertIndex); |
3997 | QFETCH(int, insertCount); |
3998 | QFETCH(int, completeIndex); |
3999 | |
4000 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4001 | |
4002 | QQmlComponent c(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
4003 | |
4004 | QaimModel model; |
4005 | for (int i = 0; i < 8; i++) |
4006 | model.addItem(name: "Original item" + QString::number(i), number: "" ); |
4007 | |
4008 | engine.rootContext()->setContextProperty("myModel" , &model); |
4009 | |
4010 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(object: c.create()); |
4011 | QVERIFY(visualModel); |
4012 | |
4013 | ItemRequester requester; |
4014 | connect(sender: visualModel, SIGNAL(initItem(int,QObject*)), receiver: &requester, SLOT(initItem(int,QObject*))); |
4015 | connect(sender: visualModel, SIGNAL(createdItem(int,QObject*)), receiver: &requester, SLOT(createdItem(int,QObject*))); |
4016 | connect(sender: visualModel, SIGNAL(destroyingItem(QObject*)), receiver: &requester, SLOT(destroyingItem(QObject*))); |
4017 | |
4018 | QQuickItem *item = qobject_cast<QQuickItem*>(object: visualModel->object(index: requestIndex, incubationMode: QQmlIncubator::Asynchronous)); |
4019 | QVERIFY(!item); |
4020 | |
4021 | QVERIFY(!requester.itemInitialized); |
4022 | QVERIFY(!requester.itemCreated); |
4023 | QVERIFY(!requester.itemDestroyed); |
4024 | |
4025 | QList<QPair<QString, QString> > newItems; |
4026 | for (int i = 0; i < insertCount; i++) |
4027 | newItems.append(t: qMakePair(x: QLatin1String("New item" ) + QString::number(i), y: QString(QLatin1String("" )))); |
4028 | model.insertItems(index: insertIndex, items: newItems); |
4029 | |
4030 | item = qobject_cast<QQuickItem*>(object: visualModel->object(index: completeIndex)); |
4031 | QVERIFY(item); |
4032 | |
4033 | QCOMPARE(requester.itemInitialized, item); |
4034 | QCOMPARE(requester.indexInitialized, completeIndex); |
4035 | QCOMPARE(requester.itemCreated, item); |
4036 | QCOMPARE(requester.indexCreated, completeIndex); |
4037 | QVERIFY(!requester.itemDestroyed); |
4038 | |
4039 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4040 | |
4041 | visualModel->release(object: item); |
4042 | |
4043 | QCOMPARE(requester.itemDestroyed, item); |
4044 | } |
4045 | |
4046 | void tst_qquickvisualdatamodel::asynchronousRemove_data() |
4047 | { |
4048 | QTest::addColumn<int>(name: "requestIndex" ); |
4049 | QTest::addColumn<int>(name: "removeIndex" ); |
4050 | QTest::addColumn<int>(name: "removeCount" ); |
4051 | QTest::addColumn<int>(name: "completeIndex" ); |
4052 | |
4053 | QTest::newRow(dataTag: "remove before" ) << 4 << 1 << 3 << 1; |
4054 | QTest::newRow(dataTag: "remove after" ) << 4 << 6 << 2 << 4; |
4055 | QTest::newRow(dataTag: "remove requested" ) << 4 << 4 << 3 << -1; |
4056 | } |
4057 | |
4058 | void tst_qquickvisualdatamodel::asynchronousRemove() |
4059 | { |
4060 | QFETCH(int, requestIndex); |
4061 | QFETCH(int, removeIndex); |
4062 | QFETCH(int, removeCount); |
4063 | QFETCH(int, completeIndex); |
4064 | |
4065 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4066 | |
4067 | QQmlComponent c(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
4068 | |
4069 | QaimModel model; |
4070 | for (int i = 0; i < 8; i++) |
4071 | model.addItem(name: "Original item" + QString::number(i), number: "" ); |
4072 | |
4073 | engine.rootContext()->setContextProperty("myModel" , &model); |
4074 | |
4075 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(object: c.create()); |
4076 | QVERIFY(visualModel); |
4077 | |
4078 | ItemRequester requester; |
4079 | connect(sender: visualModel, SIGNAL(initItem(int,QObject*)), receiver: &requester, SLOT(initItem(int,QObject*))); |
4080 | connect(sender: visualModel, SIGNAL(createdItem(int,QObject*)), receiver: &requester, SLOT(createdItem(int,QObject*))); |
4081 | connect(sender: visualModel, SIGNAL(destroyingItem(QObject*)), receiver: &requester, SLOT(destroyingItem(QObject*))); |
4082 | |
4083 | QQuickItem *item = qobject_cast<QQuickItem*>(object: visualModel->object(index: requestIndex, incubationMode: QQmlIncubator::Asynchronous)); |
4084 | QVERIFY(!item); |
4085 | |
4086 | QVERIFY(!requester.itemInitialized); |
4087 | QVERIFY(!requester.itemCreated); |
4088 | QVERIFY(!requester.itemDestroyed); |
4089 | |
4090 | model.removeItems(index: removeIndex, count: removeCount); |
4091 | |
4092 | if (completeIndex == -1) { |
4093 | QElapsedTimer timer; |
4094 | timer.start(); |
4095 | do { |
4096 | controller.incubateFor(msecs: 50); |
4097 | } while (timer.elapsed() < 1000 && controller.incubatingObjectCount() > 0); |
4098 | |
4099 | // The item was removed before incubation started. We should not have any item created. |
4100 | QVERIFY(!requester.itemInitialized); |
4101 | QVERIFY(!requester.itemCreated); |
4102 | QVERIFY(!requester.itemDestroyed); |
4103 | } else { |
4104 | item = qobject_cast<QQuickItem*>(object: visualModel->object(index: completeIndex)); |
4105 | QVERIFY(item); |
4106 | |
4107 | QCOMPARE(requester.itemInitialized, item); |
4108 | QCOMPARE(requester.indexInitialized, completeIndex); |
4109 | QCOMPARE(requester.itemCreated, item); |
4110 | QCOMPARE(requester.indexCreated, completeIndex); |
4111 | QVERIFY(!requester.itemDestroyed); |
4112 | |
4113 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4114 | |
4115 | visualModel->release(object: item); |
4116 | |
4117 | QCOMPARE(requester.itemDestroyed, item); |
4118 | } |
4119 | } |
4120 | |
4121 | void tst_qquickvisualdatamodel::asynchronousMove_data() |
4122 | { |
4123 | QTest::addColumn<int>(name: "requestIndex" ); |
4124 | QTest::addColumn<int>(name: "from" ); |
4125 | QTest::addColumn<int>(name: "to" ); |
4126 | QTest::addColumn<int>(name: "count" ); |
4127 | QTest::addColumn<int>(name: "completeIndex" ); |
4128 | |
4129 | QTest::newRow(dataTag: "move before" ) << 4 << 1 << 0 << 3 << 4; |
4130 | QTest::newRow(dataTag: "move after" ) << 4 << 6 << 5 << 2 << 4; |
4131 | QTest::newRow(dataTag: "move requested" ) << 4 << 4 << 3 << 2 << 3; |
4132 | QTest::newRow(dataTag: "move before to after" ) << 4 << 1 << 4 << 3 << 1; |
4133 | QTest::newRow(dataTag: "move after to before" ) << 4 << 6 << 2 << 2 << 6; |
4134 | } |
4135 | |
4136 | void tst_qquickvisualdatamodel::asynchronousMove() |
4137 | { |
4138 | QFETCH(int, requestIndex); |
4139 | QFETCH(int, from); |
4140 | QFETCH(int, to); |
4141 | QFETCH(int, count); |
4142 | QFETCH(int, completeIndex); |
4143 | |
4144 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4145 | |
4146 | QQmlComponent c(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
4147 | |
4148 | QaimModel model; |
4149 | for (int i = 0; i < 8; i++) |
4150 | model.addItem(name: "Original item" + QString::number(i), number: "" ); |
4151 | |
4152 | engine.rootContext()->setContextProperty("myModel" , &model); |
4153 | |
4154 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(object: c.create()); |
4155 | QVERIFY(visualModel); |
4156 | |
4157 | ItemRequester requester; |
4158 | connect(sender: visualModel, SIGNAL(initItem(int,QObject*)), receiver: &requester, SLOT(initItem(int,QObject*))); |
4159 | connect(sender: visualModel, SIGNAL(createdItem(int,QObject*)), receiver: &requester, SLOT(createdItem(int,QObject*))); |
4160 | connect(sender: visualModel, SIGNAL(destroyingItem(QObject*)), receiver: &requester, SLOT(destroyingItem(QObject*))); |
4161 | |
4162 | QQuickItem *item = qobject_cast<QQuickItem*>(object: visualModel->object(index: requestIndex, incubationMode: QQmlIncubator::Asynchronous)); |
4163 | QVERIFY(!item); |
4164 | |
4165 | QVERIFY(!requester.itemInitialized); |
4166 | QVERIFY(!requester.itemCreated); |
4167 | QVERIFY(!requester.itemDestroyed); |
4168 | |
4169 | model.moveItems(from, to, count); |
4170 | |
4171 | item = qobject_cast<QQuickItem*>(object: visualModel->object(index: completeIndex)); |
4172 | QVERIFY(item); |
4173 | |
4174 | |
4175 | QCOMPARE(requester.itemInitialized, item); |
4176 | QCOMPARE(requester.indexInitialized, completeIndex); |
4177 | QCOMPARE(requester.itemCreated, item); |
4178 | QCOMPARE(requester.indexCreated, completeIndex); |
4179 | QVERIFY(!requester.itemDestroyed); |
4180 | |
4181 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4182 | |
4183 | visualModel->release(object: item); |
4184 | |
4185 | QCOMPARE(requester.itemDestroyed, item); |
4186 | } |
4187 | |
4188 | void tst_qquickvisualdatamodel::asynchronousCancel() |
4189 | { |
4190 | const int requestIndex = 4; |
4191 | |
4192 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4193 | |
4194 | QQmlComponent c(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
4195 | |
4196 | QaimModel model; |
4197 | for (int i = 0; i < 8; i++) |
4198 | model.addItem(name: "Original item" + QString::number(i), number: "" ); |
4199 | |
4200 | engine.rootContext()->setContextProperty("myModel" , &model); |
4201 | |
4202 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(object: c.create()); |
4203 | QVERIFY(visualModel); |
4204 | |
4205 | QQuickItem *item = qobject_cast<QQuickItem*>(object: visualModel->object(index: requestIndex, incubationMode: QQmlIncubator::Asynchronous)); |
4206 | QVERIFY(!item); |
4207 | QCOMPARE(controller.incubatingObjectCount(), 1); |
4208 | |
4209 | visualModel->cancel(index: requestIndex); |
4210 | QCOMPARE(controller.incubatingObjectCount(), 0); |
4211 | } |
4212 | |
4213 | void tst_qquickvisualdatamodel::invalidContext() |
4214 | { |
4215 | QQmlEngine engine; |
4216 | QaimModel model; |
4217 | for (int i = 0; i < 8; i++) |
4218 | model.addItem(name: "Original item" + QString::number(i), number: "" ); |
4219 | |
4220 | engine.rootContext()->setContextProperty("myModel" , &model); |
4221 | |
4222 | QScopedPointer<QQmlContext> context(new QQmlContext(engine.rootContext())); |
4223 | |
4224 | QQmlComponent c(&engine, testFileUrl(fileName: "visualdatamodel.qml" )); |
4225 | |
4226 | |
4227 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(object: c.create(context: context.data())); |
4228 | QVERIFY(visualModel); |
4229 | |
4230 | QQuickItem *item = qobject_cast<QQuickItem*>(object: visualModel->object(index: 4)); |
4231 | QVERIFY(item); |
4232 | visualModel->release(object: item); |
4233 | |
4234 | delete context.take(); |
4235 | |
4236 | model.insertItem(index: 4, name: "new item" , number: "" ); |
4237 | |
4238 | item = qobject_cast<QQuickItem*>(object: visualModel->object(index: 4)); |
4239 | QVERIFY(!item); |
4240 | } |
4241 | |
4242 | class ObjectsProvider : public QObject |
4243 | { |
4244 | Q_OBJECT |
4245 | Q_PROPERTY(QQmlListProperty<QObject> objects READ objects NOTIFY objectsChanged) |
4246 | |
4247 | public: |
4248 | explicit ObjectsProvider(QObject *parent = nullptr) : QObject(parent) {} |
4249 | |
4250 | Q_INVOKABLE void rebuild() |
4251 | { |
4252 | for (auto old: m_objects) |
4253 | old->deleteLater(); |
4254 | |
4255 | m_objects.clear(); |
4256 | emit objectsChanged(); |
4257 | |
4258 | const int size = std::rand() & 0xff; |
4259 | for (int i = 0; i < size; ++i) { |
4260 | auto newElement = new QObject(this); |
4261 | QQmlEngine::setObjectOwnership(newElement, QQmlEngine::CppOwnership); |
4262 | m_objects.push_back(t: newElement); |
4263 | } |
4264 | emit objectsChanged(); |
4265 | } |
4266 | |
4267 | Q_INVOKABLE QQmlListProperty<QObject> objects() |
4268 | { |
4269 | return QQmlListProperty<QObject>(this, nullptr, &ObjectsProvider::listLength, |
4270 | &ObjectsProvider::listAt); |
4271 | } |
4272 | |
4273 | static int listLength(QQmlListProperty<QObject> *property) |
4274 | { |
4275 | auto objectsProvider = qobject_cast<ObjectsProvider*>(object: property->object); |
4276 | return objectsProvider ? objectsProvider->m_objects.length() : 0; |
4277 | } |
4278 | |
4279 | static QObject* listAt(QQmlListProperty<QObject> *property, int index) |
4280 | { |
4281 | auto objectsProvider = qobject_cast<ObjectsProvider*>(object: property->object); |
4282 | return objectsProvider ? objectsProvider->m_objects.at(i: index) : nullptr; |
4283 | } |
4284 | |
4285 | signals: |
4286 | void objectsChanged(); |
4287 | |
4288 | private: |
4289 | QList<QObject *> m_objects; |
4290 | }; |
4291 | |
4292 | void tst_qquickvisualdatamodel::externalManagedModel() |
4293 | { |
4294 | qmlRegisterType<ObjectsProvider>(uri: "example" , versionMajor: 1, versionMinor: 0, qmlName: "ObjectsProvider" ); |
4295 | |
4296 | QQmlEngine engine; |
4297 | QQmlComponent component(&engine, testFileUrl(fileName: "externalManagedModel.qml" )); |
4298 | QVERIFY(component.isReady()); |
4299 | |
4300 | QScopedPointer<QObject> object(component.create()); |
4301 | QVERIFY(!object.isNull()); |
4302 | |
4303 | QVERIFY(object->property("running" ).toBool()); |
4304 | |
4305 | // Make sure it runs to completion without crashing. |
4306 | QTRY_VERIFY(!object->property("running" ).toBool()); |
4307 | } |
4308 | |
4309 | void tst_qquickvisualdatamodel::delegateModelChangeDelegate() |
4310 | { |
4311 | // Verify that QTBUG-63477 is fixed. |
4312 | // Changing the delegate would not update existing items. |
4313 | QQmlEngine engine; |
4314 | QScopedPointer<QQmlContext> context(new QQmlContext(engine.rootContext())); |
4315 | |
4316 | QQmlComponent c(&engine); |
4317 | c.setData("import QtQml.Models 2.2\nDelegateModel {}\n" , baseUrl: QUrl()); |
4318 | QCOMPARE(c.status(), QQmlComponent::Ready); |
4319 | |
4320 | QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(object: c.create(context: context.data())); |
4321 | QVERIFY(visualModel); |
4322 | visualModel->setModel(QVariant(3)); |
4323 | |
4324 | QQmlComponent first(&engine); |
4325 | first.setData("import QtQuick 2.0\nItem { objectName: \"old\" }\n" , baseUrl: QUrl()); |
4326 | QCOMPARE(first.status(), QQmlComponent::Ready); |
4327 | |
4328 | // Without delegate, claim to have an item count of 0 |
4329 | QCOMPARE(visualModel->count(), 0); |
4330 | |
4331 | visualModel->setDelegate(&first); |
4332 | // The first delegate has been set, verify we get it |
4333 | QObject* old = visualModel->object(index: 0, incubationMode: QQmlIncubator::Synchronous); |
4334 | QVERIFY(old); |
4335 | QCOMPARE(visualModel->object(0, QQmlIncubator::Synchronous)->objectName(), QStringLiteral("old" )); |
4336 | QCOMPARE(visualModel->count(), 3); |
4337 | |
4338 | QQmlComponent second(&engine); |
4339 | second.setData("import QtQuick 2.0\nItem { objectName: \"new\" }\n" , baseUrl: QUrl()); |
4340 | QCOMPARE(second.status(), QQmlComponent::Ready); |
4341 | |
4342 | visualModel->setDelegate(&second); |
4343 | // After changing the delegate, expect the existing item to have the new delegate |
4344 | QCOMPARE(visualModel->object(0, QQmlIncubator::Synchronous)->objectName(), QStringLiteral("new" )); |
4345 | QCOMPARE(visualModel->count(), 3); |
4346 | } |
4347 | |
4348 | void tst_qquickvisualdatamodel::checkFilterGroupForDelegate() |
4349 | { |
4350 | QQuickView view; |
4351 | view.setSource(testFileUrl(fileName: "filterGroupForDelegate.qml" )); |
4352 | view.show(); |
4353 | |
4354 | QQuickItem *obj = view.rootObject(); |
4355 | QVERIFY(obj); |
4356 | |
4357 | QTRY_VERIFY(obj->property("numChanges" ).toInt() > 100); |
4358 | QVERIFY(obj->property("ok" ).toBool()); |
4359 | } |
4360 | |
4361 | void tst_qquickvisualdatamodel::readFromProxyObject() |
4362 | { |
4363 | QQmlEngine engine; |
4364 | QQmlComponent component(&engine, testFileUrl(fileName: "readFromProxyObject.qml" )); |
4365 | |
4366 | QScopedPointer<QObject> obj(component.create()); |
4367 | QVERIFY(obj); |
4368 | |
4369 | auto *window = qobject_cast<QQuickWindow *>(object: obj.get()); |
4370 | QVERIFY(window); |
4371 | |
4372 | QCOMPARE(window->property("name" ).type(), QMetaType::QString); |
4373 | QTRY_VERIFY(window->property("name" ).toString() != QLatin1String("wrong" )); |
4374 | } |
4375 | |
4376 | QTEST_MAIN(tst_qquickvisualdatamodel) |
4377 | |
4378 | #include "tst_qquickvisualdatamodel.moc" |
4379 | |