1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the test suite of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
43
#include <QtTest/QtTest>
44
#include <qabstractproxymodel.h>
45
#include <QItemSelection>
46
#include <qstandarditemmodel.h>
47
48
class tst_QAbstractProxyModel : public QObject
49
{
50
    Q_OBJECT
51
52
public slots:
53
    void initTestCase();
54
    void cleanupTestCase();
55
    void init();
56
    void cleanup();
57
58
private slots:
59
    void qabstractproxymodel_data();
60
    void qabstractproxymodel();
61
    void data_data();
62
    void data();
63
    void flags_data();
64
    void flags();
65
    void headerData_data();
66
    void headerData();
67
    void itemData_data();
68
    void itemData();
69
    void mapFromSource_data();
70
    void mapFromSource();
71
    void mapSelectionFromSource_data();
72
    void mapSelectionFromSource();
73
    void mapSelectionToSource_data();
74
    void mapSelectionToSource();
75
    void mapToSource_data();
76
    void mapToSource();
77
    void revert_data();
78
    void revert();
79
    void setSourceModel_data();
80
    void setSourceModel();
81
    void submit_data();
82
    void submit();
83
    void testRoleNames();
84
};
85
86
// Subclass that exposes the protected functions.
87
class SubQAbstractProxyModel : public QAbstractProxyModel
88
{
89
public:
90
    // QAbstractProxyModel::mapFromSource is a pure virtual function.
91
    QModelIndex mapFromSource(QModelIndex const& sourceIndex) const
92
        { Q_UNUSED(sourceIndex); return QModelIndex(); }
93
94
    // QAbstractProxyModel::mapToSource is a pure virtual function.
95
    QModelIndex mapToSource(QModelIndex const& proxyIndex) const
96
        { Q_UNUSED(proxyIndex); return QModelIndex(); }
97
98
    QModelIndex index(int, int, const QModelIndex&) const
99
    {
100
        return QModelIndex();
101
    }
102
103
    QModelIndex parent(const QModelIndex&) const
104
    {
105
        return QModelIndex();
106
    }
107
108
    int rowCount(const QModelIndex&) const
109
    {
110
        return 0;
111
    }
112
113
    int columnCount(const QModelIndex&) const
114
    {
115
        return 0;
116
    }
117
};
118
119
// This will be called before the first test function is executed.
120
// It is only called once.
121
void tst_QAbstractProxyModel::initTestCase()
122
{
123
}
124
125
// This will be called after the last test function is executed.
126
// It is only called once.
127
void tst_QAbstractProxyModel::cleanupTestCase()
128
{
129
}
130
131
// This will be called before each test function is executed.
132
void tst_QAbstractProxyModel::init()
133
{
134
}
135
136
// This will be called after every test function.
137
void tst_QAbstractProxyModel::cleanup()
138
{
139
}
140
141
void tst_QAbstractProxyModel::qabstractproxymodel_data()
142
{
143
}
144
145
void tst_QAbstractProxyModel::qabstractproxymodel()
146
{
147
    SubQAbstractProxyModel model;
148
    model.data(QModelIndex());
149
    model.flags(QModelIndex());
150
    model.headerData(0, Qt::Vertical, 0);
151
    model.itemData(QModelIndex());
152
    model.mapFromSource(QModelIndex());
153
    model.mapSelectionFromSource(QItemSelection());
154
    model.mapSelectionToSource(QItemSelection());
155
    model.mapToSource(QModelIndex());
156
    model.revert();
157
    model.setSourceModel(0);
158
    QCOMPARE(model.sourceModel(), (QAbstractItemModel*)0);
159
    model.submit();
160
}
161
162
Q_DECLARE_METATYPE(QVariant)
163
Q_DECLARE_METATYPE(QModelIndex)
164
void tst_QAbstractProxyModel::data_data()
165
{
166
    QTest::addColumn<QModelIndex>("proxyIndex");
167
    QTest::addColumn<int>("role");
168
    QTest::addColumn<QVariant>("data");
169
    QTest::newRow("null") << QModelIndex() << 0 << QVariant();
170
}
171
172
// public QVariant data(QModelIndex const& proxyIndex, int role = Qt::DisplayRole) const
173
void tst_QAbstractProxyModel::data()
174
{
175
    QFETCH(QModelIndex, proxyIndex);
176
    QFETCH(int, role);
177
    QFETCH(QVariant, data);
178
179
    SubQAbstractProxyModel model;
180
    QCOMPARE(model.data(proxyIndex, role), data);
181
}
182
183
Q_DECLARE_METATYPE(Qt::ItemFlags)
184
void tst_QAbstractProxyModel::flags_data()
185
{
186
    QTest::addColumn<QModelIndex>("index");
187
    QTest::addColumn<Qt::ItemFlags>("flags");
188
    QTest::newRow("null") << QModelIndex() << (Qt::ItemFlags)0;
189
}
190
191
// public Qt::ItemFlags flags(QModelIndex const& index) const
192
void tst_QAbstractProxyModel::flags()
193
{
194
    QFETCH(QModelIndex, index);
195
    QFETCH(Qt::ItemFlags, flags);
196
197
    SubQAbstractProxyModel model;
198
    QCOMPARE(model.flags(index), flags);
199
}
200
201
Q_DECLARE_METATYPE(Qt::Orientation)
202
Q_DECLARE_METATYPE(Qt::ItemDataRole)
203
void tst_QAbstractProxyModel::headerData_data()
204
{
205
    QTest::addColumn<int>("section");
206
    QTest::addColumn<Qt::Orientation>("orientation");
207
    QTest::addColumn<Qt::ItemDataRole>("role");
208
    QTest::addColumn<QVariant>("headerData");
209
    QTest::newRow("null") << 0 << Qt::Vertical << Qt::UserRole << QVariant();
210
}
211
212
// public QVariant headerData(int section, Qt::Orientation orientation, int role) const
213
void tst_QAbstractProxyModel::headerData()
214
{
215
    QFETCH(int, section);
216
    QFETCH(Qt::Orientation, orientation);
217
    QFETCH(Qt::ItemDataRole, role);
218
    QFETCH(QVariant, headerData);
219
220
    SubQAbstractProxyModel model;
221
    QCOMPARE(model.headerData(section, orientation, role), headerData);
222
}
223
224
void tst_QAbstractProxyModel::itemData_data()
225
{
226
    QTest::addColumn<QModelIndex>("index");
227
    QTest::addColumn<int>("count");
228
229
    QTest::newRow("null") << QModelIndex() << 0;
230
}
231
232
// public QMap<int,QVariant> itemData(QModelIndex const& index) const
233
void tst_QAbstractProxyModel::itemData()
234
{
235
    QFETCH(QModelIndex, index);
236
    QFETCH(int, count);
237
    SubQAbstractProxyModel model;
238
    QCOMPARE(model.itemData(index).count(), count);
239
}
240
241
void tst_QAbstractProxyModel::mapFromSource_data()
242
{
243
    QTest::addColumn<QModelIndex>("sourceIndex");
244
    QTest::addColumn<QModelIndex>("mapFromSource");
245
    QTest::newRow("null") << QModelIndex() << QModelIndex();
246
}
247
248
// public QModelIndex mapFromSource(QModelIndex const& sourceIndex) const
249
void tst_QAbstractProxyModel::mapFromSource()
250
{
251
    QFETCH(QModelIndex, sourceIndex);
252
    QFETCH(QModelIndex, mapFromSource);
253
254
    SubQAbstractProxyModel model;
255
    QCOMPARE(model.mapFromSource(sourceIndex), mapFromSource);
256
}
257
258
Q_DECLARE_METATYPE(QItemSelection)
259
void tst_QAbstractProxyModel::mapSelectionFromSource_data()
260
{
261
    QTest::addColumn<QItemSelection>("selection");
262
    QTest::addColumn<QItemSelection>("mapSelectionFromSource");
263
    QTest::newRow("null") << QItemSelection() << QItemSelection();
264
    QTest::newRow("empty") << QItemSelection(QModelIndex(), QModelIndex()) << QItemSelection(QModelIndex(), QModelIndex());
265
}
266
267
// public QItemSelection mapSelectionFromSource(QItemSelection const& selection) const
268
void tst_QAbstractProxyModel::mapSelectionFromSource()
269
{
270
    QFETCH(QItemSelection, selection);
271
    QFETCH(QItemSelection, mapSelectionFromSource);
272
273
    SubQAbstractProxyModel model;
274
    QCOMPARE(model.mapSelectionFromSource(selection), mapSelectionFromSource);
275
}
276
277
void tst_QAbstractProxyModel::mapSelectionToSource_data()
278
{
279
    QTest::addColumn<QItemSelection>("selection");
280
    QTest::addColumn<QItemSelection>("mapSelectionToSource");
281
    QTest::newRow("null") << QItemSelection() << QItemSelection();
282
    QTest::newRow("empty") << QItemSelection(QModelIndex(), QModelIndex()) << QItemSelection(QModelIndex(), QModelIndex());
283
}
284
285
// public QItemSelection mapSelectionToSource(QItemSelection const& selection) const
286
void tst_QAbstractProxyModel::mapSelectionToSource()
287
{
288
    QFETCH(QItemSelection, selection);
289
    QFETCH(QItemSelection, mapSelectionToSource);
290
291
    SubQAbstractProxyModel model;
292
    QCOMPARE(model.mapSelectionToSource(selection), mapSelectionToSource);
293
}
294
295
void tst_QAbstractProxyModel::mapToSource_data()
296
{
297
    QTest::addColumn<QModelIndex>("proxyIndex");
298
    QTest::addColumn<QModelIndex>("mapToSource");
299
    QTest::newRow("null") << QModelIndex() << QModelIndex();
300
}
301
302
// public QModelIndex mapToSource(QModelIndex const& proxyIndex) const
303
void tst_QAbstractProxyModel::mapToSource()
304
{
305
    QFETCH(QModelIndex, proxyIndex);
306
    QFETCH(QModelIndex, mapToSource);
307
308
    SubQAbstractProxyModel model;
309
    QCOMPARE(model.mapToSource(proxyIndex), mapToSource);
310
}
311
312
void tst_QAbstractProxyModel::revert_data()
313
{
314
    //QTest::addColumn<int>("foo");
315
    //QTest::newRow("null") << 0;
316
}
317
318
// public void revert()
319
void tst_QAbstractProxyModel::revert()
320
{
321
    //QFETCH(int, foo);
322
323
    SubQAbstractProxyModel model;
324
    model.revert();
325
}
326
327
void tst_QAbstractProxyModel::setSourceModel_data()
328
{
329
    //QTest::addColumn<int>("sourceModelCount");
330
    //QTest::newRow("null") << 0;
331
}
332
333
// public void setSourceModel(QAbstractItemModel* sourceModel)
334
void tst_QAbstractProxyModel::setSourceModel()
335
{
336
    //QFETCH(int, sourceModelCount);
337
338
    SubQAbstractProxyModel model;
339
    QStandardItemModel *sourceModel = new QStandardItemModel(&model);
340
    model.setSourceModel(sourceModel);
341
    QCOMPARE(model.sourceModel(), static_cast<QAbstractItemModel*>(sourceModel));
342
343
    QStandardItemModel *sourceModel2 = new QStandardItemModel(&model);
344
    model.setSourceModel(sourceModel2);
345
    QCOMPARE(model.sourceModel(), static_cast<QAbstractItemModel*>(sourceModel2));
346
347
    delete sourceModel2;
348
    QCOMPARE(model.sourceModel(), static_cast<QAbstractItemModel*>(0));
349
}
350
351
void tst_QAbstractProxyModel::submit_data()
352
{
353
    QTest::addColumn<bool>("submit");
354
    QTest::newRow("null") << true;
355
}
356
357
// public bool submit()
358
void tst_QAbstractProxyModel::submit()
359
{
360
    QFETCH(bool, submit);
361
362
    SubQAbstractProxyModel model;
363
    QCOMPARE(model.submit(), submit);
364
}
365
366
class StandardItemModelWithCustomRoleNames : public QStandardItemModel
367
{
368
public:
369
    enum CustomRole {
370
        CustomRole1 = Qt::UserRole,
371
        CustomRole2
372
    };
373
374
    StandardItemModelWithCustomRoleNames() {
375
        QHash<int, QByteArray> _roleNames = roleNames();
376
        _roleNames.insert(CustomRole1, "custom1");
377
        _roleNames.insert(CustomRole2, "custom2");
378
        setRoleNames(_roleNames);
379
    }
380
};
381
382
class AnotherStandardItemModelWithCustomRoleNames : public QStandardItemModel
383
{
384
    public:
385
        enum CustomRole {
386
            AnotherCustomRole1 = Qt::UserRole + 10,  // Different to StandardItemModelWithCustomRoleNames::CustomRole1
387
            AnotherCustomRole2
388
        };
389
390
        AnotherStandardItemModelWithCustomRoleNames() {
391
            QHash<int, QByteArray> _roleNames = roleNames();
392
            _roleNames.insert(AnotherCustomRole1, "another_custom1");
393
            _roleNames.insert(AnotherCustomRole2, "another_custom2");
394
            setRoleNames(_roleNames);
395
        }
396
};
397
398
/**
399
    Verifies that @p subSet is a subset of @p superSet. That is, all keys in @p subSet exist in @p superSet and have the same values.
400
*/
401
static void verifySubSetOf(const QHash<int, QByteArray> &superSet, const QHash<int, QByteArray> &subSet)
402
{
403
    QHash<int, QByteArray>::const_iterator it = subSet.constBegin();
404
    const QHash<int, QByteArray>::const_iterator end = subSet.constEnd();
405
    for ( ; it != end; ++it ) {
406
        QVERIFY(superSet.contains(it.key()));
407
        QVERIFY(it.value() == superSet.value(it.key()));
408
    }
409
}
410
411
void tst_QAbstractProxyModel::testRoleNames()
412
{
413
    QStandardItemModel defaultModel;
414
    StandardItemModelWithCustomRoleNames model;
415
    QHash<int, QByteArray> rootModelRoleNames = model.roleNames();
416
    QHash<int, QByteArray> defaultModelRoleNames = defaultModel.roleNames();
417
418
    verifySubSetOf( rootModelRoleNames, defaultModelRoleNames);
419
    QVERIFY( rootModelRoleNames.size() == defaultModelRoleNames.size() + 2 );
420
    QVERIFY( rootModelRoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole1));
