~saviq/ubuntu/saucy/qtdeclarative-opensource-src/add-qtquick-delegate-range

« back to all changes in this revision

Viewing changes to tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 14:17:19 UTC
  • Revision ID: package-import@ubuntu.com-20130205141719-qqeyml8wslpyez52
Tags: upstream-5.0.1
ImportĀ upstreamĀ versionĀ 5.0.1

Show diffs side-by-side

added added

removed removed

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