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 <QtGui/QtGui>
45
46
#include "modeltest.h"
47
#include "dynamictreemodel.h"
48
49
50
class tst_ModelTest : public QObject
51
{
52
    Q_OBJECT
53
54
public:
55
    tst_ModelTest() {}
56
    virtual ~tst_ModelTest() {}
57
58
public slots:
59
    void initTestCase();
60
    void cleanupTestCase();
61
    void init();
62
    void cleanup();
63
64
private slots:
65
    void stringListModel();
66
    void treeWidgetModel();
67
    void standardItemModel();
68
    void testInsertThroughProxy();
69
    void moveSourceItems();
70
    void testResetThroughProxy();
71
};
72
73
74
75
void tst_ModelTest::initTestCase()
76
{
77
}
78
79
void tst_ModelTest::cleanupTestCase()
80
{
81
}
82
83
void tst_ModelTest::init()
84
{
85
86
}
87
88
void tst_ModelTest::cleanup()
89
{
90
}
91
/*
92
  tests
93
*/
94
95
void tst_ModelTest::stringListModel()
96
{
97
    QStringListModel model;
98
    QSortFilterProxyModel proxy;
99
100
    ModelTest t1(&model);
101
    ModelTest t2(&proxy);
102
103
    proxy.setSourceModel(&model);
104
105
    model.setStringList(QStringList() << "2" << "3" << "1");
106
    model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c" );
107
108
    proxy.setDynamicSortFilter(true);
109
    proxy.setFilterRegExp(QRegExp("[^b]"));
110
}
111
112
void tst_ModelTest::treeWidgetModel()
113
{
114
    QTreeWidget widget;
115
116
    ModelTest t1(widget.model());
117
118
    QTreeWidgetItem *root = new QTreeWidgetItem(&widget, QStringList("root"));
119
    for (int i = 0; i < 20; ++i) {
120
        new QTreeWidgetItem(root, QStringList(QString::number(i)));
121
    }
122
    QTreeWidgetItem *remove = root->child(2);
123
    root->removeChild(remove);
124
    QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent"));
125
    new QTreeWidgetItem(parent, QStringList("child"));
126
    widget.setItemHidden(parent, true);
127
128
    widget.sortByColumn(0);
129
}
130
131
void tst_ModelTest::standardItemModel()
132
{
133
    QStandardItemModel model(10,10);
134
    QSortFilterProxyModel proxy;
135
136
137
    ModelTest t1(&model);
138
    ModelTest t2(&proxy);
139
140
    proxy.setSourceModel(&model);
141
142
    model.insertRows(2, 5);
143
    model.removeRows(4, 5);
144
145
    model.insertColumns(2, 5);
146
    model.removeColumns(4, 5);
147
148
    model.insertRows(0,5, model.index(1,1));
149
    model.insertColumns(0,5, model.index(1,3));
150
}
151
152
void tst_ModelTest::testInsertThroughProxy()
153
{
154
    DynamicTreeModel *model = new DynamicTreeModel(this);
155
156
    QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
157
    proxy->setSourceModel(model);
158
159
    new ModelTest(proxy, this);
160
161
    ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
162
    insertCommand->setNumCols(4);
163
    insertCommand->setStartRow(0);
164
    insertCommand->setEndRow(9);
165
    // Parent is QModelIndex()
166
    insertCommand->doCommand();
167
168
    insertCommand = new ModelInsertCommand(model, this);
169
    insertCommand->setNumCols(4);
170
    insertCommand->setAncestorRowNumbers(QList<int>() << 5);
171
    insertCommand->setStartRow(0);
172
    insertCommand->setEndRow(9);
173
    insertCommand->doCommand();
174
175
    ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this);
176
    moveCommand->setNumCols(4);
177
    moveCommand->setStartRow(0);
178
    moveCommand->setEndRow(0);
179
    moveCommand->setDestRow(9);
180
    moveCommand->setDestAncestors(QList<int>() << 5);
181
    moveCommand->doCommand();
