~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

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
 
 
42
 
 
43
#include <QtTest/QtTest>
 
44
#include <QtCore/QCoreApplication>
 
45
#include <QtSql/QtSql>
 
46
#include <QtWidgets/QtWidgets>
 
47
#include <QtCore/QSortFilterProxyModel>
 
48
 
 
49
/*
 
50
    To add a model to be tested add the header file to the includes
 
51
    and impliment what is needed in the four functions below.
 
52
 
 
53
    You can add more then one model, several Qt models and included as examples.
 
54
 
 
55
    In tst_qitemmodel.cpp a new ModelsToTest object is created for each test.
 
56
 
 
57
    When you have errors fix the first ones first.  Later tests depend upon them working
 
58
*/
 
59
 
 
60
class ModelsToTest {
 
61
 
 
62
public:
 
63
    ModelsToTest();
 
64
 
 
65
    QAbstractItemModel *createModel(const QString &modelType);
 
66
    QModelIndex populateTestArea(QAbstractItemModel *model);
 
67
    void cleanupTestArea(QAbstractItemModel *model);
 
68
 
 
69
    enum Read {
 
70
        ReadOnly, // wont perform remove(), insert(), and setData()
 
71
        ReadWrite
 
72
    };
 
73
    enum Contains {
 
74
        Empty,  // Confirm that rowCount() == 0 etc throughout the test
 
75
        HasData // Confirm that rowCount() != 0 etc throughout the test
 
76
    };
 
77
 
 
78
    struct test {
 
79
            test(QString m, Read r, Contains c) : modelType(m), read(r), contains(c){};
 
80
 
 
81
            QString modelType;
 
82
            Read read;
 
83
            Contains contains;
 
84
    };
 
85
 
 
86
    QList<test> tests;
 
87
 
 
88
    static void setupDatabase();
 
89
};
 
90
 
 
91
 
 
92
/*!
 
93
    Add new tests, they can be the same model, but in a different state.
 
94
 
 
95
    The name of the model is passed to createModel
 
96
    If readOnly is true the remove tests will be skipped.  Example: QDirModel is disabled.
 
97
    If createModel returns an empty model.  Example: QDirModel does not
 
98
 */
 
99
ModelsToTest::ModelsToTest()
 
100
{
 
101
    setupDatabase();
 
102
 
 
103
    tests.append(test("QDirModel", ReadOnly, HasData));
 
104
    tests.append(test("QStringListModel", ReadWrite, HasData));
 
105
    tests.append(test("QStringListModelEmpty", ReadWrite, Empty));
 
106
 
 
107
    tests.append(test("QStandardItemModel", ReadWrite, HasData));
 
108
    tests.append(test("QStandardItemModelEmpty", ReadWrite, Empty));
 
109
 
 
110
    // QSortFilterProxyModel test uses QStandardItemModel so test it first
 
111
    tests.append(test("QSortFilterProxyModel", ReadWrite, HasData));
 
112
    tests.append(test("QSortFilterProxyModelEmpty", ReadWrite, Empty));
 
113
    tests.append(test("QSortFilterProxyModelRegExp", ReadWrite, HasData));
 
114
 
 
115
    tests.append(test("QListModel", ReadWrite, HasData));
 
116
    tests.append(test("QListModelEmpty", ReadWrite, Empty));
 
117
    tests.append(test("QTableModel", ReadWrite, HasData));
 
118
    tests.append(test("QTableModelEmpty", ReadWrite, Empty));
 
119
 
 
120
    tests.append(test("QTreeModel", ReadWrite, HasData));
 
121
    tests.append(test("QTreeModelEmpty", ReadWrite, Empty));
 
122
 
 
123
    tests.append(test("QSqlQueryModel", ReadOnly, HasData));
 
124
    tests.append(test("QSqlQueryModelEmpty", ReadOnly, Empty));
 
125
 
 
126
    // Fails on remove
 
127
    tests.append(test("QSqlTableModel", ReadOnly, HasData));
 
128
}
 
129
 
 
130
/*!
 
131
    Return a new modelType.
 
132
 */
 
133
QAbstractItemModel *ModelsToTest::createModel(const QString &modelType)
 
