1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40
****************************************************************************/
43
#include <QtTest/QtTest>
44
#include <QtCore/QCoreApplication>
45
#include <QtSql/QtSql>
46
#include <QtWidgets/QtWidgets>
47
#include <QtCore/QSortFilterProxyModel>
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.
53
You can add more then one model, several Qt models and included as examples.
55
In tst_qitemmodel.cpp a new ModelsToTest object is created for each test.
57
When you have errors fix the first ones first. Later tests depend upon them working
65
QAbstractItemModel *createModel(const QString &modelType);
66
QModelIndex populateTestArea(QAbstractItemModel *model);
67
void cleanupTestArea(QAbstractItemModel *model);
70
ReadOnly, // wont perform remove(), insert(), and setData()
74
Empty, // Confirm that rowCount() == 0 etc throughout the test
75
HasData // Confirm that rowCount() != 0 etc throughout the test
79
test(QString m, Read r, Contains c) : modelType(m), read(r), contains(c){};
88
static void setupDatabase();
93
Add new tests, they can be the same model, but in a different state.
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
99
ModelsToTest::ModelsToTest()
103
tests.append(test("QDirModel", ReadOnly, HasData));
104
tests.append(test("QStringListModel", ReadWrite, HasData));
105
tests.append(test("QStringListModelEmpty", ReadWrite, Empty));
107
tests.append(test("QStandardItemModel", ReadWrite, HasData));
108
tests.append(test("QStandardItemModelEmpty", ReadWrite, Empty));
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));
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));
120
tests.append(test("QTreeModel", ReadWrite, HasData));
121
tests.append(test("QTreeModelEmpty", ReadWrite, Empty));
123
tests.append(test("QSqlQueryModel", ReadOnly, HasData));
124
tests.append(test("QSqlQueryModelEmpty", ReadOnly, Empty));
127
tests.append(test("QSqlTableModel", ReadOnly, HasData));
131
Return a new modelType.
133
QAbstractItemModel *ModelsToTest::createModel(const QString &modelType)
135
if (modelType == "QStringListModelEmpty")
136
return new QStringListModel();
138
if (modelType == "QStringListModel") {
139
QStringListModel *model = new QStringListModel();
140
populateTestArea(model);
144
if (modelType == "QStandardItemModelEmpty") {
145
return new QStandardItemModel();
148
if (modelType == "QStandardItemModel") {
149
QStandardItemModel *model = new QStandardItemModel();
150
populateTestArea(model);
154
if (modelType == "QSortFilterProxyModelEmpty") {
155
QSortFilterProxyModel *model = new QSortFilterProxyModel;
156
QStandardItemModel *standardItemModel = new QStandardItemModel;
157
model->setSourceModel(standardItemModel);
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.*)"));
170
if (modelType == "QSortFilterProxyModel") {
171
QSortFilterProxyModel *model = new QSortFilterProxyModel;
172
QStandardItemModel *standardItemModel = new QStandardItemModel;
173
model->setSourceModel(standardItemModel);
174
populateTestArea(model);
178
if (modelType == "QDirModel") {
179
QDirModel *model = new QDirModel();
180
model->setReadOnly(false);
184
if (modelType == "QSqlQueryModel") {
185
QSqlQueryModel *model = new QSqlQueryModel();
186
populateTestArea(model);
190
if (modelType == "QSqlQueryModelEmpty") {
191
QSqlQueryModel *model = new QSqlQueryModel();
195
if (modelType == "QSqlTableModel") {
196
QSqlTableModel *model = new QSqlTableModel();
197
populateTestArea(model);
201
if (modelType == "QListModelEmpty")
202
return (new QListWidget)->model();
204
if (modelType == "QListModel") {
205
QListWidget *widget = new QListWidget;
206
populateTestArea(widget->model());
207
return widget->model();
210
if (modelType == "QTableModelEmpty")
211
return (new QTableWidget)->model();
213
if (modelType == "QTableModel") {
214
QTableWidget *widget = new QTableWidget;
215
populateTestArea(widget->model());
216
return widget->model();
219
if (modelType == "QTreeModelEmpty") {
220
QTreeWidget *widget = new QTreeWidget;
221
return widget->model();
224
if (modelType == "QTreeModel") {
225
QTreeWidget *widget = new QTreeWidget;
226
populateTestArea(widget->model());
227
return widget->model();
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.
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.
240
QModelIndex ModelsToTest::populateTestArea(QAbstractItemModel *model)
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();
248
if (qobject_cast<QStandardItemModel *>(model)) {
249
// Basic tree StandardItemModel
251
QVariant blue = QVariant(QColor(Qt::blue));
253
for (int i = 0; i < 4; ++i) {
255
for (int i = 0; i < 2; ++i) {
257
parent = model->index(0, 0, parent);
258
model->insertRows(0, 26 + i, parent);
260
model->insertColumns(0, 26 + i, parent);
262
model->insertColumns(0, 4 + i, parent);
264
// Fill in some values to make it easier to debug
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);
277
return model->index(0,0);
280
if (qobject_cast<QSortFilterProxyModel *>(model)) {
281
QAbstractItemModel *realModel = (qobject_cast<QSortFilterProxyModel *>(model))->sourceModel();
282
// Basic tree StandardItemModel
284
QVariant blue = QVariant(QColor(Qt::blue));
286
for (int i = 0; i < 4; ++i) {
288
for (int i = 0; i < 2; ++i) {
290
parent = realModel->index(0, 0, parent);
291
realModel->insertRows(0, 26+i, parent);
293
realModel->insertColumns(0, 26+i, parent);
295
realModel->insertColumns(0, 4, parent);
297
// Fill in some values to make it easier to debug
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);
310
QModelIndex returnIndex = model->index(0,0);
311
if (!returnIndex.isValid())
312
qFatal("%s: model index to be returned is invalid", Q_FUNC_INFO);
316
if (QDirModel *dirModel = qobject_cast<QDirModel *>(model)) {
317
if (!QDir::current().mkdir("test"))
318
qFatal("%s: cannot create directory %s",
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",
326
qPrintable(QDir::toNativeSeparators(QDir::currentPath()+"/"+subdir)));
328
return dirModel->index(QDir::currentPath()+"/test");
331
if (QSqlQueryModel *queryModel = qobject_cast<QSqlQueryModel *>(model)) {
333
q.exec("CREATE TABLE test(id int primary key, name varchar(30))");
334
q.prepare("INSERT INTO test(id, name) values (?, ?)");
336
for (int i = 0; i < 1024; ++i) {
338
for (int i = 0; i < 512; ++i) {
341
q.addBindValue("Mr. Smith" + QString::number(i));
344
if (QSqlTableModel *tableModel = qobject_cast<QSqlTableModel *>(model)) {
345
tableModel->setTable("test");
346
tableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
347
tableModel->select();
349
queryModel->setQuery("select * from test");
351
return QModelIndex();
354
if (QListWidget *listWidget = qobject_cast<QListWidget *>(model->parent())) {
361
listWidget->addItem(QString("item %1").arg(items));
362
return QModelIndex();
365
if (QTableWidget *tableWidget = qobject_cast<QTableWidget *>(model->parent())) {
366
tableWidget->setColumnCount(20);
367
tableWidget->setRowCount(20);
368
return QModelIndex();
371
if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(model->parent())) {
373
treeWidget->setColumnCount(1);
374
QTreeWidgetItem *parent;
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)));
380
return QModelIndex();
383
qFatal("%s: unknown type of model", Q_FUNC_INFO);
384
return QModelIndex();
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.
391
void ModelsToTest::cleanupTestArea(QAbstractItemModel *model)
393
if (qobject_cast<QDirModel *>(model))
395
if (QDir(QDir::currentPath()+"/test").exists())
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",
402
qPrintable(QDir::toNativeSeparators(QDir::currentPath()+"/"+subdir)));
404
if (!QDir::current().rmdir("test"))
405
qFatal("%s: cannot remove directory %s",
407
qPrintable(QDir::toNativeSeparators(QDir::currentPath()+"/test")));
409
} else if (qobject_cast<QSqlQueryModel *>(model)) {
410
QSqlQuery q("DROP TABLE test");
414
void ModelsToTest::setupDatabase()
416
if (!QSqlDatabase::database().isValid()) {
417
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
418
db.setDatabaseName(":memory:");
420
qWarning() << "Unable to open database" << db.lastError();