182
}
183
184
/**
185
  Makes the persistent index list publicly accessible
186
*/
187
class AccessibleProxyModel : public QSortFilterProxyModel
188
{
189
    Q_OBJECT
190
public:
191
    AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {}
192
193
    QModelIndexList persistent()
194
    {
195
        return persistentIndexList();
196
    }
197
};
198
199
class ObservingObject : public QObject
200
{
201
    Q_OBJECT
202
public:
203
    ObservingObject(AccessibleProxyModel  *proxy, QObject *parent = 0)
204
    : QObject(parent)
205
    , m_proxy(proxy)
206
    , storePersistentFailureCount(0)
207
    , checkPersistentFailureCount(0)
208
    {
209
        connect(m_proxy, SIGNAL(layoutAboutToBeChanged()), SLOT(storePersistent()));
210
        connect(m_proxy, SIGNAL(layoutChanged()), SLOT(checkPersistent()));
211
    }
212
213
public slots:
214
215
    void storePersistent(const QModelIndex &parent)
216
    {
217
        for (int row = 0; row < m_proxy->rowCount(parent); ++row) {
218
            QModelIndex proxyIndex = m_proxy->index(row, 0, parent);
219
            QModelIndex sourceIndex = m_proxy->mapToSource(proxyIndex);
220
            if (!proxyIndex.isValid()) {
221
                qWarning("%s: Invalid proxy index", Q_FUNC_INFO);
222
                ++storePersistentFailureCount;
223
            }
224
            if (!sourceIndex.isValid()) {
225
                qWarning("%s: invalid source index", Q_FUNC_INFO);
226
                ++storePersistentFailureCount;
227
            }
228
            m_persistentSourceIndexes.append(sourceIndex);
229
            m_persistentProxyIndexes.append(proxyIndex);
230
            if (m_proxy->hasChildren(proxyIndex))
231
                storePersistent(proxyIndex);
232
        }
233
    }
234
235
    void storePersistent()
236
    {
237
        // This method is called from layoutAboutToBeChanged. Persistent indexes should be valid
238
        foreach(const QModelIndex &idx, m_persistentProxyIndexes)
239
            if (!idx.isValid()) {
240
                qWarning("%s: persistentProxyIndexes contains invalid index", Q_FUNC_INFO);
241
                ++storePersistentFailureCount;
242
            }
243
244
        if (!m_proxy->persistent().isEmpty()) {
245
            qWarning("%s: proxy should have no persistent indexes when storePersistent called",
246
                     Q_FUNC_INFO);
247
            ++storePersistentFailureCount;
248
        }
249
        storePersistent(QModelIndex());
250
        if (m_proxy->persistent().isEmpty()) {
251
            qWarning("%s: proxy should have persistent index after storePersistent called",
252
                     Q_FUNC_INFO);
253
            ++storePersistentFailureCount;
254
        }
255
    }
256
257
    void checkPersistent()
258
    {
259
        for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) {
260
            QModelIndex updatedProxy = m_persistentProxyIndexes.at(row);
261
            QModelIndex updatedSource = m_persistentSourceIndexes.at(row);
262
        }
263
        for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) {
264
            QModelIndex updatedProxy = m_persistentProxyIndexes.at(row);
265
            QModelIndex updatedSource = m_persistentSourceIndexes.at(row);
266
            if (m_proxy->mapToSource(updatedProxy) != updatedSource) {
267
                qWarning("%s: check failed at row %d", Q_FUNC_INFO, row);
268
                ++checkPersistentFailureCount;
269
            }
270
        }
271
        m_persistentSourceIndexes.clear();
272
        m_persistentProxyIndexes.clear();
273
    }
274
275
private:
276
    AccessibleProxyModel  *m_proxy;
277
    QList<QPersistentModelIndex> m_persistentSourceIndexes;
278
    QList<QPersistentModelIndex> m_persistentProxyIndexes;
279
public:
280
    int storePersistentFailureCount;
281
    int checkPersistentFailureCount;
282
};
283
284
void tst_ModelTest::moveSourceItems()
285
{
286
    DynamicTreeModel *model = new DynamicTreeModel(this);
287
    AccessibleProxyModel *proxy = new AccessibleProxyModel(this);
288
    proxy->setSourceModel(model);
289
290
    ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
291
    insertCommand->setStartRow(0);
292
    insertCommand->setEndRow(2);
293
    insertCommand->doCommand();
294
295
    insertCommand = new ModelInsertCommand(model, this);
296
    insertCommand->setAncestorRowNumbers(QList<int>() << 1);
297
    insertCommand->setStartRow(0);
298
    insertCommand->setEndRow(2);
299
    insertCommand->doCommand();
300
301
    ObservingObject observer(proxy);
302
303
    ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this);
304
    moveCommand->setStartRow(0);
305
    moveCommand->setEndRow(0);
306
    moveCommand->setDestAncestors(QList<int>() << 1);
307
    moveCommand->setDestRow(0);
308
    moveCommand->doCommand();
309
310
    QCOMPARE(observer.storePersistentFailureCount, 0);
311
    QCOMPARE(observer.checkPersistentFailureCount, 0);
312
}
313
314
void tst_ModelTest::testResetThroughProxy()
315
{
316
    DynamicTreeModel *model = new DynamicTreeModel(this);
317
318
    ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
319
    insertCommand->setStartRow(0);
320
    insertCommand->setEndRow(2);
321
    insertCommand->doCommand();
322
323
    QPersistentModelIndex persistent = model->index(0, 0);
324
325
    AccessibleProxyModel *proxy = new AccessibleProxyModel(this);
326
    proxy->setSourceModel(model);
327
328
    ObservingObject observer(proxy);
329
    observer.storePersistent();
330
331
    ModelResetCommand *resetCommand = new ModelResetCommand(model, this);
332
    resetCommand->setNumCols(0);
333
    resetCommand->doCommand();
334
335
    QCOMPARE(observer.storePersistentFailureCount, 0);
336
    QCOMPARE(observer.checkPersistentFailureCount, 0);
337
}
338
339
340
QTEST_MAIN(tst_ModelTest)
341
#include "tst_modeltest.moc"