134
{
 
135
    if (modelType == "QStringListModelEmpty")
 
136
        return new QStringListModel();
 
137
 
 
138
    if (modelType == "QStringListModel") {
 
139
        QStringListModel *model = new QStringListModel();
 
140
        populateTestArea(model);
 
141
        return model;
 
142
    }
 
143
 
 
144
    if (modelType == "QStandardItemModelEmpty") {
 
145
        return new QStandardItemModel();
 
146
    }
 
147
 
 
148
    if (modelType == "QStandardItemModel") {
 
149
        QStandardItemModel *model = new QStandardItemModel();
 
150
        populateTestArea(model);
 
151
        return model;
 
152
    }
 
153
 
 
154
    if (modelType == "QSortFilterProxyModelEmpty") {
 
155
        QSortFilterProxyModel *model = new QSortFilterProxyModel;
 
156
        QStandardItemModel *standardItemModel = new QStandardItemModel;
 
157
        model->setSourceModel(standardItemModel);
 
158
        return model;
 
159
    }
 
160
 
 
161
    if (modelType == "QSortFilterProxyModelRegExp") {
 
162
        QSortFilterProxyModel *model = new QSortFilterProxyModel;
 
163
        QStandardItemModel *standardItemModel = new QStandardItemModel;
 
164
        model->setSourceModel(standardItemModel);
 
165
        populateTestArea(model);
 
166
        model->setFilterRegExp(QRegExp("(^$|I.*)"));
 
167
        return model;
 
168
    }
 
169
 
 
170
    if (modelType == "QSortFilterProxyModel") {
 
171
        QSortFilterProxyModel *model = new QSortFilterProxyModel;
 
172
        QStandardItemModel *standardItemModel = new QStandardItemModel;
 
173
        model->setSourceModel(standardItemModel);
 
174
        populateTestArea(model);
 
175
        return model;
 
176
    }
 
177
 
 
178
    if (modelType == "QDirModel") {
 
179
        QDirModel *model = new QDirModel();
 
180
        model->setReadOnly(false);
 
181
        return model;
 
182
    }
 
183
 
 
184
    if (modelType == "QSqlQueryModel") {
 
185
        QSqlQueryModel *model = new QSqlQueryModel();
 
186
        populateTestArea(model);
 
187
        return model;
 
188
    }
 
189
 
 
190
    if (modelType == "QSqlQueryModelEmpty") {
 
191
        QSqlQueryModel *model = new QSqlQueryModel();
 
192
        return model;
 
193
    }
 
194
 
 
195
    if (modelType == "QSqlTableModel") {
 
196
        QSqlTableModel *model = new QSqlTableModel();
 
197
        populateTestArea(model);
 
198
        return model;
 
199
    }
 
200
 
 
201
    if (modelType == "QListModelEmpty")
 
202
        return (new QListWidget)->model();
 
203
 
 
204
    if (modelType == "QListModel") {
 
205
        QListWidget *widget = new QListWidget;
 
206
        populateTestArea(widget->model());
 
207
        return widget->model();
 
208
    }
 
209
 
 
210
    if (modelType == "QTableModelEmpty")
 
211
        return (new QTableWidget)->model();
 
212
 
 
213
    if (modelType == "QTableModel") {
 
214
        QTableWidget *widget = new QTableWidget;
 
215
        populateTestArea(widget->model());
 
216
        return widget->model();
 
217
    }
 
218
 
 
219
    if (modelType == "QTreeModelEmpty") {
 
220
        QTreeWidget *widget = new QTreeWidget;
 
221
        return widget->model();
 
222
    }
 
223
 
 
224
    if (modelType == "QTreeModel") {
 
225
        QTreeWidget *widget = new QTreeWidget;
 
226
        populateTestArea(widget->model());
 
227
        return widget->model();
 
228
    }
 
229
 
 
230
    return 0;
 
231
}
 
232
 
 
233
/*!
 
234
    Fills model with some test data at least twenty rows and if possible twenty or more columns.
 
235
    Return the parent of a row/column that can be tested.
 
236
 
 
237
    NOTE: If readOnly is true tests will try to remove and add rows and columns.
 
238
    If you have a tree model returning not the root index will help catch more errors.
 
239
 */
 
240
QModelIndex ModelsToTest::populateTestArea(QAbstractItemModel *model)
 
241
{
 
242
    if (QStringListModel *stringListModel = qobject_cast<QStringListModel *>(model)) {
 
243
        QString alphabet = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
 
244
        stringListModel->setStringList( alphabet.split(",") );
 
245
        return QModelIndex();
 
246
    }
 
247
 
 
248
    if (qobject_cast<QStandardItemModel *>(model)) {
 
249
        // Basic tree StandardItemModel
 
250
        QModelIndex parent;
 
251
        QVariant blue = QVariant(QColor(Qt::blue));
 
252
#ifndef Q_OS_WINCE
 
253
        for (int i = 0; i < 4; ++i) {
 
254
#else
 
255
        for (int i = 0; i < 2; ++i) {
 
256
#endif
 
257
            parent = model->index(0, 0, parent);
 
258
            model->insertRows(0, 26 + i, parent);
 
259
#ifndef Q_OS_WINCE
 
260
            model->insertColumns(0, 26 + i, parent);
 
261
#else
 
262
            model->insertColumns(0, 4 + i, parent);
 
263
#endif
 
264
            // Fill in some values to make it easier to debug
 
265
            /*
 
266
            for (int x = 0; x < 26 + i; ++x) {
 
267
                QString xval = QString::number(x);
 
268
                for (int y = 0; y < 26 + i; ++y) {
 
269
                    QString val = xval + QString::number(y) + QString::number(i);
 
270
                    QModelIndex index = model->index(x, y, parent);
 
271
                    model->setData(index, val);
 
272
                    model->setData(index, blue, Qt::TextColorRole);
 
273
                }
 
274
            }
 
275
            */
 
276
        }
 
277
        return model->index(0,0);
 
278
    }
 
279
 
 
280
    if (qobject_cast<QSortFilterProxyModel *>(model)) {
 
281
        QAbstractItemModel *realModel = (qobject_cast<QSortFilterProxyModel *>(model))->sourceModel();
 
282
        // Basic tree StandardItemModel
 
283
        QModelIndex parent;
 
284
        QVariant blue = QVariant(QColor(Qt::blue));
 
285
#ifndef Q_OS_WINCE
 
286
        for (int i = 0; i < 4; ++i) {
 
287
#else
 
288
        for (int i = 0; i < 2; ++i) {
 
289
#endif
 
290
            parent = realModel->index(0, 0, parent);
 
291
            realModel->insertRows(0, 26+i, parent);
 
292
#ifndef Q_OS_WINCE
 
293
            realModel->insertColumns(0, 26+i, parent);
 
294
#else
 
295
            realModel->insertColumns(0, 4, parent);
 
296
#endif
 
297
            // Fill in some values to make it easier to debug
 
298
            /*
 
299
            for (int x = 0; x < 26+i; ++x) {
 
300
                QString xval = QString::number(x);
 
301
                for (int y = 0; y < 26 + i; ++y) {
 
302
                    QString val = xval + QString::number(y) + QString::number(i);
 
303
                    QModelIndex index = realModel->index(x, y, parent);
 
304
                    realModel->setData(index, val);
 
305
                    realModel->setData(index, blue, Qt::TextColorRole);
 
306
                }
 
307
            }
 
308
            */
 
309
        }
 
310
        QModelIndex returnIndex = model->index(0,0);
 
311
        if (!returnIndex.isValid())
 
312
            qFatal("%s: model index to be returned is invalid", Q_FUNC_INFO);
 
313
        return returnIndex;
 
314
    }
 
315
 
 
316
    if (QDirModel *dirModel = qobject_cast<QDirModel *>(model)) {
 
317
        if (!QDir::current().mkdir("test"))
 
318
            qFatal("%s: cannot create directory %s",
 
319
                   Q_FUNC_INFO,
 
320
                   qPrintable(QDir::toNativeSeparators(QDir::currentPath()+"/test")));
 
321
        for (int i = 0; i < 26; ++i) {
 
322
            QString subdir = QString("test/foo_%1").arg(i);
 
323
            if (!QDir::current().mkdir(subdir))
 
324
                qFatal("%s: cannot create directory %s",
 
325
                       Q_FUNC_INFO,
 
326
                       qPrintable(QDir::toNativeSeparators(QDir::currentPath()+"/"+subdir)));
 
327
        }
 
328
        return dirModel->index(QDir::currentPath()+"/test");
 
329
    }
 
330
 
 
331
    if (QSqlQueryModel *queryModel = qobject_cast<QSqlQueryModel *>(model)) {
 
332
        QSqlQuery q;
 
333
        q.exec("CREATE TABLE test(id int primary key, name varchar(30))");
 
334
        q.prepare("INSERT INTO test(id, name) values (?, ?)");
 
335
#ifndef Q_OS_WINCE
 
336
        for (int i = 0; i < 1024; ++i) {
 
337
#else
 
338
        for (int i = 0; i < 512; ++i) {
 
339
#endif
 
340
            q.addBindValue(i);
 
341
            q.addBindValue("Mr. Smith" + QString::number(i));
 
342
            q.exec();
 
343
        }
 
344
        if (QSqlTableModel *tableModel = qobject_cast<QSqlTableModel *>(model)) {
 
345
            tableModel->setTable("test");
 
346
            tableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
 
347
            tableModel->select();
 
348
        } else {
 
349
            queryModel->setQuery("select * from test");
 
350
        }
 
351
        return QModelIndex();
 
352
    }
 
353
 
 
354
    if (QListWidget *listWidget = qobject_cast<QListWidget *>(model->parent())) {
 
355
#ifndef Q_OS_WINCE
 
356
        int items = 100;
 
357
#else
 
358
        int items = 50;
 
359
#endif
 
360
        while (items--)
 
361
            listWidget->addItem(QString("item %1").arg(items));
 
362
        return QModelIndex();
 
363
    }
 
364
 
 
365
    if (QTableWidget *tableWidget = qobject_cast<QTableWidget *>(model->parent())) {
 
366
        tableWidget->setColumnCount(20);
 
367
        tableWidget->setRowCount(20);
 
368
        return QModelIndex();
 
369
    }
 
370
 
 
371
    if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(model->parent())) {
 
372
        int topItems = 20;
 
373
        treeWidget->setColumnCount(1);
 
374
        QTreeWidgetItem *parent;
 
375
        while (topItems--){
 
376
            parent = new QTreeWidgetItem(treeWidget, QStringList(QString("top %1").arg(topItems)));
 
377
            for (int i = 0; i < 20; ++i)
 
378
                new QTreeWidgetItem(parent, QStringList(QString("child %1").arg(topItems)));
 
379
        }
 
380
        return QModelIndex();
 
381
    }
 
382
 
 
383
    qFatal("%s: unknown type of model", Q_FUNC_INFO);
 
384
    return QModelIndex();
 
385
}
 
386
 
 
387
/*!
 
388
    If you need to cleanup from populateTest() do it here.
 
389
    Note that this is called after every test even if populateTestArea isn't called.
 
390
 */
 
391
void ModelsToTest::cleanupTestArea(QAbstractItemModel *model)
 
392
{
 
393
    if (qobject_cast<QDirModel *>(model))
 
394
    {
 
395
        if (QDir(QDir::currentPath()+"/test").exists())
 
396
        {
 
397
            for (int i = 0; i < 26; ++i) {
 
398
                QString subdir(QString("test/foo_%1").arg(i));
 
399
                if (!QDir::current().rmdir(subdir))
 
400
                    qFatal("%s: cannot remove directory %s",
 
401
                           Q_FUNC_INFO,
 
402
                           qPrintable(QDir::toNativeSeparators(QDir::currentPath()+"/"+subdir)));
 
403
            }
 
404
            if (!QDir::current().rmdir("test"))
 
405
                qFatal("%s: cannot remove directory %s",
 
406
                       Q_FUNC_INFO,
 
407
                       qPrintable(QDir::toNativeSeparators(QDir::currentPath()+"/test")));
 
408
        }
 
409
    } else if (qobject_cast<QSqlQueryModel *>(model)) {
 
410
        QSqlQuery q("DROP TABLE test");
 
411
    }
 
412
}
 
413
 
 
414
void ModelsToTest::setupDatabase()
 
415
{
 
416
    if (!QSqlDatabase::database().isValid()) {
 
417
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
 
418
        db.setDatabaseName(":memory:");
 
419
        if (!db.open()) {
 
420
            qWarning() << "Unable to open database" << db.lastError();
 
421
            return;
 
422
        }
 
423
    }
 
424
}
 
425