421
    QVERIFY( rootModelRoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole2));
422
    QVERIFY( rootModelRoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole1) == "custom1" );
423
    QVERIFY( rootModelRoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole2) == "custom2" );
424
425
    SubQAbstractProxyModel proxy1;
426
    proxy1.setSourceModel(&model);
427
    QHash<int, QByteArray> proxy1RoleNames = proxy1.roleNames();
428
    verifySubSetOf( proxy1RoleNames, defaultModelRoleNames );
429
    QVERIFY( proxy1RoleNames.size() == defaultModelRoleNames.size() + 2 );
430
    QVERIFY( proxy1RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole1));
431
    QVERIFY( proxy1RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole2));
432
    QVERIFY( proxy1RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole1) == "custom1" );
433
    QVERIFY( proxy1RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole2) == "custom2" );
434
435
    SubQAbstractProxyModel proxy2;
436
    proxy2.setSourceModel(&proxy1);
437
    QHash<int, QByteArray> proxy2RoleNames = proxy2.roleNames();
438
    verifySubSetOf( proxy2RoleNames, defaultModelRoleNames );
439
    QVERIFY( proxy2RoleNames.size() == defaultModelRoleNames.size() + 2 );
440
    QVERIFY( proxy2RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole1));
441
    QVERIFY( proxy2RoleNames.contains(StandardItemModelWithCustomRoleNames::CustomRole2));
442
    QVERIFY( proxy2RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole1) == "custom1" );
443
    QVERIFY( proxy2RoleNames.value(StandardItemModelWithCustomRoleNames::CustomRole2) == "custom2" );
444
445
}
446
447
QTEST_MAIN(tst_QAbstractProxyModel)
448
#include "tst_qabstractproxymodel.moc"