1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30#include <QtGui/QtGui>
31#include <QtWidgets/QtWidgets>
32
33#include "dynamictreemodel.h"
34
35class tst_QAbstractItemModelTester : public QObject
36{
37 Q_OBJECT
38
39private slots:
40 void stringListModel();
41 void treeWidgetModel();
42 void standardItemModel();
43 void standardItemModelZeroColumns();
44 void testInsertThroughProxy();
45 void moveSourceItems();
46 void testResetThroughProxy();
47};
48
49/*
50 tests
51*/
52
53void tst_QAbstractItemModelTester::stringListModel()
54{
55 QStringListModel model;
56 QSortFilterProxyModel proxy;
57
58 QAbstractItemModelTester t1(&model);
59 QAbstractItemModelTester t2(&proxy);
60
61 proxy.setSourceModel(&model);
62
63 model.setStringList(QStringList() << "2" << "3" << "1");
64 model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c");
65
66 proxy.setDynamicSortFilter(true);
67 proxy.setFilterRegularExpression(QRegularExpression("[^b]"));
68}
69
70void tst_QAbstractItemModelTester::treeWidgetModel()
71{
72 QTreeWidget widget;
73
74 QAbstractItemModelTester t1(widget.model());
75
76 QTreeWidgetItem *root = new QTreeWidgetItem(&widget, QStringList("root"));
77 for (int i = 0; i < 20; ++i)
78 new QTreeWidgetItem(root, QStringList(QString::number(i)));
79 QTreeWidgetItem *remove = root->child(index: 2);
80 root->removeChild(child: remove);
81 QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent"));
82 new QTreeWidgetItem(parent, QStringList("child"));
83 parent->setHidden(true);
84
85 widget.sortByColumn(column: 0, order: Qt::AscendingOrder);
86}
87
88void tst_QAbstractItemModelTester::standardItemModel()
89{
90 QStandardItemModel model(10, 10);
91 QSortFilterProxyModel proxy;
92
93 QAbstractItemModelTester t1(&model);
94 QAbstractItemModelTester t2(&proxy);
95
96 proxy.setSourceModel(&model);
97
98 model.insertRows(row: 2, count: 5);
99 model.removeRows(row: 4, count: 5);
100
101 model.insertColumns(column: 2, count: 5);
102 model.removeColumns(column: 4, count: 5);
103
104 model.insertRows(row: 0, count: 5, parent: model.index(row: 1, column: 1));
105 model.insertColumns(column: 0, count: 5, parent: model.index(row: 1, column: 3));
106}
107
108void tst_QAbstractItemModelTester::standardItemModelZeroColumns()
109{
110 QStandardItemModel model;
111 QAbstractItemModelTester t1(&model);
112 // QTBUG-92220
113 model.insertRows(row: 0, count: 5);
114 model.removeRows(row: 0, count: 5);
115 // QTBUG-92886
116 model.insertRows(row: 0, count: 5);
117 model.removeRows(row: 1, count: 2);
118}
119
120void tst_QAbstractItemModelTester::testInsertThroughProxy()
121{
122 DynamicTreeModel *model = new DynamicTreeModel(this);
123
124 QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
125 proxy->setSourceModel(model);
126
127 new QAbstractItemModelTester(proxy, this);
128
129 ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
130 insertCommand->setNumCols(4);
131 insertCommand->setStartRow(0);
132 insertCommand->setEndRow(9);
133 // Parent is QModelIndex()
134 insertCommand->doCommand();
135
136 insertCommand = new ModelInsertCommand(model, this);
137 insertCommand->setNumCols(4);
138 insertCommand->setAncestorRowNumbers(QList<int>() << 5);
139 insertCommand->setStartRow(0);
140 insertCommand->setEndRow(9);
141 insertCommand->doCommand();
142
143 ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this);
144 moveCommand->setNumCols(4);
145 moveCommand->setStartRow(0);
146 moveCommand->setEndRow(0);
147 moveCommand->setDestRow(9);
148 moveCommand->setDestAncestors(QList<int>() << 5);
149 moveCommand->doCommand();
150}
151
152/**
153 Makes the persistent index list publicly accessible
154*/
155class AccessibleProxyModel : public QSortFilterProxyModel
156{
157 Q_OBJECT
158public:
159 AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent)
160 {
161 }
162
163 QModelIndexList persistent()
164 {
165 return persistentIndexList();
166 }
167};
168
169class ObservingObject : public QObject
170{
171 Q_OBJECT
172public:
173 ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0) :
174 QObject(parent),
175 m_proxy(proxy),
176 storePersistentFailureCount(0),
177 checkPersistentFailureCount(0)
178 {
179 connect(asender: m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
180 SLOT(storePersistent()));
181 connect(asender: m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
182 SLOT(checkPersistent()));
183 }
184
185public slots:
186
187 void storePersistent(const QModelIndex &parent)
188 {
189 for (int row = 0; row < m_proxy->rowCount(parent); ++row) {
190 QModelIndex proxyIndex = m_proxy->index(row, column: 0, parent);
191 QModelIndex sourceIndex = m_proxy->mapToSource(proxyIndex);
192 if (!proxyIndex.isValid()) {
193 qWarning(msg: "%s: Invalid proxy index", Q_FUNC_INFO);
194 ++storePersistentFailureCount;
195 }
196 if (!sourceIndex.isValid()) {
197 qWarning(msg: "%s: invalid source index", Q_FUNC_INFO);
198 ++storePersistentFailureCount;
199 }
200 m_persistentSourceIndexes.append(t: sourceIndex);
201 m_persistentProxyIndexes.append(t: proxyIndex);
202 if (m_proxy->hasChildren(parent: proxyIndex))
203 storePersistent(parent: proxyIndex);
204 }
205 }
206
207 void storePersistent()
208 {
209 // This method is called from rowsAboutToBeMoved. Persistent indexes should be valid
210 foreach (const QModelIndex &idx, m_persistentProxyIndexes)
211 if (!idx.isValid()) {
212 qWarning(msg: "%s: persistentProxyIndexes contains invalid index", Q_FUNC_INFO);
213 ++storePersistentFailureCount;
214 }
215
216 if (!m_proxy->persistent().isEmpty()) {
217 qWarning(msg: "%s: proxy should have no persistent indexes when storePersistent called",
218 Q_FUNC_INFO);
219 ++storePersistentFailureCount;
220 }
221 storePersistent(parent: QModelIndex());
222 if (m_proxy->persistent().isEmpty()) {
223 qWarning(msg: "%s: proxy should have persistent index after storePersistent called",
224 Q_FUNC_INFO);
225 ++storePersistentFailureCount;
226 }
227 }
228
229 void checkPersistent()
230 {
231 for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) {
232 m_persistentProxyIndexes.at(i: row);
233 m_persistentSourceIndexes.at(i: row);
234 }
235 for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) {
236 QModelIndex updatedProxy = m_persistentProxyIndexes.at(i: row);
237 QModelIndex updatedSource = m_persistentSourceIndexes.at(i: row);
238 if (m_proxy->mapToSource(proxyIndex: updatedProxy) != updatedSource) {
239 qWarning(msg: "%s: check failed at row %d", Q_FUNC_INFO, row);
240 ++checkPersistentFailureCount;
241 }
242 }
243 m_persistentSourceIndexes.clear();
244 m_persistentProxyIndexes.clear();
245 }
246
247private:
248 AccessibleProxyModel *m_proxy;
249 QList<QPersistentModelIndex> m_persistentSourceIndexes;
250 QList<QPersistentModelIndex> m_persistentProxyIndexes;
251public:
252 int storePersistentFailureCount;
253 int checkPersistentFailureCount;
254};
255
256void tst_QAbstractItemModelTester::moveSourceItems()
257{
258 DynamicTreeModel *model = new DynamicTreeModel(this);
259 AccessibleProxyModel *proxy = new AccessibleProxyModel(this);
260 proxy->setSourceModel(model);
261
262 ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
263 insertCommand->setStartRow(0);
264 insertCommand->setEndRow(2);
265 insertCommand->doCommand();
266
267 insertCommand = new ModelInsertCommand(model, this);
268 insertCommand->setAncestorRowNumbers(QList<int>() << 1);
269 insertCommand->setStartRow(0);
270 insertCommand->setEndRow(2);
271 insertCommand->doCommand();
272
273 ObservingObject observer(proxy);
274
275 ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this);
276 moveCommand->setStartRow(0);
277 moveCommand->setEndRow(0);
278 moveCommand->setDestAncestors(QList<int>() << 1);
279 moveCommand->setDestRow(0);
280 moveCommand->doCommand();
281
282 QCOMPARE(observer.storePersistentFailureCount, 0);
283 QCOMPARE(observer.checkPersistentFailureCount, 0);
284}
285
286void tst_QAbstractItemModelTester::testResetThroughProxy()
287{
288 DynamicTreeModel *model = new DynamicTreeModel(this);
289
290 ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
291 insertCommand->setStartRow(0);
292 insertCommand->setEndRow(2);
293 insertCommand->doCommand();
294
295 QPersistentModelIndex persistent = model->index(row: 0, column: 0);
296
297 AccessibleProxyModel *proxy = new AccessibleProxyModel(this);
298 proxy->setSourceModel(model);
299
300 ObservingObject observer(proxy);
301 observer.storePersistent();
302
303 ModelResetCommand *resetCommand = new ModelResetCommand(model, this);
304 resetCommand->setNumCols(0);
305 resetCommand->doCommand();
306
307 QCOMPARE(observer.storePersistentFailureCount, 0);
308 QCOMPARE(observer.checkPersistentFailureCount, 0);
309}
310
311QTEST_MAIN(tst_QAbstractItemModelTester)
312#include "tst_qabstractitemmodeltester.moc"
313

source code of qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp