1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 
43 #include <QtTest/QtTest>
44 
45 #include <qstandarditemmodel.h>
46 #include <QTreeView>
47 #include <private/qtreeview_p.h>
48 
49 //TESTED_CLASS=
50 //TESTED_FILES=
51 
52 class tst_QStandardItemModel : public QObject
53 {
54     Q_OBJECT
55 
56 public:
57     tst_QStandardItemModel();
58     virtual ~tst_QStandardItemModel();
59 
60     enum ModelChanged {
61         RowsAboutToBeInserted,
62         RowsInserted,
63         RowsAboutToBeRemoved,
64         RowsRemoved,
65         ColumnsAboutToBeInserted,
66         ColumnsInserted,
67         ColumnsAboutToBeRemoved,
68         ColumnsRemoved
69     };
70 
71 public slots:
72     void init();
73     void cleanup();
74 
75 protected slots:
76     void checkAboutToBeRemoved();
77     void checkRemoved();
78     void updateRowAboutToBeRemoved();
79 
rowsAboutToBeInserted(const QModelIndex & parent,int first,int last)80     void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
81         { modelChanged(RowsAboutToBeInserted, parent, first, last); }
rowsInserted(const QModelIndex & parent,int first,int last)82     void rowsInserted(const QModelIndex &parent, int first, int last)
83         { modelChanged(RowsInserted, parent, first, last); }
rowsAboutToBeRemoved(const QModelIndex & parent,int first,int last)84     void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
85         { modelChanged(RowsAboutToBeRemoved, parent, first, last); }
rowsRemoved(const QModelIndex & parent,int first,int last)86     void rowsRemoved(const QModelIndex &parent, int first, int last)
87         { modelChanged(RowsRemoved, parent, first, last); }
columnsAboutToBeInserted(const QModelIndex & parent,int first,int last)88     void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
89         { modelChanged(ColumnsAboutToBeInserted, parent, first, last); }
columnsInserted(const QModelIndex & parent,int first,int last)90     void columnsInserted(const QModelIndex &parent, int first, int last)
91         { modelChanged(ColumnsInserted, parent, first, last); }
columnsAboutToBeRemoved(const QModelIndex & parent,int first,int last)92     void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
93         { modelChanged(ColumnsAboutToBeRemoved, parent, first, last); }
columnsRemoved(const QModelIndex & parent,int first,int last)94     void columnsRemoved(const QModelIndex &parent, int first, int last)
95         { modelChanged(ColumnsRemoved, parent, first, last); }
96 
97     void modelChanged(ModelChanged change, const QModelIndex &parent, int first, int last);
98 
99 private slots:
100     void insertRow_data();
101     void insertRow();
102     void insertRows();
103     void insertRowsItems();
104     void insertRowInHierarcy();
105     void insertColumn_data();
106     void insertColumn();
107     void insertColumns();
108     void removeRows();
109     void removeColumns();
110     void setHeaderData();
111     void persistentIndexes();
112     void removingPersistentIndexes();
113     void updatingPersistentIndexes();
114 
115     void checkChildren();
116     void data();
117     void clear();
118     void sort_data();
119     void sort();
120     void sortRole_data();
121     void sortRole();
122     void findItems();
123     void getSetHeaderItem();
124     void indexFromItem();
125     void itemFromIndex();
126     void getSetItemPrototype();
127     void getSetItemData();
128     void setHeaderLabels_data();
129     void setHeaderLabels();
130     void itemDataChanged();
131     void takeHeaderItem();
132     void useCase1();
133     void useCase2();
134     void useCase3();
135 
136     void rootItemFlags();
137     void treeDragAndDrop();
138     void removeRowsAndColumns();
139 
140 private:
141     QAbstractItemModel *m_model;
142     QPersistentModelIndex persistent;
143     QVector<QModelIndex> rcParent;
144     QVector<int> rcFirst;
145     QVector<int> rcLast;
146 
147     //return true if models have the same structure, and all child have the same text
148     bool compareModels(QStandardItemModel *model1, QStandardItemModel *model2);
149     //return true if models have the same structure, and all child have the same text
150     bool compareItems(QStandardItem *item1, QStandardItem *item2);
151 };
152 
153 static const int defaultSize = 3;
154 
155 Q_DECLARE_METATYPE(QModelIndex)
Q_DECLARE_METATYPE(QStandardItem *)156 Q_DECLARE_METATYPE(QStandardItem*)
157 Q_DECLARE_METATYPE(Qt::Orientation)
158 Q_DECLARE_METATYPE(QVariantList)
159 
160 tst_QStandardItemModel::tst_QStandardItemModel() : m_model(0), rcParent(8), rcFirst(8,0), rcLast(8,0)
161 {
162 }
163 
~tst_QStandardItemModel()164 tst_QStandardItemModel::~tst_QStandardItemModel()
165 {
166 }
167 
168 /*
169   This test usually uses a model with a 3x3 table
170   ---------------------------
171   |  0,0  |  0,1    |  0,2  |
172   ---------------------------
173   |  1,0  |  1,1    |  1,2  |
174   ---------------------------
175   |  2,0  |  2,1    |  2,2  |
176   ---------------------------
177 */
init()178 void tst_QStandardItemModel::init()
179 {
180     qRegisterMetaType<QModelIndex>("QModelIndex");
181     qRegisterMetaType<QStandardItem*>("QStandardItem*");
182     qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
183 
184     m_model = new QStandardItemModel(defaultSize, defaultSize);
185     connect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)),
186             this, SLOT(rowsAboutToBeInserted(QModelIndex, int, int)));
187     connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
188             this, SLOT(rowsInserted(QModelIndex, int, int)));
189     connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
190             this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
191     connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)),
192             this, SLOT(rowsRemoved(QModelIndex, int, int)));
193 
194     connect(m_model, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)),
195             this, SLOT(columnsAboutToBeInserted(QModelIndex, int, int)));
196     connect(m_model, SIGNAL(columnsInserted(QModelIndex, int, int)),
197             this, SLOT(columnsInserted(QModelIndex, int, int)));
198     connect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)),
199             this, SLOT(columnsAboutToBeRemoved(QModelIndex, int, int)));
200     connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)),
201             this, SLOT(columnsRemoved(QModelIndex, int, int)));
202 
203     rcFirst.fill(-1);
204     rcLast.fill(-1);
205 }
206 
cleanup()207 void tst_QStandardItemModel::cleanup()
208 {
209     disconnect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)),
210                this, SLOT(rowsAboutToBeInserted(QModelIndex, int, int)));
211     disconnect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)),
212                this, SLOT(rowsInserted(QModelIndex, int, int)));
213     disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
214                this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
215     disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)),
216                this, SLOT(rowsRemoved(QModelIndex, int, int)));
217 
218     disconnect(m_model, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)),
219                this, SLOT(columnsAboutToBeInserted(QModelIndex, int, int)));
220     disconnect(m_model, SIGNAL(columnsInserted(QModelIndex, int, int)),
221                this, SLOT(columnsInserted(QModelIndex, int, int)));
222     disconnect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)),
223                this, SLOT(columnsAboutToBeRemoved(QModelIndex, int, int)));
224     disconnect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)),
225                this, SLOT(columnsRemoved(QModelIndex, int, int)));
226     delete m_model;
227     m_model = 0;
228 }
229 
insertRow_data()230 void tst_QStandardItemModel::insertRow_data()
231 {
232     QTest::addColumn<int>("insertRow");
233     QTest::addColumn<int>("expectedRow");
234 
235     QTest::newRow("Insert less then 0") << -1 << 0;
236     QTest::newRow("Insert at 0")  << 0 << 0;
237     QTest::newRow("Insert beyond count")  << defaultSize+1 << defaultSize;
238     QTest::newRow("Insert at count") << defaultSize << defaultSize;
239     QTest::newRow("Insert in the middle") << 1 << 1;
240 }
241 
insertRow()242 void tst_QStandardItemModel::insertRow()
243 {
244     QFETCH(int, insertRow);
245     QFETCH(int, expectedRow);
246 
247     QIcon icon;
248     // default all initial items to DisplayRole: "initalitem"
249     for (int r=0; r < m_model->rowCount(); ++r) {
250         for (int c=0; c < m_model->columnCount(); ++c) {
251             m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
252         }
253     }
254 
255     // check that inserts changes rowCount
256     QCOMPARE(m_model->rowCount(), defaultSize);
257     m_model->insertRow(insertRow);
258     if (insertRow >= 0 && insertRow <= defaultSize) {
259         QCOMPARE(m_model->rowCount(), defaultSize + 1);
260 
261         // check that signals were emitted with correct info
262         QCOMPARE(rcFirst[RowsAboutToBeInserted], expectedRow);
263         QCOMPARE(rcLast[RowsAboutToBeInserted], expectedRow);
264         QCOMPARE(rcFirst[RowsInserted], expectedRow);
265         QCOMPARE(rcLast[RowsInserted], expectedRow);
266 
267         //check that the inserted item has different DisplayRole than initial items
268         QVERIFY(m_model->data(m_model->index(expectedRow, 0), Qt::DisplayRole).toString() != "initialitem");
269     } else {
270         // We inserted something outside the bounds, do nothing
271         QCOMPARE(m_model->rowCount(), defaultSize);
272         QCOMPARE(rcFirst[RowsAboutToBeInserted], -1);
273         QCOMPARE(rcLast[RowsAboutToBeInserted], -1);
274         QCOMPARE(rcFirst[RowsInserted], -1);
275         QCOMPARE(rcLast[RowsInserted], -1);
276     }
277 }
278 
insertRows()279 void tst_QStandardItemModel::insertRows()
280 {
281     int rowCount = m_model->rowCount();
282     QCOMPARE(rowCount, defaultSize);
283 
284     // insert custom header label
285     QString headerLabel = "custom";
286     m_model->setHeaderData(0, Qt::Vertical, headerLabel);
287 
288     // insert one row
289     m_model->insertRows(0, 1);
290     QCOMPARE(m_model->rowCount(), rowCount + 1);
291     rowCount = m_model->rowCount();
292 
293     // check header data has moved
294     QCOMPARE(m_model->headerData(1, Qt::Vertical).toString(), headerLabel);
295 
296     // insert two rows
297     m_model->insertRows(0, 2);
298     QCOMPARE(m_model->rowCount(), rowCount + 2);
299 
300     // check header data has moved
301     QCOMPARE(m_model->headerData(3, Qt::Vertical).toString(), headerLabel);
302 }
303 
insertRowsItems()304 void tst_QStandardItemModel::insertRowsItems()
305 {
306     int rowCount = m_model->rowCount();
307 
308     QList<QStandardItem *> items;
309     QStandardItemModel *m = qobject_cast<QStandardItemModel*>(m_model);
310     QStandardItem *hiddenRoot = m->invisibleRootItem();
311     for (int i = 0; i < 3; ++i)
312         items.append(new QStandardItem(QString("%1").arg(i + 10)));
313     hiddenRoot->appendRows(items);
314     QCOMPARE(m_model->rowCount(), rowCount + 3);
315     QCOMPARE(m_model->index(rowCount + 0, 0).data().toInt(), 10);
316     QCOMPARE(m_model->index(rowCount + 1, 0).data().toInt(), 11);
317     QCOMPARE(m_model->index(rowCount + 2, 0).data().toInt(), 12);
318     for (int i = rowCount; i < rowCount + 3; ++i) {
319         QVERIFY(m->item(i));
320         QCOMPARE(static_cast<QAbstractItemModel *>(m->item(i)->model()), m_model);
321     }
322 }
323 
insertRowInHierarcy()324 void tst_QStandardItemModel::insertRowInHierarcy()
325 {
326     QVERIFY(m_model->insertRows(0, 1, QModelIndex()));
327     QVERIFY(m_model->insertColumns(0, 1, QModelIndex()));
328     QVERIFY(m_model->hasIndex(0, 0, QModelIndex()));
329 
330     QModelIndex parent = m_model->index(0, 0, QModelIndex());
331     QVERIFY(parent.isValid());
332 
333     QVERIFY(m_model->insertRows(0, 1, parent));
334     QVERIFY(m_model->insertColumns(0, 1, parent));
335     QVERIFY(m_model->hasIndex(0, 0, parent));
336 
337     QModelIndex child = m_model->index(0, 0, parent);
338     QVERIFY(child.isValid());
339 }
340 
insertColumn_data()341 void tst_QStandardItemModel::insertColumn_data()
342 {
343     QTest::addColumn<int>("insertColumn");
344     QTest::addColumn<int>("expectedColumn");
345 
346     QTest::newRow("Insert less then 0") << -1 << 0;
347     QTest::newRow("Insert at 0")  << 0 << 0;
348     QTest::newRow("Insert beyond count")  << defaultSize+1 << defaultSize;
349     QTest::newRow("Insert at count") << defaultSize << defaultSize;
350     QTest::newRow("Insert in the middle") << 1 << 1;
351 }
352 
insertColumn()353 void tst_QStandardItemModel::insertColumn()
354 {
355     QFETCH(int, insertColumn);
356     QFETCH(int, expectedColumn);
357 
358     // default all initial items to DisplayRole: "initalitem"
359     for (int r=0; r < m_model->rowCount(); ++r) {
360         for (int c=0; c < m_model->columnCount(); ++c) {
361             m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
362         }
363     }
364 
365     // check that inserts changes columnCount
366     QCOMPARE(m_model->columnCount(), defaultSize);
367     m_model->insertColumn(insertColumn);
368     if (insertColumn >= 0 && insertColumn <= defaultSize) {
369         QCOMPARE(m_model->columnCount(), defaultSize +  1);
370         // check that signals were emitted with correct info
371         QCOMPARE(rcFirst[ColumnsAboutToBeInserted], expectedColumn);
372         QCOMPARE(rcLast[ColumnsAboutToBeInserted], expectedColumn);
373         QCOMPARE(rcFirst[ColumnsInserted], expectedColumn);
374         QCOMPARE(rcLast[ColumnsInserted], expectedColumn);
375 
376         //check that the inserted item has different DisplayRole than initial items
377         QVERIFY(m_model->data(m_model->index(0, expectedColumn), Qt::DisplayRole).toString() != "initialitem");
378     } else {
379         // We inserted something outside the bounds, do nothing
380         QCOMPARE(m_model->columnCount(), defaultSize);
381         QCOMPARE(rcFirst[ColumnsAboutToBeInserted], -1);
382         QCOMPARE(rcLast[ColumnsAboutToBeInserted], -1);
383         QCOMPARE(rcFirst[ColumnsInserted], -1);
384         QCOMPARE(rcLast[ColumnsInserted], -1);
385     }
386 
387 }
388 
insertColumns()389 void tst_QStandardItemModel::insertColumns()
390 {
391     int columnCount = m_model->columnCount();
392     QCOMPARE(columnCount, defaultSize);
393 
394     // insert custom header label
395     QString headerLabel = "custom";
396     m_model->setHeaderData(0, Qt::Horizontal, headerLabel);
397 
398     // insert one column
399     m_model->insertColumns(0, 1);
400     QCOMPARE(m_model->columnCount(), columnCount + 1);
401     columnCount = m_model->columnCount();
402 
403     // check header data has moved
404     QCOMPARE(m_model->headerData(1, Qt::Horizontal).toString(), headerLabel);
405 
406     // insert two columns
407     m_model->insertColumns(0, 2);
408     QCOMPARE(m_model->columnCount(), columnCount + 2);
409 
410     // check header data has moved
411     QCOMPARE(m_model->headerData(3, Qt::Horizontal).toString(), headerLabel);
412 }
413 
removeRows()414 void tst_QStandardItemModel::removeRows()
415 {
416     int rowCount = m_model->rowCount();
417     QCOMPARE(rowCount, defaultSize);
418 
419     // insert custom header label
420     QString headerLabel = "custom";
421     m_model->setHeaderData(rowCount - 1, Qt::Vertical, headerLabel);
422 
423     // remove one row
424     m_model->removeRows(0, 1);
425     QCOMPARE(m_model->rowCount(), rowCount - 1);
426     rowCount = m_model->rowCount();
427 
428     // check header data has moved
429     QCOMPARE(m_model->headerData(rowCount - 1, Qt::Vertical).toString(), headerLabel);
430 
431     // remove two rows
432     m_model->removeRows(0, 2);
433     QCOMPARE(m_model->rowCount(), rowCount - 2);
434 }
435 
removeColumns()436 void tst_QStandardItemModel::removeColumns()
437 {
438     int columnCount = m_model->columnCount();
439     QCOMPARE(columnCount, defaultSize);
440 
441     // insert custom header label
442     QString headerLabel = "custom";
443     m_model->setHeaderData(columnCount - 1, Qt::Horizontal, headerLabel);
444 
445     // remove one column
446     m_model->removeColumns(0, 1);
447     QCOMPARE(m_model->columnCount(), columnCount - 1);
448     columnCount = m_model->columnCount();
449 
450     // check header data has moved
451     QCOMPARE(m_model->headerData(columnCount - 1, Qt::Horizontal).toString(), headerLabel);
452 
453     // remove two columns
454     m_model->removeColumns(0, 2);
455     QCOMPARE(m_model->columnCount(), columnCount - 2);
456 }
457 
458 
setHeaderData()459 void tst_QStandardItemModel::setHeaderData()
460 {
461     for (int x = 0; x < 2; ++x) {
462         bool vertical = (x == 0);
463         int count = vertical ? m_model->rowCount() : m_model->columnCount();
464         QCOMPARE(count, defaultSize);
465         Qt::Orientation orient = vertical ? Qt::Vertical : Qt::Horizontal;
466 
467         // check default values are ok
468         for (int i = 0; i < count; ++i)
469             QCOMPARE(m_model->headerData(i, orient).toString(), QString::number(i + 1));
470 
471         QSignalSpy headerDataChangedSpy(
472             m_model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
473         QSignalSpy dataChangedSpy(
474             m_model, SIGNAL(dataChanged(QModelIndex, QModelIndex)));
475         // insert custom values and check
476         for (int i = 0; i < count; ++i) {
477             QString customString = QString("custom") + QString::number(i);
478             QCOMPARE(m_model->setHeaderData(i, orient, customString), true);
479             QCOMPARE(headerDataChangedSpy.count(), 1);
480             QCOMPARE(dataChangedSpy.count(), 0);
481             QVariantList args = headerDataChangedSpy.takeFirst();
482             QCOMPARE(qvariant_cast<Qt::Orientation>(args.at(0)), orient);
483             QCOMPARE(args.at(1).toInt(), i);
484             QCOMPARE(args.at(2).toInt(), i);
485             QCOMPARE(m_model->headerData(i, orient).toString(), customString);
486             QCOMPARE(m_model->setHeaderData(i, orient, customString), true);
487             QCOMPARE(headerDataChangedSpy.count(), 0);
488             QCOMPARE(dataChangedSpy.count(), 0);
489         }
490 
491         //check read from invalid sections
492         QVERIFY(!m_model->headerData(count, orient).isValid());
493         QVERIFY(!m_model->headerData(-1, orient).isValid());
494         //check write to invalid section
495         QCOMPARE(m_model->setHeaderData(count, orient, "foo"), false);
496         QCOMPARE(m_model->setHeaderData(-1, orient, "foo"), false);
497         QVERIFY(!m_model->headerData(count, orient).isValid());
498         QVERIFY(!m_model->headerData(-1, orient).isValid());
499     }
500 }
501 
persistentIndexes()502 void tst_QStandardItemModel::persistentIndexes()
503 {
504     QCOMPARE(m_model->rowCount(), defaultSize);
505     QCOMPARE(m_model->columnCount(), defaultSize);
506 
507     // create a persisten index at 0,0
508     QPersistentModelIndex persistentIndex(m_model->index(0, 0));
509 
510     // verify it is ok and at the correct spot
511     QVERIFY(persistentIndex.isValid());
512     QCOMPARE(persistentIndex.row(), 0);
513     QCOMPARE(persistentIndex.column(), 0);
514 
515     // insert row and check that the persisten index has moved
516     QVERIFY(m_model->insertRow(0));
517     QVERIFY(persistentIndex.isValid());
518     QCOMPARE(persistentIndex.row(), 1);
519     QCOMPARE(persistentIndex.column(), 0);
520 
521     // insert row after the persisten index and see that it stays the same
522     QVERIFY(m_model->insertRow(m_model->rowCount()));
523     QVERIFY(persistentIndex.isValid());
524     QCOMPARE(persistentIndex.row(), 1);
525     QCOMPARE(persistentIndex.column(), 0);
526 
527     // insert column and check that the persisten index has moved
528     QVERIFY(m_model->insertColumn(0));
529     QVERIFY(persistentIndex.isValid());
530     QCOMPARE(persistentIndex.row(), 1);
531     QCOMPARE(persistentIndex.column(), 1);
532 
533     // insert column after the persisten index and see that it stays the same
534     QVERIFY(m_model->insertColumn(m_model->columnCount()));
535     QVERIFY(persistentIndex.isValid());
536     QCOMPARE(persistentIndex.row(), 1);
537     QCOMPARE(persistentIndex.column(), 1);
538 
539     // removes a row beyond the persistent index and see it stays the same
540     QVERIFY(m_model->removeRow(m_model->rowCount() - 1));
541     QVERIFY(persistentIndex.isValid());
542     QCOMPARE(persistentIndex.row(), 1);
543     QCOMPARE(persistentIndex.column(), 1);
544 
545     // removes a column beyond the persistent index and see it stays the same
546     QVERIFY(m_model->removeColumn(m_model->columnCount() - 1));
547     QVERIFY(persistentIndex.isValid());
548     QCOMPARE(persistentIndex.row(), 1);
549     QCOMPARE(persistentIndex.column(), 1);
550 
551     // removes a row before the persistent index and see it moves the same
552     QVERIFY(m_model->removeRow(0));
553     QVERIFY(persistentIndex.isValid());
554     QCOMPARE(persistentIndex.row(), 0);
555     QCOMPARE(persistentIndex.column(), 1);
556 
557     // removes a column before the persistent index and see it moves the same
558     QVERIFY(m_model->removeColumn(0));
559     QVERIFY(persistentIndex.isValid());
560     QCOMPARE(persistentIndex.row(), 0);
561     QCOMPARE(persistentIndex.column(), 0);
562 
563     // remove the row where the persistent index is, and see that it becomes invalid
564     QVERIFY(m_model->removeRow(0));
565     QVERIFY(!persistentIndex.isValid());
566 
567     // remove the row where the persistent index is, and see that it becomes invalid
568     persistentIndex = m_model->index(0, 0);
569     QVERIFY(persistentIndex.isValid());
570     QVERIFY(m_model->removeColumn(0));
571     QVERIFY(!persistentIndex.isValid());
572 }
573 
checkAboutToBeRemoved()574 void tst_QStandardItemModel::checkAboutToBeRemoved()
575 {
576     QVERIFY(persistent.isValid());
577 }
578 
checkRemoved()579 void tst_QStandardItemModel::checkRemoved()
580 {
581     QVERIFY(!persistent.isValid());
582 }
583 
removingPersistentIndexes()584 void tst_QStandardItemModel::removingPersistentIndexes()
585 {
586     // add 10 rows and columns to model to make it big enough
587     QVERIFY(m_model->insertRows(0, 10));
588     QVERIFY(m_model->insertColumns(0, 10));
589 
590     QObject::connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
591                      this, SLOT(checkAboutToBeRemoved()));
592     QObject::connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
593                      this, SLOT(checkRemoved()));
594     QObject::connect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
595                      this, SLOT(checkAboutToBeRemoved()));
596     QObject::connect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
597                      this, SLOT(checkRemoved()));
598 
599 
600     // test removeRow
601     // add child table 3x3 to parent index(0, 0)
602     QVERIFY(m_model->insertRows(0, 3, m_model->index(0, 0)));
603     QVERIFY(m_model->insertColumns(0, 3, m_model->index(0, 0)));
604 
605     // set child to persistent and delete parent row
606     persistent = m_model->index(0, 0, m_model->index(0, 0));
607     QVERIFY(persistent.isValid());
608     QVERIFY(m_model->removeRow(0));
609 
610     // set persistent to index(0, 0) and remove that row
611     persistent = m_model->index(0, 0);
612     QVERIFY(persistent.isValid());
613     QVERIFY(m_model->removeRow(0));
614 
615 
616     // test removeColumn
617     // add child table 3x3 to parent index (0, 0)
618     QVERIFY(m_model->insertRows(0, 3, m_model->index(0, 0)));
619     QVERIFY(m_model->insertColumns(0, 3, m_model->index(0, 0)));
620 
621     // set child to persistent and delete parent column
622     persistent = m_model->index(0, 0, m_model->index(0, 0));
623     QVERIFY(persistent.isValid());
624     QVERIFY(m_model->removeColumn(0));
625 
626     // set persistent to index(0, 0) and remove that column
627     persistent = m_model->index(0, 0);
628     QVERIFY(persistent.isValid());
629     QVERIFY(m_model->removeColumn(0));
630 
631 
632     QObject::disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
633                         this, SLOT(checkAboutToBeRemoved()));
634     QObject::disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
635                         this, SLOT(checkRemoved()));
636     QObject::disconnect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
637                         this, SLOT(checkAboutToBeRemoved()));
638     QObject::disconnect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
639                         this, SLOT(checkRemoved()));
640 }
641 
updateRowAboutToBeRemoved()642 void tst_QStandardItemModel::updateRowAboutToBeRemoved()
643 {
644     QModelIndex idx = m_model->index(0, 0);
645     QVERIFY(idx.isValid());
646     persistent = idx;
647 }
648 
updatingPersistentIndexes()649 void tst_QStandardItemModel::updatingPersistentIndexes()
650 {
651     QObject::connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
652                      this, SLOT(updateRowAboutToBeRemoved()));
653 
654     persistent = m_model->index(1, 0);
655     QVERIFY(persistent.isValid());
656     QVERIFY(m_model->removeRow(1));
657     QVERIFY(persistent.isValid());
658     QPersistentModelIndex tmp = m_model->index(0, 0);
659     QCOMPARE(persistent, tmp);
660 
661     QObject::disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
662                         this, SLOT(updateRowAboutToBeRemoved()));
663 }
664 
modelChanged(ModelChanged change,const QModelIndex & parent,int first,int last)665 void tst_QStandardItemModel::modelChanged(ModelChanged change, const QModelIndex &parent,
666                                           int first, int last)
667 {
668     rcParent[change] = parent;
669     rcFirst[change] = first;
670     rcLast[change] = last;
671 }
672 
673 
checkChildren()674 void tst_QStandardItemModel::checkChildren()
675 {
676     QStandardItemModel model(0, 0);
677     QCOMPARE(model.rowCount(), 0);
678     QCOMPARE(model.columnCount(), 0);
679     QVERIFY(!model.hasChildren());
680 
681     QVERIFY(model.insertRows(0, 1));
682     QVERIFY(!model.hasChildren());
683     QCOMPARE(model.rowCount(), 1);
684     QCOMPARE(model.columnCount(), 0);
685 
686     QVERIFY(model.insertColumns(0, 1));
687     QVERIFY(model.hasChildren());
688     QCOMPARE(model.rowCount(), 1);
689     QCOMPARE(model.columnCount(), 1);
690 
691     QModelIndex idx = model.index(0, 0);
692     QVERIFY(!model.hasChildren(idx));
693     QCOMPARE(model.rowCount(idx), 0);
694     QCOMPARE(model.columnCount(idx), 0);
695 
696     QVERIFY(model.insertRows(0, 1, idx));
697     QVERIFY(!model.hasChildren(idx));
698     QCOMPARE(model.rowCount(idx), 1);
699     QCOMPARE(model.columnCount(idx), 0);
700 
701     QVERIFY(model.insertColumns(0, 1, idx));
702     QVERIFY(model.hasChildren(idx));
703     QCOMPARE(model.rowCount(idx), 1);
704     QCOMPARE(model.columnCount(idx), 1);
705 
706     QModelIndex idx2 = model.index(0, 0, idx);
707     QVERIFY(!model.hasChildren(idx2));
708     QCOMPARE(model.rowCount(idx2), 0);
709     QCOMPARE(model.columnCount(idx2), 0);
710 
711     QVERIFY(model.removeRows(0, 1, idx));
712     QVERIFY(model.hasChildren());
713     QCOMPARE(model.rowCount(), 1);
714     QCOMPARE(model.columnCount(), 1);
715     QVERIFY(!model.hasChildren(idx));
716     QCOMPARE(model.rowCount(idx), 0);
717     QCOMPARE(model.columnCount(idx), 1);
718 
719     QVERIFY(model.removeRows(0, 1));
720     QVERIFY(!model.hasChildren());
721     QCOMPARE(model.rowCount(), 0);
722     QCOMPARE(model.columnCount(), 1);
723 }
724 
data()725 void tst_QStandardItemModel::data()
726 {
727     // bad args
728     m_model->setData(QModelIndex(), "bla", Qt::DisplayRole);
729 
730     QIcon icon;
731     for (int r=0; r < m_model->rowCount(); ++r) {
732         for (int c=0; c < m_model->columnCount(); ++c) {
733             m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
734             m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole);
735             m_model->setData(m_model->index(r,c), icon, Qt::DecorationRole);
736         }
737     }
738 
739     QVERIFY(m_model->data(m_model->index(0, 0), Qt::DisplayRole).toString() == "initialitem");
740     QVERIFY(m_model->data(m_model->index(0, 0), Qt::ToolTipRole).toString() == "tooltip");
741 
742 }
743 
clear()744 void tst_QStandardItemModel::clear()
745 {
746     QStandardItemModel model;
747     model.insertColumns(0, 10);
748     model.insertRows(0, 10);
749     QCOMPARE(model.columnCount(), 10);
750     QCOMPARE(model.rowCount(), 10);
751 
752     QSignalSpy modelResetSpy(&model, SIGNAL(modelReset()));
753     QSignalSpy layoutChangedSpy(&model, SIGNAL(layoutChanged()));
754     QSignalSpy rowsRemovedSpy(&model, SIGNAL(rowsRemoved(QModelIndex, int, int)));
755     model.clear();
756 
757     QCOMPARE(modelResetSpy.count(), 1);
758     QCOMPARE(layoutChangedSpy.count(), 0);
759     QCOMPARE(rowsRemovedSpy.count(), 0);
760     QCOMPARE(model.index(0, 0), QModelIndex());
761     QCOMPARE(model.columnCount(), 0);
762     QCOMPARE(model.rowCount(), 0);
763     QCOMPARE(model.hasChildren(), false);
764 }
765 
sort_data()766 void tst_QStandardItemModel::sort_data()
767 {
768     QTest::addColumn<int>("sortOrder");
769     QTest::addColumn<QStringList>("initial");
770     QTest::addColumn<QStringList>("expected");
771 
772     QTest::newRow("flat descending") << static_cast<int>(Qt::DescendingOrder)
773                                   << (QStringList()
774                                       << "delta"
775                                       << "yankee"
776                                       << "bravo"
777                                       << "lima"
778                                       << "charlie"
779                                       << "juliet"
780                                       << "tango"
781                                       << "hotel"
782                                       << "uniform"
783                                       << "alpha"
784                                       << "echo"
785                                       << "golf"
786                                       << "quebec"
787                                       << "foxtrot"
788                                       << "india"
789                                       << "romeo"
790                                       << "november"
791                                       << "oskar"
792                                       << "zulu"
793                                       << "kilo"
794                                       << "whiskey"
795                                       << "mike"
796                                       << "papa"
797                                       << "sierra"
798                                       << "xray"
799                                       << "viktor")
800                                   << (QStringList()
801                                       << "zulu"
802                                       << "yankee"
803                                       << "xray"
804                                       << "whiskey"
805                                       << "viktor"
806                                       << "uniform"
807                                       << "tango"
808                                       << "sierra"
809                                       << "romeo"
810                                       << "quebec"
811                                       << "papa"
812                                       << "oskar"
813                                       << "november"
814                                       << "mike"
815                                       << "lima"
816                                       << "kilo"
817                                       << "juliet"
818                                       << "india"
819                                       << "hotel"
820                                       << "golf"
821                                       << "foxtrot"
822                                       << "echo"
823                                       << "delta"
824                                       << "charlie"
825                                       << "bravo"
826                                       << "alpha");
827     QTest::newRow("flat ascending") <<  static_cast<int>(Qt::AscendingOrder)
828                                  << (QStringList()
829                                      << "delta"
830                                      << "yankee"
831                                      << "bravo"
832                                      << "lima"
833                                      << "charlie"
834                                      << "juliet"
835                                      << "tango"
836                                      << "hotel"
837                                      << "uniform"
838                                      << "alpha"
839                                      << "echo"
840                                      << "golf"
841                                      << "quebec"
842                                      << "foxtrot"
843                                      << "india"
844                                      << "romeo"
845                                      << "november"
846                                      << "oskar"
847                                      << "zulu"
848                                      << "kilo"
849                                      << "whiskey"
850                                      << "mike"
851                                      << "papa"
852                                      << "sierra"
853                                      << "xray"
854                                      << "viktor")
855                                  << (QStringList()
856                                      << "alpha"
857                                      << "bravo"
858                                      << "charlie"
859                                      << "delta"
860                                      << "echo"
861                                      << "foxtrot"
862                                      << "golf"
863                                      << "hotel"
864                                      << "india"
865                                      << "juliet"
866                                      << "kilo"
867                                      << "lima"
868                                      << "mike"
869                                      << "november"
870                                      << "oskar"
871                                      << "papa"
872                                      << "quebec"
873                                      << "romeo"
874                                      << "sierra"
875                                      << "tango"
876                                      << "uniform"
877                                      << "viktor"
878                                      << "whiskey"
879                                      << "xray"
880                                      << "yankee"
881                                      << "zulu");
882     QStringList list;
883     for (int i=1000; i < 2000; ++i)
884         list.append(QString("Number: %1").arg(i));
885     QTest::newRow("large set ascending") <<  static_cast<int>(Qt::AscendingOrder) << list << list;
886 }
887 
sort()888 void tst_QStandardItemModel::sort()
889 {
890     QFETCH(int, sortOrder);
891     QFETCH(QStringList, initial);
892     QFETCH(QStringList, expected);
893     // prepare model
894     QStandardItemModel model;
895     QVERIFY(model.insertRows(0, initial.count(), QModelIndex()));
896     QCOMPARE(model.rowCount(QModelIndex()), initial.count());
897     model.insertColumns(0, 1, QModelIndex());
898     QCOMPARE(model.columnCount(QModelIndex()), 1);
899     for (int row = 0; row < model.rowCount(QModelIndex()); ++row) {
900         QModelIndex index = model.index(row, 0, QModelIndex());
901         model.setData(index, initial.at(row), Qt::DisplayRole);
902     }
903 
904     QSignalSpy layoutAboutToBeChangedSpy(
905         &model, SIGNAL(layoutAboutToBeChanged()));
906     QSignalSpy layoutChangedSpy(
907         &model, SIGNAL(layoutChanged()));
908 
909     // sort
910     model.sort(0, static_cast<Qt::SortOrder>(sortOrder));
911 
912     QCOMPARE(layoutAboutToBeChangedSpy.count(), 1);
913     QCOMPARE(layoutChangedSpy.count(), 1);
914 
915     // make sure the model is sorted
916     for (int row = 0; row < model.rowCount(QModelIndex()); ++row) {
917         QModelIndex index = model.index(row, 0, QModelIndex());
918         QCOMPARE(model.data(index, Qt::DisplayRole).toString(), expected.at(row));
919     }
920 }
921 
sortRole_data()922 void tst_QStandardItemModel::sortRole_data()
923 {
924     QTest::addColumn<QStringList>("initialText");
925     QTest::addColumn<QVariantList>("initialData");
926     QTest::addColumn<int>("sortRole");
927     QTest::addColumn<int>("sortOrder");
928     QTest::addColumn<QStringList>("expectedText");
929     QTest::addColumn<QVariantList>("expectedData");
930 
931     QTest::newRow("sort ascending with Qt::DisplayRole")
932         << (QStringList() << "b" << "a" << "c")
933         << (QVariantList() << 2 << 3 << 1)
934         << static_cast<int>(Qt::DisplayRole)
935         << static_cast<int>(Qt::AscendingOrder)
936         << (QStringList() << "a" << "b" << "c")
937         << (QVariantList() << 3 << 2 << 1);
938     QTest::newRow("sort ascending with Qt::UserRole")
939         << (QStringList() << "a" << "b" << "c")
940         << (QVariantList() << 3 << 2 << 1)
941         << static_cast<int>(Qt::UserRole)
942         << static_cast<int>(Qt::AscendingOrder)
943         << (QStringList() << "c" << "b" << "a")
944         << (QVariantList() << 1 << 2 << 3);
945 }
946 
sortRole()947 void tst_QStandardItemModel::sortRole()
948 {
949     QFETCH(QStringList, initialText);
950     QFETCH(QVariantList, initialData);
951     QFETCH(int, sortRole);
952     QFETCH(int, sortOrder);
953     QFETCH(QStringList, expectedText);
954     QFETCH(QVariantList, expectedData);
955 
956     QStandardItemModel model;
957     for (int i = 0; i < initialText.count(); ++i) {
958         QStandardItem *item = new QStandardItem;
959         item->setText(initialText.at(i));
960         item->setData(initialData.at(i), Qt::UserRole);
961         model.appendRow(item);
962     }
963     model.setSortRole(sortRole);
964     model.sort(0, static_cast<Qt::SortOrder>(sortOrder));
965     for (int i = 0; i < expectedText.count(); ++i) {
966         QStandardItem *item = model.item(i);
967         QCOMPARE(item->text(), expectedText.at(i));
968         QCOMPARE(item->data(Qt::UserRole), expectedData.at(i));
969     }
970 }
971 
findItems()972 void tst_QStandardItemModel::findItems()
973 {
974     QStandardItemModel model;
975     model.appendRow(new QStandardItem(QLatin1String("foo")));
976     model.appendRow(new QStandardItem(QLatin1String("bar")));
977     model.item(1)->appendRow(new QStandardItem(QLatin1String("foo")));
978     QList<QStandardItem*> matches;
979     matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, 0);
980     QCOMPARE(matches.count(), 2);
981     matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly, 0);
982     QCOMPARE(matches.count(), 1);
983     matches = model.findItems(QLatin1String("food"), Qt::MatchExactly|Qt::MatchRecursive, 0);
984     QCOMPARE(matches.count(), 0);
985     matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, -1);
986     QCOMPARE(matches.count(), 0);
987     matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, 1);
988     QCOMPARE(matches.count(), 0);
989 }
990 
getSetHeaderItem()991 void tst_QStandardItemModel::getSetHeaderItem()
992 {
993     QStandardItemModel model;
994 
995     QCOMPARE(model.horizontalHeaderItem(0), static_cast<QStandardItem*>(0));
996     QStandardItem *hheader = new QStandardItem();
997     model.setHorizontalHeaderItem(0, hheader);
998     QCOMPARE(model.columnCount(), 1);
999     QCOMPARE(model.horizontalHeaderItem(0), hheader);
1000     QCOMPARE(hheader->model(), &model);
1001     model.setHorizontalHeaderItem(0, 0);
1002     QCOMPARE(model.horizontalHeaderItem(0), static_cast<QStandardItem*>(0));
1003 
1004     QCOMPARE(model.verticalHeaderItem(0), static_cast<QStandardItem*>(0));
1005     QStandardItem *vheader = new QStandardItem();
1006     model.setVerticalHeaderItem(0, vheader);
1007     QCOMPARE(model.rowCount(), 1);
1008     QCOMPARE(model.verticalHeaderItem(0), vheader);
1009     QCOMPARE(vheader->model(), &model);
1010     model.setVerticalHeaderItem(0, 0);
1011     QCOMPARE(model.verticalHeaderItem(0), static_cast<QStandardItem*>(0));
1012 }
1013 
indexFromItem()1014 void tst_QStandardItemModel::indexFromItem()
1015 {
1016     QStandardItemModel model;
1017 
1018     QCOMPARE(model.indexFromItem(model.invisibleRootItem()), QModelIndex());
1019 
1020     QStandardItem *item = new QStandardItem;
1021     model.setItem(10, 20, item);
1022     QCOMPARE(item->model(), &model);
1023     QModelIndex itemIndex = model.indexFromItem(item);
1024     QVERIFY(itemIndex.isValid());
1025     QCOMPARE(itemIndex.row(), 10);
1026     QCOMPARE(itemIndex.column(), 20);
1027     QCOMPARE(itemIndex.parent(), QModelIndex());
1028     QCOMPARE(itemIndex.model(), (const QAbstractItemModel*)(&model));
1029 
1030     QStandardItem *child = new QStandardItem;
1031     item->setChild(4, 2, child);
1032     QModelIndex childIndex = model.indexFromItem(child);
1033     QVERIFY(childIndex.isValid());
1034     QCOMPARE(childIndex.row(), 4);
1035     QCOMPARE(childIndex.column(), 2);
1036     QCOMPARE(childIndex.parent(), itemIndex);
1037 
1038     QStandardItem *dummy = new QStandardItem;
1039     QModelIndex noSuchIndex = model.indexFromItem(dummy);
1040     QVERIFY(!noSuchIndex.isValid());
1041     delete dummy;
1042 
1043     noSuchIndex = model.indexFromItem(0);
1044     QVERIFY(!noSuchIndex.isValid());
1045 }
1046 
itemFromIndex()1047 void tst_QStandardItemModel::itemFromIndex()
1048 {
1049     QStandardItemModel model;
1050 
1051     QCOMPARE(model.itemFromIndex(QModelIndex()), (QStandardItem*)0);
1052 
1053     QStandardItem *item = new QStandardItem;
1054     model.setItem(10, 20, item);
1055     QModelIndex itemIndex = model.index(10, 20, QModelIndex());
1056     QVERIFY(itemIndex.isValid());
1057     QCOMPARE(model.itemFromIndex(itemIndex), item);
1058 
1059     QStandardItem *child = new QStandardItem;
1060     item->setChild(4, 2, child);
1061     QModelIndex childIndex = model.index(4, 2, itemIndex);
1062     QVERIFY(childIndex.isValid());
1063     QCOMPARE(model.itemFromIndex(childIndex), child);
1064 
1065     QModelIndex noSuchIndex = model.index(99, 99, itemIndex);
1066     QVERIFY(!noSuchIndex.isValid());
1067 }
1068 
1069 class CustomItem : public QStandardItem
1070 {
1071 public:
CustomItem()1072     CustomItem() : QStandardItem() { }
~CustomItem()1073     ~CustomItem() { }
type() const1074     int type() const {
1075         return UserType;
1076     }
clone() const1077     QStandardItem *clone() const {
1078         return new CustomItem;
1079     }
1080 };
1081 
getSetItemPrototype()1082 void tst_QStandardItemModel::getSetItemPrototype()
1083 {
1084     QStandardItemModel model;
1085     QCOMPARE(model.itemPrototype(), static_cast<const QStandardItem*>(0));
1086 
1087     const CustomItem *proto = new CustomItem;
1088     model.setItemPrototype(proto);
1089     QCOMPARE(model.itemPrototype(), (const QStandardItem*)proto);
1090 
1091     model.setRowCount(1);
1092     model.setColumnCount(1);
1093     QModelIndex index = model.index(0, 0, QModelIndex());
1094     model.setData(index, "foo");
1095     QStandardItem *item = model.itemFromIndex(index);
1096     QVERIFY(item != 0);
1097     QCOMPARE(item->type(), static_cast<int>(QStandardItem::UserType));
1098 
1099     model.setItemPrototype(0);
1100     QCOMPARE(model.itemPrototype(), static_cast<const QStandardItem*>(0));
1101 }
1102 
getSetItemData()1103 void tst_QStandardItemModel::getSetItemData()
1104 {
1105     QMap<int, QVariant> roles;
1106     QLatin1String text("text");
1107     roles.insert(Qt::DisplayRole, text);
1108     QLatin1String statusTip("statusTip");
1109     roles.insert(Qt::StatusTipRole, statusTip);
1110     QLatin1String toolTip("toolTip");
1111     roles.insert(Qt::ToolTipRole, toolTip);
1112     QLatin1String whatsThis("whatsThis");
1113     roles.insert(Qt::WhatsThisRole, whatsThis);
1114     QSize sizeHint(64, 48);
1115     roles.insert(Qt::SizeHintRole, sizeHint);
1116     QFont font;
1117     roles.insert(Qt::FontRole, font);
1118     Qt::Alignment textAlignment(Qt::AlignLeft|Qt::AlignVCenter);
1119     roles.insert(Qt::TextAlignmentRole, int(textAlignment));
1120     QColor backgroundColor(Qt::blue);
1121     roles.insert(Qt::BackgroundRole, backgroundColor);
1122     QColor textColor(Qt::green);
1123     roles.insert(Qt::TextColorRole, textColor);
1124     Qt::CheckState checkState(Qt::PartiallyChecked);
1125     roles.insert(Qt::CheckStateRole, int(checkState));
1126     QLatin1String accessibleText("accessibleText");
1127     roles.insert(Qt::AccessibleTextRole, accessibleText);
1128     QLatin1String accessibleDescription("accessibleDescription");
1129     roles.insert(Qt::AccessibleDescriptionRole, accessibleDescription);
1130 
1131     QStandardItemModel model;
1132     model.insertRows(0, 1);
1133     model.insertColumns(0, 1);
1134     QModelIndex idx = model.index(0, 0, QModelIndex());
1135 
1136     QSignalSpy modelDataChangedSpy(
1137          &model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)));
1138     QVERIFY(model.setItemData(idx, roles));
1139     QCOMPARE(modelDataChangedSpy.count(), 1);
1140     QVERIFY(model.setItemData(idx, roles));
1141     QCOMPARE(modelDataChangedSpy.count(), 1); //it was already changed once
1142     QCOMPARE(model.itemData(idx), roles);
1143 }
1144 
setHeaderLabels_data()1145 void tst_QStandardItemModel::setHeaderLabels_data()
1146 {
1147     QTest::addColumn<int>("rows");
1148     QTest::addColumn<int>("columns");
1149     QTest::addColumn<int>("orientation");
1150     QTest::addColumn<QStringList>("labels");
1151     QTest::addColumn<QStringList>("expectedLabels");
1152 
1153     QTest::newRow("horizontal labels")
1154         << 1
1155         << 4
1156         << int(Qt::Horizontal)
1157         << (QStringList() << "a" << "b" << "c" << "d")
1158         << (QStringList() << "a" << "b" << "c" << "d");
1159     QTest::newRow("vertical labels")
1160         << 4
1161         << 1
1162         << int(Qt::Vertical)
1163         << (QStringList() << "a" << "b" << "c" << "d")
1164         << (QStringList() << "a" << "b" << "c" << "d");
1165     QTest::newRow("too few (horizontal)")
1166         << 1
1167         << 4
1168         << int(Qt::Horizontal)
1169         << (QStringList() << "a" << "b")
1170         << (QStringList() << "a" << "b" << "3" << "4");
1171     QTest::newRow("too few (vertical)")
1172         << 4
1173         << 1
1174         << int(Qt::Vertical)
1175         << (QStringList() << "a" << "b")
1176         << (QStringList() << "a" << "b" << "3" << "4");
1177     QTest::newRow("too many (horizontal)")
1178         << 1
1179         << 2
1180         << int(Qt::Horizontal)
1181         << (QStringList() << "a" << "b" << "c" << "d")
1182         << (QStringList() << "a" << "b" << "c" << "d");
1183     QTest::newRow("too many (vertical)")
1184         << 2
1185         << 1
1186         << int(Qt::Vertical)
1187         << (QStringList() << "a" << "b" << "c" << "d")
1188         << (QStringList() << "a" << "b" << "c" << "d");
1189 }
1190 
setHeaderLabels()1191 void tst_QStandardItemModel::setHeaderLabels()
1192 {
1193     QFETCH(int, rows);
1194     QFETCH(int, columns);
1195     QFETCH(int, orientation);
1196     QFETCH(QStringList, labels);
1197     QFETCH(QStringList, expectedLabels);
1198     QStandardItemModel model(rows, columns);
1199     QSignalSpy columnsInsertedSpy(
1200         &model, SIGNAL(columnsInserted(QModelIndex,int,int)));
1201     QSignalSpy rowsInsertedSpy(
1202         &model, SIGNAL(rowsInserted(QModelIndex,int,int)));
1203     if (orientation == Qt::Horizontal)
1204         model.setHorizontalHeaderLabels(labels);
1205     else
1206         model.setVerticalHeaderLabels(labels);
1207     for (int i = 0; i < expectedLabels.count(); ++i)
1208         QCOMPARE(model.headerData(i, Qt::Orientation(orientation)).toString(), expectedLabels.at(i));
1209     QCOMPARE(columnsInsertedSpy.count(),
1210              (orientation == Qt::Vertical) ? 0 : labels.count() > columns);
1211     QCOMPARE(rowsInsertedSpy.count(),
1212              (orientation == Qt::Horizontal) ? 0 : labels.count() > rows);
1213 }
1214 
itemDataChanged()1215 void tst_QStandardItemModel::itemDataChanged()
1216 {
1217     QStandardItemModel model(6, 4);
1218     QStandardItem item;
1219     QSignalSpy dataChangedSpy(
1220         &model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
1221     QSignalSpy itemChangedSpy(
1222         &model, SIGNAL(itemChanged(QStandardItem *)));
1223 
1224     model.setItem(0, &item);
1225     QCOMPARE(dataChangedSpy.count(), 1);
1226     QCOMPARE(itemChangedSpy.count(), 1);
1227     QModelIndex index = model.indexFromItem(&item);
1228     QList<QVariant> args;
1229     args = dataChangedSpy.takeFirst();
1230     QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
1231     QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
1232     args = itemChangedSpy.takeFirst();
1233     QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
1234 
1235     item.setData(QLatin1String("foo"), Qt::DisplayRole);
1236     QCOMPARE(dataChangedSpy.count(), 1);
1237     QCOMPARE(itemChangedSpy.count(), 1);
1238     args = dataChangedSpy.takeFirst();
1239     QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
1240     QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
1241     args = itemChangedSpy.takeFirst();
1242     QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
1243 
1244     item.setData(item.data(Qt::DisplayRole), Qt::DisplayRole);
1245     QCOMPARE(dataChangedSpy.count(), 0);
1246     QCOMPARE(itemChangedSpy.count(), 0);
1247 
1248     item.setFlags(Qt::ItemIsEnabled);
1249     QCOMPARE(dataChangedSpy.count(), 1);
1250     QCOMPARE(itemChangedSpy.count(), 1);
1251     args = dataChangedSpy.takeFirst();
1252     QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
1253     QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
1254     args = itemChangedSpy.takeFirst();
1255     QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
1256 
1257     item.setFlags(item.flags());
1258     QCOMPARE(dataChangedSpy.count(), 0);
1259     QCOMPARE(itemChangedSpy.count(), 0);
1260 }
1261 
takeHeaderItem()1262 void tst_QStandardItemModel::takeHeaderItem()
1263 {
1264     QStandardItemModel model;
1265     // set header items
1266     QStandardItem *hheader = new QStandardItem();
1267     model.setHorizontalHeaderItem(0, hheader);
1268     QStandardItem *vheader = new QStandardItem();
1269     model.setVerticalHeaderItem(0, vheader);
1270     // take header items
1271     QCOMPARE(model.takeHorizontalHeaderItem(0), hheader);
1272     QCOMPARE(model.takeVerticalHeaderItem(0), vheader);
1273     QCOMPARE(hheader->model(), static_cast<QStandardItemModel*>(0));
1274     QCOMPARE(vheader->model(), static_cast<QStandardItemModel*>(0));
1275     QCOMPARE(model.takeHorizontalHeaderItem(0), static_cast<QStandardItem*>(0));
1276     QCOMPARE(model.takeVerticalHeaderItem(0), static_cast<QStandardItem*>(0));
1277     delete hheader;
1278     delete vheader;
1279 }
1280 
useCase1()1281 void tst_QStandardItemModel::useCase1()
1282 {
1283     const int rows = 5;
1284     const int columns = 8;
1285     QStandardItemModel model(rows, columns);
1286     for (int i = 0; i < model.rowCount(); ++i) {
1287         for (int j = 0; j < model.columnCount(); ++j) {
1288             QCOMPARE(model.item(i, j), static_cast<QStandardItem*>(0));
1289 
1290             QStandardItem *item = new QStandardItem();
1291             model.setItem(i, j, item);
1292             QCOMPARE(item->row(), i);
1293             QCOMPARE(item->column(), j);
1294             QCOMPARE(item->model(), &model);
1295 
1296             QModelIndex index = model.indexFromItem(item);
1297             QCOMPARE(index, model.index(i, j, QModelIndex()));
1298             QStandardItem *sameItem = model.itemFromIndex(index);
1299             QCOMPARE(sameItem, item);
1300         }
1301     }
1302 }
1303 
createChildren(QStandardItemModel * model,QStandardItem * parent,int level)1304 static void createChildren(QStandardItemModel *model, QStandardItem *parent, int level)
1305 {
1306     if (level > 4)
1307         return;
1308     for (int i = 0; i < 4; ++i) {
1309         QCOMPARE(parent->rowCount(), i);
1310         parent->appendRow(QList<QStandardItem*>());
1311         for (int j = 0; j < parent->columnCount(); ++j) {
1312             QStandardItem *item = new QStandardItem();
1313             parent->setChild(i, j, item);
1314             QCOMPARE(item->row(), i);
1315             QCOMPARE(item->column(), j);
1316 
1317             QModelIndex parentIndex = model->indexFromItem(parent);
1318             QModelIndex index = model->indexFromItem(item);
1319             QCOMPARE(index, model->index(i, j, parentIndex));
1320             QStandardItem *theItem = model->itemFromIndex(index);
1321             QCOMPARE(theItem, item);
1322             QStandardItem *theParent = model->itemFromIndex(parentIndex);
1323             QCOMPARE(theParent, (level == 0) ? (QStandardItem*)0 : parent);
1324         }
1325 
1326         {
1327             QStandardItem *item = parent->child(i);
1328             item->setColumnCount(parent->columnCount());
1329             createChildren(model, item, level + 1);
1330         }
1331     }
1332 }
1333 
useCase2()1334 void tst_QStandardItemModel::useCase2()
1335 {
1336     QStandardItemModel model;
1337     model.setColumnCount(2);
1338     createChildren(&model, model.invisibleRootItem(), 0);
1339 }
1340 
useCase3()1341 void tst_QStandardItemModel::useCase3()
1342 {
1343     // create the tree structure first
1344     QStandardItem *childItem = 0;
1345     for (int i = 0; i < 100; ++i) {
1346         QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
1347         if (childItem)
1348             item->appendRow(childItem);
1349         childItem = item;
1350     }
1351 
1352     // add to model as last step
1353     QStandardItemModel model;
1354     model.appendRow(childItem);
1355 
1356     // make sure each item has the correct model and parent
1357     QStandardItem *parentItem = 0;
1358     while (childItem) {
1359         QCOMPARE(childItem->model(), &model);
1360         QCOMPARE(childItem->parent(), parentItem);
1361         parentItem = childItem;
1362         childItem = childItem->child(0);
1363     }
1364 
1365     // take the item, make sure model is set to 0, but that parents are the same
1366     childItem = model.takeItem(0);
1367     {
1368         parentItem = 0;
1369         QStandardItem *item = childItem;
1370         while (item) {
1371             QCOMPARE(item->model(), static_cast<QStandardItemModel*>(0));
1372             QCOMPARE(item->parent(), parentItem);
1373             parentItem = item;
1374             item = item->child(0);
1375         }
1376     }
1377     delete childItem;
1378 }
1379 
rootItemFlags()1380 void tst_QStandardItemModel::rootItemFlags()
1381 {
1382     QStandardItemModel model(6, 4);
1383     QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
1384     QCOMPARE(model.invisibleRootItem()->flags() , Qt::ItemIsDropEnabled);
1385 
1386     Qt::ItemFlags f = Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
1387     model.invisibleRootItem()->setFlags(f);
1388     QCOMPARE(model.invisibleRootItem()->flags() , f);
1389     QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
1390 
1391 #ifndef QT_NO_DRAGANDDROP
1392     model.invisibleRootItem()->setDropEnabled(false);
1393 #endif
1394     QCOMPARE(model.invisibleRootItem()->flags() , Qt::ItemIsEnabled);
1395     QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
1396 }
1397 
compareModels(QStandardItemModel * model1,QStandardItemModel * model2)1398 bool tst_QStandardItemModel::compareModels(QStandardItemModel *model1, QStandardItemModel *model2)
1399 {
1400     return compareItems(model1->invisibleRootItem(), model2->invisibleRootItem());
1401 }
1402 
compareItems(QStandardItem * item1,QStandardItem * item2)1403 bool tst_QStandardItemModel::compareItems(QStandardItem *item1, QStandardItem *item2)
1404 {
1405     if (!item1 && !item2)
1406         return true;
1407     if (!item1 || !item2)
1408         return false;
1409     if (item1->text() != item2->text()){
1410         qDebug() << item1->text() << item2->text();
1411         return false;
1412     }
1413     if (item1->rowCount() != item2->rowCount()) {
1414   //      qDebug() << "RowCount" << item1->text() << item1->rowCount() << item2->rowCount();
1415         return false;
1416     }
1417     if (item1->columnCount() != item2->columnCount()) {
1418   //     qDebug() << "ColumnCount" << item1->text() << item1->columnCount() << item2->columnCount();
1419         return false;
1420     }
1421     for (int row = 0; row < item1->columnCount(); row++)
1422         for (int col = 0; col < item1->columnCount(); col++) {
1423 
1424         if (!compareItems(item1->child(row, col), item2->child(row, col)))
1425             return false;
1426     }
1427     return true;
1428 }
1429 
itemFromText(QStandardItem * parent,const QString & text)1430 static QStandardItem *itemFromText(QStandardItem *parent, const QString &text)
1431 {
1432     QStandardItem *item = 0;
1433     for(int i = 0; i < parent->columnCount(); i++)
1434         for(int j = 0; j < parent->rowCount(); j++) {
1435 
1436         QStandardItem *child = parent->child(j, i);
1437 
1438         if(!child)
1439             continue;
1440 
1441         if (child->text() == text) {
1442             if (item) {
1443                 return 0;
1444             }
1445             item = child;
1446         }
1447 
1448         QStandardItem *candidate = itemFromText(child, text);
1449         if(candidate) {
1450             if (item) {
1451                 return 0;
1452             }
1453             item = candidate;
1454         }
1455     }
1456     return item;
1457 }
1458 
1459 #ifdef QT_BUILD_INTERNAL
indexFromText(QStandardItemModel * model,const QString & text)1460 static QModelIndex indexFromText(QStandardItemModel *model, const QString &text)
1461 {
1462     QStandardItem *item = itemFromText(model->invisibleRootItem(), text);
1463     /*QVERIFY(item);*/
1464     return model->indexFromItem(item);
1465 }
1466 
1467 
1468 struct FriendlyTreeView : public QTreeView
1469 {
1470     friend class tst_QStandardItemModel;
1471 	Q_DECLARE_PRIVATE(QTreeView)
1472 };
1473 #endif
1474 
treeDragAndDrop()1475 void tst_QStandardItemModel::treeDragAndDrop()
1476 {
1477 #ifdef QT_BUILD_INTERNAL
1478     const int nRow = 5;
1479     const int nCol = 3;
1480 
1481     QStandardItemModel model;
1482     QStandardItemModel checkModel;
1483 
1484     for (int i = 0; i < nRow; ++i) {
1485         QList<QStandardItem *> colItems1;
1486         for (int c = 0 ; c < nCol; c ++)
1487             colItems1 << new QStandardItem(QString("item %1 - %0").arg(c).arg(i));
1488         model.appendRow(colItems1);
1489 
1490         for (int j = 0; j < nRow; ++j) {
1491             QList<QStandardItem *> colItems2;
1492             for (int c = 0 ; c < nCol; c ++)
1493                 colItems2 << new QStandardItem(QString("item %1/%2 - %0").arg(c).arg(i).arg(j));
1494             colItems1.at(0)->appendRow(colItems2);
1495 
1496             for (int k = 0; k < nRow; ++k) {
1497                 QList<QStandardItem *> colItems3;
1498                 for (int c = 0 ; c < nCol; c ++)
1499                     colItems3 << new QStandardItem(QString("item %1/%2/%3 - %0").arg(c).arg(i).arg(j).arg(k));
1500                 colItems2.at(0)->appendRow(colItems3);
1501             }
1502         }
1503     }
1504 
1505     for (int i = 0; i < nRow; ++i) {
1506         QList<QStandardItem *> colItems1;
1507         for (int c = 0 ; c < nCol; c ++)
1508             colItems1 << new QStandardItem(QString("item %1 - %0").arg(c).arg(i));
1509         checkModel.appendRow(colItems1);
1510 
1511         for (int j = 0; j < nRow; ++j) {
1512             QList<QStandardItem *> colItems2;
1513             for (int c = 0 ; c < nCol; c ++)
1514                 colItems2 << new QStandardItem(QString("item %1/%2 - %0").arg(c).arg(i).arg(j));
1515             colItems1.at(0)->appendRow(colItems2);
1516 
1517             for (int k = 0; k < nRow; ++k) {
1518                 QList<QStandardItem *> colItems3;
1519                 for (int c = 0 ; c < nCol; c ++)
1520                     colItems3 << new QStandardItem(QString("item %1/%2/%3 - %0").arg(c).arg(i).arg(j).arg(k));
1521                 colItems2.at(0)->appendRow(colItems3);
1522             }
1523         }
1524     }
1525 
1526     QVERIFY(compareModels(&model, &checkModel));
1527 
1528     FriendlyTreeView  view;
1529     view.setModel(&model);
1530     view.expandAll();
1531     view.show();
1532 #ifndef QT_NO_DRAGANDDROP
1533     view.setDragDropMode(QAbstractItemView::InternalMove);
1534 #endif
1535     view.setSelectionMode(QAbstractItemView::ExtendedSelection);
1536 
1537     QItemSelectionModel *selection = view.selectionModel();
1538 
1539     //
1540     // step1  drag  "item 1" and "item 2"   into "item 4"
1541     //
1542     {
1543         selection->clear();
1544         selection->select(QItemSelection(indexFromText(&model, QString("item 1 - 0")),
1545                                         indexFromText(&model, QString("item 1 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1546 
1547         selection->select(QItemSelection(indexFromText(&model, QString("item 2 - 0")),
1548                                         indexFromText(&model, QString("item 2 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1549 
1550         //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
1551         QModelIndexList indexes = view.selectedIndexes();
1552         QMimeData *data = model.mimeData(indexes);
1553         if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 4 - 0")))
1554             view.d_func()->clearOrRemove();
1555         delete data;
1556 
1557         QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
1558         QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
1559         item4->insertRow(0, checkModel.takeRow(1));
1560         item4->insertRow(1, checkModel.takeRow(1));
1561         QVERIFY(compareModels(&model, &checkModel));
1562     }
1563 
1564     //
1565     // step2  drag  "item 3" and "item 3/0"   into "item 4"
1566     //
1567     {
1568         selection->clear();
1569         selection->select(QItemSelection(indexFromText(&model, QString("item 3 - 0")),
1570                                           indexFromText(&model, QString("item 3 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1571 
1572         selection->select(QItemSelection(indexFromText(&model, QString("item 3/0 - 0")),
1573                                         indexFromText(&model, QString("item 3/0 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1574 
1575         //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
1576         QModelIndexList indexes = view.selectedIndexes();
1577         QMimeData *data = model.mimeData(indexes);
1578         if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 4 - 0")))
1579         view.d_func()->clearOrRemove();
1580         delete data;
1581 
1582         QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
1583         QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
1584         item4->insertRow(0, checkModel.takeRow(1));
1585 
1586         QVERIFY(compareModels(&model, &checkModel));
1587     }
1588 
1589     //
1590     // step2  drag  "item 3" and "item 3/0/2"   into "item 0/2"
1591     // ( remember "item 3" is now the first child of "item 4")
1592     //
1593     {
1594         selection->clear();
1595         selection->select(QItemSelection(indexFromText(&model, QString("item 3 - 0")),
1596                                          indexFromText(&model, QString("item 3 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1597 
1598         selection->select(QItemSelection(indexFromText(&model, QString("item 3/0/2 - 0")),
1599                                         indexFromText(&model, QString("item 3/0/2 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1600 
1601         //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
1602         QModelIndexList indexes = view.selectedIndexes();
1603         QMimeData *data = model.mimeData(indexes);
1604         if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 0/2 - 0")))
1605         view.d_func()->clearOrRemove();
1606         delete data;
1607 
1608         QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
1609         QStandardItem *item02 = itemFromText(checkModel.invisibleRootItem(), "item 0/2 - 0");
1610         QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
1611         item02->insertRow(0, item4->takeRow(0));
1612 
1613         QVERIFY(compareModels(&model, &checkModel));
1614     }
1615 #endif
1616 }
1617 
removeRowsAndColumns()1618 void tst_QStandardItemModel::removeRowsAndColumns()
1619 {
1620 #define VERIFY_MODEL \
1621     for (int c = 0; c < col_list.count(); c++) \
1622         for (int r = 0; r < row_list.count(); r++) \
1623             QCOMPARE(model.item(r,c)->text() , row_list[r] + "x" + col_list[c]);
1624 
1625     QVector<QString> row_list = QString("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20").split(',').toVector();
1626     QVector<QString> col_list = row_list;
1627     QStandardItemModel model;
1628     for (int c = 0; c < col_list.count(); c++)
1629         for (int r = 0; r < row_list.count(); r++)
1630             model.setItem(r, c, new QStandardItem(row_list[r] + "x" + col_list[c]));
1631     VERIFY_MODEL
1632 
1633     row_list.remove(3);
1634     model.removeRow(3);
1635     VERIFY_MODEL
1636 
1637     col_list.remove(5);
1638     model.removeColumn(5);
1639     VERIFY_MODEL
1640 
1641     row_list.remove(2, 5);
1642     model.removeRows(2, 5);
1643     VERIFY_MODEL
1644 
1645     col_list.remove(1, 6);
1646     model.removeColumns(1, 6);
1647     VERIFY_MODEL
1648 
1649     QList<QStandardItem *> row_taken = model.takeRow(6);
1650     QCOMPARE(row_taken.count(), col_list.count());
1651     for (int c = 0; c < col_list.count(); c++)
1652         QCOMPARE(row_taken[c]->text() , row_list[6] + "x" + col_list[c]);
1653     row_list.remove(6);
1654     VERIFY_MODEL
1655 
1656     QList<QStandardItem *> col_taken = model.takeColumn(10);
1657     QCOMPARE(col_taken.count(), row_list.count());
1658     for (int r = 0; r < row_list.count(); r++)
1659         QCOMPARE(col_taken[r]->text() , row_list[r] + "x" + col_list[10]);
1660     col_list.remove(10);
1661     VERIFY_MODEL
1662 }
1663 
1664 
1665 QTEST_MAIN(tst_QStandardItemModel)
1666 #include "tst_qstandarditemmodel.moc"
1667