QtBase  v6.3.1
tst_qstandarditemmodel.cpp
Go to the documentation of this file.
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 
30 #include <QTest>
31 #include <QStandardItemModel>
32 #include <QTreeView>
33 #include <QSignalSpy>
34 #include <QAbstractItemModelTester>
35 
36 #include <private/qabstractitemmodel_p.h>
37 #include <private/qtreeview_p.h>
38 
40 {
41  Q_OBJECT
42 
43 public:
45 
46  enum ModelChanged {
55  };
56 
57 public slots:
58  void init();
59  void cleanup();
60 
61 protected slots:
62  void checkAboutToBeRemoved();
63  void checkRemoved();
65 
66  void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
68  void rowsInserted(const QModelIndex &parent, int first, int last)
70  void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
72  void rowsRemoved(const QModelIndex &parent, int first, int last)
73  { modelChanged(RowsRemoved, parent, first, last); }
74  void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
76  void columnsInserted(const QModelIndex &parent, int first, int last)
78  void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
80  void columnsRemoved(const QModelIndex &parent, int first, int last)
82 
83  void modelChanged(ModelChanged change, const QModelIndex &parent, int first, int last);
84 
85 private slots:
86  void insertRow_data();
87  void insertRow();
88  void insertRows();
89  void insertRowsItems();
90  void insertRowInHierarcy();
91  void insertColumn_data();
92  void insertColumn();
93  void insertColumns();
94  void removeRows();
95  void removeColumns();
96  void setHeaderData();
97  void persistentIndexes();
98  void removingPersistentIndexes();
99  void updatingPersistentIndexes();
100 
101  void checkChildren();
102  void data();
103  void clear();
104  void clearItemData();
105  void sort_data();
106  void sort();
107  void sortRole_data();
108  void sortRole();
109  void sortRoleBindings();
110  void findItems();
111  void getSetHeaderItem();
112  void indexFromItem();
113  void itemFromIndex();
114  void getSetItemPrototype();
115  void getSetItemData();
116  void setHeaderLabels_data();
117  void setHeaderLabels();
118  void itemDataChanged();
119  void takeHeaderItem();
120  void useCase1();
121  void useCase2();
122  void useCase3();
123 
124  void setNullChild();
125  void deleteChild();
126 
127  void rootItemFlags();
128 #ifdef QT_BUILD_INTERNAL
129  void treeDragAndDrop();
130 #endif
131  void removeRowsAndColumns();
132 
133  void defaultItemRoles();
134  void itemRoleNames();
135  void getMimeDataWithInvalidModelIndex();
136  void supportedDragDropActions();
137 
138  void taskQTBUG_45114_setItemData();
139  void setItemPersistentIndex();
140  void signalsOnTakeItem();
141  void createPersistentOnLayoutAboutToBeChanged();
142 private:
143  QStandardItemModel *m_model = nullptr;
144  QPersistentModelIndex persistent;
146  QList<int> rcFirst = QList<int>(8, 0);
147  QList<int> rcLast = QList<int>(8, 0);
148  QList<int> currentRoles;
149 
150  //return true if models have the same structure, and all child have the same text
151  static bool compareModels(QStandardItemModel *model1, QStandardItemModel *model2);
152  //return true if models have the same structure, and all child have the same text
153  static bool compareItems(QStandardItem *item1, QStandardItem *item2);
154 };
155 
156 static constexpr int defaultSize = 3;
157 
160 
162 {
163  qRegisterMetaType<QStandardItem*>("QStandardItem*");
164  qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
165  qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>("QAbstractItemModel::LayoutChangeHint");
166  qRegisterMetaType<QList<QPersistentModelIndex>>("QList<QPersistentModelIndex>");
167 }
168 
169 /*
170  This test usually uses a model with a 3x3 table
171  ---------------------------
172  | 0,0 | 0,1 | 0,2 |
173  ---------------------------
174  | 1,0 | 1,1 | 1,2 |
175  ---------------------------
176  | 2,0 | 2,1 | 2,2 |
177  ---------------------------
178 */
180 {
181  m_model = new QStandardItemModel(defaultSize, defaultSize);
190 
199 
201  [this](const QModelIndex &, const QModelIndex &, const QList<int> &roles) {
202  currentRoles = roles;
203  });
204 
205  rcFirst.fill(-1);
206  rcLast.fill(-1);
207 }
208 
210 {
211  m_model->disconnect(this);
212  delete m_model;
213  m_model = nullptr;
214 }
215 
216 void tst_QStandardItemModel::insertRow_data()
217 {
218  QTest::addColumn<int>("insertRow");
219  QTest::addColumn<int>("expectedRow");
220 
221  QTest::newRow("Insert less then 0") << -1 << 0;
222  QTest::newRow("Insert at 0") << 0 << 0;
223  QTest::newRow("Insert beyond count") << defaultSize+1 << defaultSize;
224  QTest::newRow("Insert at count") << defaultSize << defaultSize;
225  QTest::newRow("Insert in the middle") << 1 << 1;
226 }
227 
228 void tst_QStandardItemModel::insertRow()
229 {
230  QFETCH(int, insertRow);
231  QFETCH(int, expectedRow);
232 
233  QIcon icon;
234  // default all initial items to DisplayRole: "initalitem"
235  for (int r = 0; r < m_model->rowCount(); ++r) {
236  for (int c = 0; c < m_model->columnCount(); ++c) {
237  m_model->setData(m_model->index(r, c), "initialitem", Qt::DisplayRole);
238  }
239  }
240 
241  // check that inserts changes rowCount
242  QCOMPARE(m_model->rowCount(), defaultSize);
243  m_model->insertRow(insertRow);
244  if (insertRow >= 0 && insertRow <= defaultSize) {
245  QCOMPARE(m_model->rowCount(), defaultSize + 1);
246 
247  // check that signals were emitted with correct info
248  QCOMPARE(rcFirst[RowsAboutToBeInserted], expectedRow);
249  QCOMPARE(rcLast[RowsAboutToBeInserted], expectedRow);
250  QCOMPARE(rcFirst[RowsInserted], expectedRow);
251  QCOMPARE(rcLast[RowsInserted], expectedRow);
252 
253  //check that the inserted item has different DisplayRole than initial items
254  QVERIFY(m_model->data(m_model->index(expectedRow, 0), Qt::DisplayRole).toString() != QLatin1String("initialitem"));
255  } else {
256  // We inserted something outside the bounds, do nothing
257  QCOMPARE(m_model->rowCount(), defaultSize);
258  QCOMPARE(rcFirst[RowsAboutToBeInserted], -1);
259  QCOMPARE(rcLast[RowsAboutToBeInserted], -1);
260  QCOMPARE(rcFirst[RowsInserted], -1);
261  QCOMPARE(rcLast[RowsInserted], -1);
262  }
263 }
264 
265 void tst_QStandardItemModel::insertRows()
266 {
267  int rowCount = m_model->rowCount();
268  QCOMPARE(rowCount, defaultSize);
269 
270  // insert custom header label
271  QString headerLabel = "custom";
272  m_model->setHeaderData(0, Qt::Vertical, headerLabel);
273 
274  // insert one row
275  m_model->insertRows(0, 1);
276  QCOMPARE(m_model->rowCount(), rowCount + 1);
277  rowCount = m_model->rowCount();
278 
279  // check header data has moved
280  QCOMPARE(m_model->headerData(1, Qt::Vertical).toString(), headerLabel);
281 
282  // insert two rows
283  m_model->insertRows(0, 2);
284  QCOMPARE(m_model->rowCount(), rowCount + 2);
285 
286  // check header data has moved
287  QCOMPARE(m_model->headerData(3, Qt::Vertical).toString(), headerLabel);
288 
289  // do not assert on empty list
290  QStandardItem *si = m_model->invisibleRootItem();
292  si->insertRows(0, 0);
294 }
295 
296 void tst_QStandardItemModel::insertRowsItems()
297 {
298  int rowCount = m_model->rowCount();
299 
301  QStandardItemModel *m = m_model;
302  QStandardItem *hiddenRoot = m->invisibleRootItem();
303  for (int i = 0; i < 3; ++i)
305  hiddenRoot->appendRows(items);
306  QCOMPARE(m_model->rowCount(), rowCount + 3);
307  QCOMPARE(m_model->index(rowCount + 0, 0).data().toInt(), 10);
308  QCOMPARE(m_model->index(rowCount + 1, 0).data().toInt(), 11);
309  QCOMPARE(m_model->index(rowCount + 2, 0).data().toInt(), 12);
310  for (int i = rowCount; i < rowCount + 3; ++i) {
311  QVERIFY(m->item(i));
312  QCOMPARE(m->item(i)->model(), m_model);
313  }
314 }
315 
316 void tst_QStandardItemModel::insertRowInHierarcy()
317 {
318  QVERIFY(m_model->insertRows(0, 1, QModelIndex()));
319  QVERIFY(m_model->insertColumns(0, 1, QModelIndex()));
320  QVERIFY(m_model->hasIndex(0, 0, QModelIndex()));
321 
322  QModelIndex parent = m_model->index(0, 0, QModelIndex());
323  QVERIFY(parent.isValid());
324 
325  QVERIFY(m_model->insertRows(0, 1, parent));
326  QVERIFY(m_model->insertColumns(0, 1, parent));
327  QVERIFY(m_model->hasIndex(0, 0, parent));
328 
329  QModelIndex child = m_model->index(0, 0, parent);
330  QVERIFY(child.isValid());
331 }
332 
333 void tst_QStandardItemModel::insertColumn_data()
334 {
335  QTest::addColumn<int>("insertColumn");
336  QTest::addColumn<int>("expectedColumn");
337 
338  QTest::newRow("Insert less then 0") << -1 << 0;
339  QTest::newRow("Insert at 0") << 0 << 0;
340  QTest::newRow("Insert beyond count") << defaultSize+1 << defaultSize;
341  QTest::newRow("Insert at count") << defaultSize << defaultSize;
342  QTest::newRow("Insert in the middle") << 1 << 1;
343 }
344 
345 void tst_QStandardItemModel::insertColumn()
346 {
347  QFETCH(int, insertColumn);
348  QFETCH(int, expectedColumn);
349 
350  // default all initial items to DisplayRole: "initalitem"
351  for (int r = 0; r < m_model->rowCount(); ++r) {
352  for (int c = 0; c < m_model->columnCount(); ++c) {
353  m_model->setData(m_model->index(r, c), "initialitem", Qt::DisplayRole);
354  }
355  }
356 
357  // check that inserts changes columnCount
358  QCOMPARE(m_model->columnCount(), defaultSize);
359  m_model->insertColumn(insertColumn);
360  if (insertColumn >= 0 && insertColumn <= defaultSize) {
361  QCOMPARE(m_model->columnCount(), defaultSize + 1);
362  // check that signals were emitted with correct info
363  QCOMPARE(rcFirst[ColumnsAboutToBeInserted], expectedColumn);
364  QCOMPARE(rcLast[ColumnsAboutToBeInserted], expectedColumn);
365  QCOMPARE(rcFirst[ColumnsInserted], expectedColumn);
366  QCOMPARE(rcLast[ColumnsInserted], expectedColumn);
367 
368  //check that the inserted item has different DisplayRole than initial items
369  QVERIFY(m_model->data(m_model->index(0, expectedColumn), Qt::DisplayRole).toString() != QLatin1String("initialitem"));
370  } else {
371  // We inserted something outside the bounds, do nothing
372  QCOMPARE(m_model->columnCount(), defaultSize);
373  QCOMPARE(rcFirst[ColumnsAboutToBeInserted], -1);
374  QCOMPARE(rcLast[ColumnsAboutToBeInserted], -1);
375  QCOMPARE(rcFirst[ColumnsInserted], -1);
376  QCOMPARE(rcLast[ColumnsInserted], -1);
377  }
378 
379 }
380 
381 void tst_QStandardItemModel::insertColumns()
382 {
383  int columnCount = m_model->columnCount();
384  QCOMPARE(columnCount, defaultSize);
385 
386  // insert custom header label
387  QString headerLabel = "custom";
388  m_model->setHeaderData(0, Qt::Horizontal, headerLabel);
389 
390  // insert one column
391  m_model->insertColumns(0, 1);
392  QCOMPARE(m_model->columnCount(), columnCount + 1);
393  columnCount = m_model->columnCount();
394 
395  // check header data has moved
396  QCOMPARE(m_model->headerData(1, Qt::Horizontal).toString(), headerLabel);
397 
398  // insert two columns
399  m_model->insertColumns(0, 2);
400  QCOMPARE(m_model->columnCount(), columnCount + 2);
401 
402  // check header data has moved
403  QCOMPARE(m_model->headerData(3, Qt::Horizontal).toString(), headerLabel);
404 
405  // do not assert on empty list
406  QStandardItem *si = m_model->invisibleRootItem();
408  si->insertColumns(0, 0);
409 }
410 
411 void tst_QStandardItemModel::removeRows()
412 {
413  int rowCount = m_model->rowCount();
414  QCOMPARE(rowCount, defaultSize);
415 
416  // insert custom header label
417  QString headerLabel = "custom";
418  m_model->setHeaderData(rowCount - 1, Qt::Vertical, headerLabel);
419 
420  // remove one row
421  m_model->removeRows(0, 1);
422  QCOMPARE(m_model->rowCount(), rowCount - 1);
423  rowCount = m_model->rowCount();
424 
425  // check header data has moved
426  QCOMPARE(m_model->headerData(rowCount - 1, Qt::Vertical).toString(), headerLabel);
427 
428  // remove two rows
429  m_model->removeRows(0, 2);
430  QCOMPARE(m_model->rowCount(), rowCount - 2);
431 }
432 
433 void tst_QStandardItemModel::removeColumns()
434 {
435  int columnCount = m_model->columnCount();
436  QCOMPARE(columnCount, defaultSize);
437 
438  // insert custom header label
439  QString headerLabel = "custom";
440  m_model->setHeaderData(columnCount - 1, Qt::Horizontal, headerLabel);
441 
442  // remove one column
443  m_model->removeColumns(0, 1);
444  QCOMPARE(m_model->columnCount(), columnCount - 1);
445  columnCount = m_model->columnCount();
446 
447  // check header data has moved
448  QCOMPARE(m_model->headerData(columnCount - 1, Qt::Horizontal).toString(), headerLabel);
449 
450  // remove two columns
451  m_model->removeColumns(0, 2);
452  QCOMPARE(m_model->columnCount(), columnCount - 2);
453 }
454 
455 
456 void tst_QStandardItemModel::setHeaderData()
457 {
458  for (int x = 0; x < 2; ++x) {
459  bool vertical = (x == 0);
460  int count = vertical ? m_model->rowCount() : m_model->columnCount();
461  QCOMPARE(count, defaultSize);
462  Qt::Orientation orient = vertical ? Qt::Vertical : Qt::Horizontal;
463 
464  // check default values are ok
465  for (int i = 0; i < count; ++i)
466  QCOMPARE(m_model->headerData(i, orient).toString(), QString::number(i + 1));
467 
468  QSignalSpy headerDataChangedSpy(
470  QSignalSpy dataChangedSpy(
472  // insert custom values and check
473  for (int i = 0; i < count; ++i) {
474  QString customString = QString("custom") + QString::number(i);
475  QCOMPARE(m_model->setHeaderData(i, orient, customString), true);
476  QCOMPARE(headerDataChangedSpy.count(), 1);
477  QCOMPARE(dataChangedSpy.count(), 0);
478  QVariantList args = headerDataChangedSpy.takeFirst();
479  QCOMPARE(qvariant_cast<Qt::Orientation>(args.at(0)), orient);
480  QCOMPARE(args.at(1).toInt(), i);
481  QCOMPARE(args.at(2).toInt(), i);
482  QCOMPARE(m_model->headerData(i, orient).toString(), customString);
483  QCOMPARE(m_model->setHeaderData(i, orient, customString), true);
484  QCOMPARE(headerDataChangedSpy.count(), 0);
485  QCOMPARE(dataChangedSpy.count(), 0);
486  }
487 
488  //check read from invalid sections
489  QVERIFY(!m_model->headerData(count, orient).isValid());
490  QVERIFY(!m_model->headerData(-1, orient).isValid());
491  //check write to invalid section
492  QCOMPARE(m_model->setHeaderData(count, orient, "foo"), false);
493  QCOMPARE(m_model->setHeaderData(-1, orient, "foo"), false);
494  QVERIFY(!m_model->headerData(count, orient).isValid());
495  QVERIFY(!m_model->headerData(-1, orient).isValid());
496  }
497 }
498 
499 void tst_QStandardItemModel::persistentIndexes()
500 {
501  QCOMPARE(m_model->rowCount(), defaultSize);
502  QCOMPARE(m_model->columnCount(), defaultSize);
503 
504  // create a persisten index at 0,0
505  QPersistentModelIndex persistentIndex(m_model->index(0, 0));
506 
507  // verify it is ok and at the correct spot
508  QVERIFY(persistentIndex.isValid());
509  QCOMPARE(persistentIndex.row(), 0);
510  QCOMPARE(persistentIndex.column(), 0);
511 
512  // insert row and check that the persisten index has moved
513  QVERIFY(m_model->insertRow(0));
514  QVERIFY(persistentIndex.isValid());
515  QCOMPARE(persistentIndex.row(), 1);
516  QCOMPARE(persistentIndex.column(), 0);
517 
518  // insert row after the persisten index and see that it stays the same
519  QVERIFY(m_model->insertRow(m_model->rowCount()));
520  QVERIFY(persistentIndex.isValid());
521  QCOMPARE(persistentIndex.row(), 1);
522  QCOMPARE(persistentIndex.column(), 0);
523 
524  // insert column and check that the persisten index has moved
525  QVERIFY(m_model->insertColumn(0));
526  QVERIFY(persistentIndex.isValid());
527  QCOMPARE(persistentIndex.row(), 1);
528  QCOMPARE(persistentIndex.column(), 1);
529 
530  // insert column after the persisten index and see that it stays the same
531  QVERIFY(m_model->insertColumn(m_model->columnCount()));
532  QVERIFY(persistentIndex.isValid());
533  QCOMPARE(persistentIndex.row(), 1);
534  QCOMPARE(persistentIndex.column(), 1);
535 
536  // removes a row beyond the persistent index and see it stays the same
537  QVERIFY(m_model->removeRow(m_model->rowCount() - 1));
538  QVERIFY(persistentIndex.isValid());
539  QCOMPARE(persistentIndex.row(), 1);
540  QCOMPARE(persistentIndex.column(), 1);
541 
542  // removes a column beyond the persistent index and see it stays the same
543  QVERIFY(m_model->removeColumn(m_model->columnCount() - 1));
544  QVERIFY(persistentIndex.isValid());
545  QCOMPARE(persistentIndex.row(), 1);
546  QCOMPARE(persistentIndex.column(), 1);
547 
548  // removes a row before the persistent index and see it moves the same
549  QVERIFY(m_model->removeRow(0));
550  QVERIFY(persistentIndex.isValid());
551  QCOMPARE(persistentIndex.row(), 0);
552  QCOMPARE(persistentIndex.column(), 1);
553 
554  // removes a column before the persistent index and see it moves the same
555  QVERIFY(m_model->removeColumn(0));
556  QVERIFY(persistentIndex.isValid());
557  QCOMPARE(persistentIndex.row(), 0);
558  QCOMPARE(persistentIndex.column(), 0);
559 
560  // remove the row where the persistent index is, and see that it becomes invalid
561  QVERIFY(m_model->removeRow(0));
562  QVERIFY(!persistentIndex.isValid());
563 
564  // remove the row where the persistent index is, and see that it becomes invalid
565  persistentIndex = m_model->index(0, 0);
566  QVERIFY(persistentIndex.isValid());
567  QVERIFY(m_model->removeColumn(0));
568  QVERIFY(!persistentIndex.isValid());
569 }
570 
572 {
573  QVERIFY(persistent.isValid());
574 }
575 
577 {
578  QVERIFY(!persistent.isValid());
579 }
580 
581 void tst_QStandardItemModel::removingPersistentIndexes()
582 {
583  // add 10 rows and columns to model to make it big enough
584  QVERIFY(m_model->insertRows(0, 10));
585  QVERIFY(m_model->insertColumns(0, 10));
586 
595 
596 
597  // test removeRow
598  // add child table 3x3 to parent index(0, 0)
599  QVERIFY(m_model->insertRows(0, 3, m_model->index(0, 0)));
600  QVERIFY(m_model->insertColumns(0, 3, m_model->index(0, 0)));
601 
602  // set child to persistent and delete parent row
603  persistent = m_model->index(0, 0, m_model->index(0, 0));
604  QVERIFY(persistent.isValid());
605  QVERIFY(m_model->removeRow(0));
606 
607  // set persistent to index(0, 0) and remove that row
608  persistent = m_model->index(0, 0);
609  QVERIFY(persistent.isValid());
610  QVERIFY(m_model->removeRow(0));
611 
612 
613  // test removeColumn
614  // add child table 3x3 to parent index (0, 0)
615  QVERIFY(m_model->insertRows(0, 3, m_model->index(0, 0)));
616  QVERIFY(m_model->insertColumns(0, 3, m_model->index(0, 0)));
617 
618  // set child to persistent and delete parent column
619  persistent = m_model->index(0, 0, m_model->index(0, 0));
620  QVERIFY(persistent.isValid());
621  QVERIFY(m_model->removeColumn(0));
622 
623  // set persistent to index(0, 0) and remove that column
624  persistent = m_model->index(0, 0);
625  QVERIFY(persistent.isValid());
626  QVERIFY(m_model->removeColumn(0));
627 
628 
637 }
638 
640 {
641  QModelIndex idx = m_model->index(0, 0);
642  QVERIFY(idx.isValid());
643  persistent = idx;
644 }
645 
646 void tst_QStandardItemModel::updatingPersistentIndexes()
647 {
650 
651  persistent = m_model->index(1, 0);
652  QVERIFY(persistent.isValid());
653  QVERIFY(m_model->removeRow(1));
654  QVERIFY(persistent.isValid());
655  QPersistentModelIndex tmp = m_model->index(0, 0);
656  QCOMPARE(persistent, tmp);
657 
660 }
661 
663  int first, int last)
664 {
665  rcParent[change] = parent;
666  rcFirst[change] = first;
667  rcLast[change] = last;
668 }
669 
670 
671 void tst_QStandardItemModel::checkChildren()
672 {
674  QCOMPARE(model.rowCount(), 0);
675  QCOMPARE(model.columnCount(), 0);
676  QVERIFY(!model.hasChildren());
677 
678  QVERIFY(model.insertRows(0, 1));
679  QVERIFY(!model.hasChildren());
680  QCOMPARE(model.rowCount(), 1);
681  QCOMPARE(model.columnCount(), 0);
682 
683  QVERIFY(model.insertColumns(0, 1));
684  QVERIFY(model.hasChildren());
685  QCOMPARE(model.rowCount(), 1);
686  QCOMPARE(model.columnCount(), 1);
687 
688  QModelIndex idx = model.index(0, 0);
689  QVERIFY(!model.hasChildren(idx));
690  QCOMPARE(model.rowCount(idx), 0);
692 
693  QVERIFY(model.insertRows(0, 1, idx));
694  QVERIFY(!model.hasChildren(idx));
695  QCOMPARE(model.rowCount(idx), 1);
697 
698  QVERIFY(model.insertColumns(0, 1, idx));
699  QVERIFY(model.hasChildren(idx));
700  QCOMPARE(model.rowCount(idx), 1);
702 
703  QModelIndex idx2 = model.index(0, 0, idx);
704  QVERIFY(!model.hasChildren(idx2));
705  QCOMPARE(model.rowCount(idx2), 0);
706  QCOMPARE(model.columnCount(idx2), 0);
707 
708  QVERIFY(model.removeRows(0, 1, idx));
709  QVERIFY(model.hasChildren());
710  QCOMPARE(model.rowCount(), 1);
711  QCOMPARE(model.columnCount(), 1);
712  QVERIFY(!model.hasChildren(idx));
713  QCOMPARE(model.rowCount(idx), 0);
715 
716  QVERIFY(model.removeRows(0, 1));
717  QVERIFY(!model.hasChildren());
718  QCOMPARE(model.rowCount(), 0);
719  QCOMPARE(model.columnCount(), 1);
720 
721  QVERIFY(!model.index(0,0).sibling(100,100).isValid());
722 }
723 
724 void tst_QStandardItemModel::data()
725 {
726  currentRoles.clear();
727  // bad args
728  m_model->setData(QModelIndex(), "bla", Qt::DisplayRole);
729  QVERIFY(currentRoles.isEmpty());
730 
731  QIcon icon;
732  for (int r = 0; r < m_model->rowCount(); ++r) {
733  for (int c = 0; c < m_model->columnCount(); ++c) {
734  m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
735  QCOMPARE(currentRoles, QList<int>({ Qt::DisplayRole, Qt::EditRole }));
736  m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole);
737  QCOMPARE(currentRoles, QList<int> { Qt::ToolTipRole });
738  m_model->setData(m_model->index(r,c), icon, Qt::DecorationRole);
739  QCOMPARE(currentRoles, QList<int> { Qt::DecorationRole });
740  }
741  }
742 
743  QCOMPARE(m_model->data(m_model->index(0, 0), Qt::DisplayRole).toString(), QLatin1String("initialitem"));
744  QCOMPARE(m_model->data(m_model->index(0, 0), Qt::ToolTipRole).toString(), QLatin1String("tooltip"));
745  const QMap<int, QVariant> itmData = m_model->itemData(m_model->index(0, 0));
746  QCOMPARE(itmData.value(Qt::DisplayRole), QLatin1String("initialitem"));
747  QCOMPARE(itmData.value(Qt::ToolTipRole), QLatin1String("tooltip"));
748  QVERIFY(!itmData.contains(Qt::UserRole - 1));
749  QVERIFY(m_model->itemData(QModelIndex()).isEmpty());
750 }
751 
752 void tst_QStandardItemModel::clearItemData()
753 {
754  currentRoles.clear();
755  QVERIFY(!m_model->clearItemData(QModelIndex()));
756  QVERIFY(currentRoles.isEmpty());
757  const QModelIndex idx = m_model->index(0, 0);
758  const QMap<int, QVariant> oldData = m_model->itemData(idx);
759  m_model->setData(idx, QLatin1String("initialitem"), Qt::DisplayRole);
760  m_model->setData(idx, QLatin1String("tooltip"), Qt::ToolTipRole);
761  m_model->setData(idx, 5, Qt::UserRole);
762  currentRoles.clear();
763  QVERIFY(m_model->clearItemData(idx));
764  QCOMPARE(idx.data(Qt::UserRole), QVariant());
767  QCOMPARE(idx.data(Qt::EditRole), QVariant());
768  QVERIFY(currentRoles.isEmpty());
769  m_model->setItemData(idx, oldData);
770  currentRoles.clear();
771 }
772 
773 void tst_QStandardItemModel::clear()
774 {
776  model.insertColumns(0, 10);
777  model.insertRows(0, 10);
778  QCOMPARE(model.columnCount(), 10);
779  QCOMPARE(model.rowCount(), 10);
780 
784 
786 
787  model.clear();
788 
789  QCOMPARE(modelResetSpy.count(), 1);
790  QCOMPARE(layoutChangedSpy.count(), 0);
791  QCOMPARE(rowsRemovedSpy.count(), 0);
792  QCOMPARE(model.index(0, 0), QModelIndex());
793  QCOMPARE(model.columnCount(), 0);
794  QCOMPARE(model.rowCount(), 0);
795  QCOMPARE(model.hasChildren(), false);
796 }
797 
798 void tst_QStandardItemModel::sort_data()
799 {
800  QTest::addColumn<Qt::SortOrder>("sortOrder");
801  QTest::addColumn<QStringList>("initial");
802  QTest::addColumn<QStringList>("expected");
803 
804  const QStringList unsorted(
805  {"delta", "yankee", "bravo", "lima", "charlie", "juliet",
806  "tango", "hotel", "uniform", "alpha", "echo", "golf",
807  "quebec", "foxtrot", "india", "romeo", "november",
808  "oskar", "zulu", "kilo", "whiskey", "mike", "papa",
809  "sierra", "xray" , "viktor"});
810  QStringList sorted = unsorted;
811 
812  std::sort(sorted.begin(), sorted.end());
813  QTest::newRow("flat ascending") << Qt::AscendingOrder
814  << unsorted
815  << sorted;
816  std::reverse(sorted.begin(), sorted.end());
817  QTest::newRow("flat descending") << Qt::DescendingOrder
818  << unsorted
819  << sorted;
821  for (int i = 1000; i < 2000; ++i)
822  list.append(QStringLiteral("Number: ") + QString::number(i));
823  QTest::newRow("large set ascending") << Qt::AscendingOrder << list << list;
824 }
825 
826 void tst_QStandardItemModel::sort()
827 {
828  QFETCH(Qt::SortOrder, sortOrder);
829  QFETCH(QStringList, initial);
830  QFETCH(QStringList, expected);
831  // prepare model
833  QVERIFY(model.insertRows(0, initial.count(), QModelIndex()));
834  QCOMPARE(model.rowCount(QModelIndex()), initial.count());
837  for (int row = 0; row < model.rowCount(QModelIndex()); ++row) {
839  model.setData(index, initial.at(row), Qt::DisplayRole);
840  }
841 
842  QSignalSpy layoutAboutToBeChangedSpy(
844  QSignalSpy layoutChangedSpy(
846 
847  // sort
848  model.sort(0, sortOrder);
849 
850  QCOMPARE(layoutAboutToBeChangedSpy.count(), 1);
851  QCOMPARE(layoutChangedSpy.count(), 1);
852 
853  // make sure the model is sorted
854  for (int row = 0; row < model.rowCount(QModelIndex()); ++row) {
857  }
858 }
859 
860 void tst_QStandardItemModel::sortRole_data()
861 {
862  QTest::addColumn<QStringList>("initialText");
863  QTest::addColumn<QVariantList>("initialData");
864  QTest::addColumn<Qt::ItemDataRole>("sortRole");
865  QTest::addColumn<Qt::SortOrder>("sortOrder");
866  QTest::addColumn<QStringList>("expectedText");
867  QTest::addColumn<QVariantList>("expectedData");
868 
869  QTest::newRow("sort ascending with Qt::DisplayRole")
870  << (QStringList() << "b" << "a" << "c")
871  << (QVariantList() << 2 << 3 << 1)
872  << Qt::DisplayRole
874  << (QStringList() << "a" << "b" << "c")
875  << (QVariantList() << 3 << 2 << 1);
876  QTest::newRow("sort ascending with Qt::UserRole")
877  << (QStringList() << "a" << "b" << "c")
878  << (QVariantList() << 3 << 2 << 1)
879  << Qt::UserRole
881  << (QStringList() << "c" << "b" << "a")
882  << (QVariantList() << 1 << 2 << 3);
883 }
884 
885 void tst_QStandardItemModel::sortRole()
886 {
887  QFETCH(QStringList, initialText);
888  QFETCH(QVariantList, initialData);
889  QFETCH(Qt::ItemDataRole, sortRole);
890  QFETCH(Qt::SortOrder, sortOrder);
891  QFETCH(QStringList, expectedText);
892  QFETCH(QVariantList, expectedData);
893 
895  for (int i = 0; i < initialText.count(); ++i) {
897  item->setText(initialText.at(i));
898  item->setData(initialData.at(i), Qt::UserRole);
899  model.appendRow(item);
900  }
901  model.setSortRole(sortRole);
902  model.sort(0, sortOrder);
903  for (int i = 0; i < expectedText.count(); ++i) {
904  QStandardItem *item = model.item(i);
905  QCOMPARE(item->text(), expectedText.at(i));
906  QCOMPARE(item->data(Qt::UserRole), expectedData.at(i));
907  }
908 }
909 
910 void tst_QStandardItemModel::sortRoleBindings()
911 {
913  QCOMPARE(model.sortRole(), Qt::DisplayRole);
914 
915  QProperty<int> sortRole;
916  model.bindableSortRole().setBinding(Qt::makePropertyBinding(sortRole));
917  sortRole = Qt::UserRole;
918  QCOMPARE(model.sortRole(), Qt::UserRole);
919 
920  QProperty<int> sortRoleObserver;
921  sortRoleObserver.setBinding([&] { return model.sortRole(); });
922  model.setSortRole(Qt::EditRole);
923  QCOMPARE(sortRoleObserver, Qt::EditRole);
924 }
925 
926 void tst_QStandardItemModel::findItems()
927 {
929  model.appendRow(new QStandardItem(QLatin1String("foo")));
930  model.appendRow(new QStandardItem(QLatin1String("bar")));
931  model.item(1)->appendRow(new QStandardItem(QLatin1String("foo")));
932  QList<QStandardItem*> matches;
933  matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, 0);
934  QCOMPARE(matches.count(), 2);
935  matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly, 0);
936  QCOMPARE(matches.count(), 1);
937  matches = model.findItems(QLatin1String("food"), Qt::MatchExactly|Qt::MatchRecursive, 0);
938  QCOMPARE(matches.count(), 0);
939  matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, -1);
940  QCOMPARE(matches.count(), 0);
941  matches = model.findItems(QLatin1String("foo"), Qt::MatchExactly|Qt::MatchRecursive, 1);
942  QCOMPARE(matches.count(), 0);
943 }
944 
945 void tst_QStandardItemModel::getSetHeaderItem()
946 {
948 
949  QCOMPARE(model.horizontalHeaderItem(0), nullptr);
950  QStandardItem *hheader = new QStandardItem();
951  model.setHorizontalHeaderItem(0, hheader);
952  QCOMPARE(model.columnCount(), 1);
953  QCOMPARE(model.horizontalHeaderItem(0), hheader);
954  QCOMPARE(hheader->model(), &model);
955  model.setHorizontalHeaderItem(0, nullptr);
956  QCOMPARE(model.horizontalHeaderItem(0), nullptr);
957 
958  QCOMPARE(model.verticalHeaderItem(0), nullptr);
959  QStandardItem *vheader = new QStandardItem();
960  model.setVerticalHeaderItem(0, vheader);
961  QCOMPARE(model.rowCount(), 1);
962  QCOMPARE(model.verticalHeaderItem(0), vheader);
963  QCOMPARE(vheader->model(), &model);
964  model.setVerticalHeaderItem(0, nullptr);
965  QCOMPARE(model.verticalHeaderItem(0), nullptr);
966 }
967 
968 void tst_QStandardItemModel::indexFromItem()
969 {
971 
972  QCOMPARE(model.indexFromItem(model.invisibleRootItem()), QModelIndex());
973 
975  model.setItem(10, 20, item);
976  QCOMPARE(item->model(), &model);
977  QModelIndex itemIndex = model.indexFromItem(item);
978  QVERIFY(itemIndex.isValid());
979  QCOMPARE(itemIndex.row(), 10);
980  QCOMPARE(itemIndex.column(), 20);
981  QCOMPARE(itemIndex.parent(), QModelIndex());
982  QCOMPARE(itemIndex.model(), &model);
983 
985  item->setChild(4, 2, child);
986  QModelIndex childIndex = model.indexFromItem(child);
987  QVERIFY(childIndex.isValid());
988  QCOMPARE(childIndex.row(), 4);
989  QCOMPARE(childIndex.column(), 2);
990  QCOMPARE(childIndex.parent(), itemIndex);
991 
993  QModelIndex noSuchIndex = model.indexFromItem(dummy);
994  QVERIFY(!noSuchIndex.isValid());
995  delete dummy;
996 
997  noSuchIndex = model.indexFromItem(nullptr);
998  QVERIFY(!noSuchIndex.isValid());
999 }
1000 
1001 void tst_QStandardItemModel::itemFromIndex()
1002 {
1004 
1005  QCOMPARE(model.itemFromIndex(QModelIndex()), nullptr);
1006 
1008  model.setItem(10, 20, item);
1009  QModelIndex itemIndex = model.index(10, 20, QModelIndex());
1010  QVERIFY(itemIndex.isValid());
1011  QCOMPARE(model.itemFromIndex(itemIndex), item);
1012 
1014  item->setChild(4, 2, child);
1015  QModelIndex childIndex = model.index(4, 2, itemIndex);
1016  QVERIFY(childIndex.isValid());
1017  QCOMPARE(model.itemFromIndex(childIndex), child);
1018 
1019  QModelIndex noSuchIndex = model.index(99, 99, itemIndex);
1020  QVERIFY(!noSuchIndex.isValid());
1021 }
1022 
1023 class CustomItem : public QStandardItem
1024 {
1025 public:
1027 
1028  int type() const override { return UserType; }
1029  QStandardItem *clone() const override { return new CustomItem; }
1030 };
1031 
1032 void tst_QStandardItemModel::getSetItemPrototype()
1033 {
1035  QCOMPARE(model.itemPrototype(), nullptr);
1036 
1037  const CustomItem *proto = new CustomItem;
1038  model.setItemPrototype(proto);
1039  QCOMPARE(model.itemPrototype(), proto);
1040 
1041  model.setRowCount(1);
1042  model.setColumnCount(1);
1044  model.setData(index, "foo");
1045  QStandardItem *item = model.itemFromIndex(index);
1046  QVERIFY(item != nullptr);
1047  QCOMPARE(item->type(), static_cast<int>(QStandardItem::UserType));
1048 
1049  model.setItemPrototype(nullptr);
1050  QCOMPARE(model.itemPrototype(), nullptr);
1051 }
1052 
1053 void tst_QStandardItemModel::getSetItemData()
1054 {
1055  QMap<int, QVariant> roles;
1056  QLatin1String text("text");
1057  roles.insert(Qt::DisplayRole, text);
1058  QLatin1String statusTip("statusTip");
1059  roles.insert(Qt::StatusTipRole, statusTip);
1060  QLatin1String toolTip("toolTip");
1061  roles.insert(Qt::ToolTipRole, toolTip);
1062  QLatin1String whatsThis("whatsThis");
1063  roles.insert(Qt::WhatsThisRole, whatsThis);
1064  QSize sizeHint(64, 48);
1065  roles.insert(Qt::SizeHintRole, sizeHint);
1066  QFont font;
1067  roles.insert(Qt::FontRole, font);
1069  roles.insert(Qt::TextAlignmentRole, int(textAlignment));
1072  QColor textColor(Qt::green);
1073  roles.insert(Qt::ForegroundRole, textColor);
1075  roles.insert(Qt::CheckStateRole, int(checkState));
1076  QLatin1String accessibleText("accessibleText");
1077  roles.insert(Qt::AccessibleTextRole, accessibleText);
1078  QLatin1String accessibleDescription("accessibleDescription");
1079  roles.insert(Qt::AccessibleDescriptionRole, accessibleDescription);
1080 
1082  model.insertRows(0, 1);
1083  model.insertColumns(0, 1);
1084  QModelIndex idx = model.index(0, 0, QModelIndex());
1085 
1086  QSignalSpy modelDataChangedSpy(
1088  QVERIFY(model.setItemData(idx, roles));
1089  QCOMPARE(modelDataChangedSpy.count(), 1);
1090  QVERIFY(model.setItemData(idx, roles));
1091  QCOMPARE(modelDataChangedSpy.count(), 1); //it was already changed once
1092  QCOMPARE(model.itemData(idx), roles);
1093 }
1094 
1095 void tst_QStandardItemModel::setHeaderLabels_data()
1096 {
1097  QTest::addColumn<int>("rows");
1098  QTest::addColumn<int>("columns");
1099  QTest::addColumn<Qt::Orientation>("orientation");
1100  QTest::addColumn<QStringList>("labels");
1101  QTest::addColumn<QStringList>("expectedLabels");
1102 
1103  QTest::newRow("horizontal labels")
1104  << 1
1105  << 4
1106  << Qt::Horizontal
1107  << (QStringList() << "a" << "b" << "c" << "d")
1108  << (QStringList() << "a" << "b" << "c" << "d");
1109  QTest::newRow("vertical labels")
1110  << 4
1111  << 1
1112  << Qt::Vertical
1113  << (QStringList() << "a" << "b" << "c" << "d")
1114  << (QStringList() << "a" << "b" << "c" << "d");
1115  QTest::newRow("too few (horizontal)")
1116  << 1
1117  << 4
1118  << Qt::Horizontal
1119  << (QStringList() << "a" << "b")
1120  << (QStringList() << "a" << "b" << "3" << "4");
1121  QTest::newRow("too few (vertical)")
1122  << 4
1123  << 1
1124  << Qt::Vertical
1125  << (QStringList() << "a" << "b")
1126  << (QStringList() << "a" << "b" << "3" << "4");
1127  QTest::newRow("too many (horizontal)")
1128  << 1
1129  << 2
1130  << Qt::Horizontal
1131  << (QStringList() << "a" << "b" << "c" << "d")
1132  << (QStringList() << "a" << "b" << "c" << "d");
1133  QTest::newRow("too many (vertical)")
1134  << 2
1135  << 1
1136  << Qt::Vertical
1137  << (QStringList() << "a" << "b" << "c" << "d")
1138  << (QStringList() << "a" << "b" << "c" << "d");
1139 }
1140 
1141 void tst_QStandardItemModel::setHeaderLabels()
1142 {
1143  QFETCH(int, rows);
1144  QFETCH(int, columns);
1145  QFETCH(Qt::Orientation, orientation);
1146  QFETCH(QStringList, labels);
1147  QFETCH(QStringList, expectedLabels);
1148  QStandardItemModel model(rows, columns);
1149  QSignalSpy columnsInsertedSpy(&model, &QAbstractItemModel::columnsInserted);
1151  if (orientation == Qt::Horizontal)
1152  model.setHorizontalHeaderLabels(labels);
1153  else
1154  model.setVerticalHeaderLabels(labels);
1155  for (int i = 0; i < expectedLabels.count(); ++i)
1156  QCOMPARE(model.headerData(i, orientation).toString(), expectedLabels.at(i));
1157  QCOMPARE(columnsInsertedSpy.count(),
1158  (orientation == Qt::Vertical) ? 0 : labels.count() > columns);
1159  QCOMPARE(rowsInsertedSpy.count(),
1160  (orientation == Qt::Horizontal) ? 0 : labels.count() > rows);
1161 }
1162 
1163 void tst_QStandardItemModel::itemDataChanged()
1164 {
1165  QStandardItemModel model(6, 4);
1169 
1170  model.setItem(0, &item);
1171  QCOMPARE(dataChangedSpy.count(), 1);
1172  QCOMPARE(itemChangedSpy.count(), 1);
1173  QModelIndex index = model.indexFromItem(&item);
1175  args = dataChangedSpy.takeFirst();
1176  QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
1177  QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
1178  args = itemChangedSpy.takeFirst();
1179  QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
1180 
1182  QCOMPARE(dataChangedSpy.count(), 1);
1183  QCOMPARE(itemChangedSpy.count(), 1);
1184  args = dataChangedSpy.takeFirst();
1185  QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
1186  QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
1187  args = itemChangedSpy.takeFirst();
1188  QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
1189 
1191  QCOMPARE(dataChangedSpy.count(), 0);
1192  QCOMPARE(itemChangedSpy.count(), 0);
1193 
1195  QCOMPARE(dataChangedSpy.count(), 1);
1196  QCOMPARE(itemChangedSpy.count(), 1);
1197  args = dataChangedSpy.takeFirst();
1198  QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), index);
1199  QCOMPARE(qvariant_cast<QModelIndex>(args.at(1)), index);
1200  args = itemChangedSpy.takeFirst();
1201  QCOMPARE(qvariant_cast<QStandardItem*>(args.at(0)), &item);
1202 
1203  item.setFlags(item.flags());
1204  QCOMPARE(dataChangedSpy.count(), 0);
1205  QCOMPARE(itemChangedSpy.count(), 0);
1206 }
1207 
1208 void tst_QStandardItemModel::takeHeaderItem()
1209 {
1211  // set header items
1213  model.setHorizontalHeaderItem(0, hheader.get());
1215  model.setVerticalHeaderItem(0, vheader.get());
1216  // take header items
1217  QCOMPARE(model.takeHorizontalHeaderItem(0), hheader.get());
1218  QCOMPARE(model.takeVerticalHeaderItem(0), vheader.get());
1219  QCOMPARE(hheader->model(), nullptr);
1220  QCOMPARE(vheader->model(), nullptr);
1221  QCOMPARE(model.takeHorizontalHeaderItem(0), nullptr);
1222  QCOMPARE(model.takeVerticalHeaderItem(0), nullptr);
1223 }
1224 
1225 void tst_QStandardItemModel::useCase1()
1226 {
1227  const int rows = 5;
1228  const int columns = 8;
1229  QStandardItemModel model(rows, columns);
1230  for (int i = 0; i < model.rowCount(); ++i) {
1231  for (int j = 0; j < model.columnCount(); ++j) {
1232  QCOMPARE(model.item(i, j), nullptr);
1233 
1234  QStandardItem *item = new QStandardItem();
1235  model.setItem(i, j, item);
1236  QCOMPARE(item->row(), i);
1237  QCOMPARE(item->column(), j);
1238  QCOMPARE(item->model(), &model);
1239 
1240  QModelIndex index = model.indexFromItem(item);
1242  QStandardItem *sameItem = model.itemFromIndex(index);
1243  QCOMPARE(sameItem, item);
1244  }
1245  }
1246 }
1247 
1248 static void createChildren(QStandardItemModel *model, QStandardItem *parent, int level)
1249 {
1250  if (level > 4)
1251  return;
1252  for (int i = 0; i < 4; ++i) {
1253  QCOMPARE(parent->rowCount(), i);
1254  parent->appendRow(QList<QStandardItem*>());
1255  for (int j = 0; j < parent->columnCount(); ++j) {
1256  QStandardItem *item = new QStandardItem();
1257  parent->setChild(i, j, item);
1258  QCOMPARE(item->row(), i);
1259  QCOMPARE(item->column(), j);
1260 
1261  QModelIndex parentIndex = model->indexFromItem(parent);
1262  QModelIndex index = model->indexFromItem(item);
1263  QCOMPARE(index, model->index(i, j, parentIndex));
1264  QStandardItem *theItem = model->itemFromIndex(index);
1265  QCOMPARE(theItem, item);
1266  QStandardItem *theParent = model->itemFromIndex(parentIndex);
1267  QCOMPARE(theParent, (level == 0) ? static_cast<QStandardItem *>(nullptr) : parent);
1268  }
1269 
1270  {
1271  QStandardItem *item = parent->child(i);
1272  item->setColumnCount(parent->columnCount());
1273  createChildren(model, item, level + 1);
1274  }
1275  }
1276 }
1277 
1278 void tst_QStandardItemModel::useCase2()
1279 {
1281  model.setColumnCount(2);
1282  createChildren(&model, model.invisibleRootItem(), 0);
1283 }
1284 
1285 void tst_QStandardItemModel::useCase3()
1286 {
1287  // create the tree structure first
1288  QStandardItem *childItem = nullptr;
1289  for (int i = 0; i < 100; ++i) {
1291  if (childItem)
1292  item->appendRow(childItem);
1293  childItem = item;
1294  }
1295 
1296  // add to model as last step
1298  model.appendRow(childItem);
1299 
1300  // make sure each item has the correct model and parent
1301  QStandardItem *parentItem = nullptr;
1302  while (childItem) {
1303  QCOMPARE(childItem->model(), &model);
1304  QCOMPARE(childItem->parent(), parentItem);
1305  parentItem = childItem;
1306  childItem = childItem->child(0);
1307  }
1308 
1309  // take the item, make sure model is set to 0, but that parents are the same
1310  childItem = model.takeItem(0);
1311  {
1312  parentItem = nullptr;
1313  QStandardItem *item = childItem;
1314  while (item) {
1315  QCOMPARE(item->model(), nullptr);
1316  QCOMPARE(item->parent(), parentItem);
1317  parentItem = item;
1318  item = item->child(0);
1319  }
1320  }
1321  delete childItem;
1322 }
1323 
1324 void tst_QStandardItemModel::setNullChild()
1325 {
1327  model.setColumnCount(2);
1328  createChildren(&model, model.invisibleRootItem(), 0);
1329  QStandardItem *item = model.item(0);
1331  item->setChild(0, nullptr);
1332  QCOMPARE(item->child(0), nullptr);
1333  QCOMPARE(spy.count(), 1);
1334 }
1335 
1336 void tst_QStandardItemModel::deleteChild()
1337 {
1339  model.setColumnCount(2);
1340  createChildren(&model, model.invisibleRootItem(), 0);
1341  QStandardItem *item = model.item(0);
1343  delete item->child(0);
1344  QCOMPARE(item->child(0), nullptr);
1345  QCOMPARE(spy.count(), 1);
1346 }
1347 
1348 void tst_QStandardItemModel::rootItemFlags()
1349 {
1350  QStandardItemModel model(6, 4);
1351  QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
1352  QCOMPARE(model.invisibleRootItem()->flags() , Qt::ItemIsDropEnabled);
1353 
1354  Qt::ItemFlags f = Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
1355  model.invisibleRootItem()->setFlags(f);
1356  QCOMPARE(model.invisibleRootItem()->flags() , f);
1357  QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
1358 
1359 #if QT_CONFIG(draganddrop)
1360  model.invisibleRootItem()->setDropEnabled(false);
1361 #endif
1362  QCOMPARE(model.invisibleRootItem()->flags() , Qt::ItemIsEnabled);
1363  QCOMPARE(model.invisibleRootItem()->flags() , model.flags(QModelIndex()));
1364 }
1365 
1366 bool tst_QStandardItemModel::compareModels(QStandardItemModel *model1, QStandardItemModel *model2)
1367 {
1368  return compareItems(model1->invisibleRootItem(), model2->invisibleRootItem());
1369 }
1370 
1371 bool tst_QStandardItemModel::compareItems(QStandardItem *item1, QStandardItem *item2)
1372 {
1373  if (!item1 && !item2)
1374  return true;
1375  if (!item1 || !item2)
1376  return false;
1377  if (item1->text() != item2->text()) {
1378  qDebug() << item1->text() << item2->text();
1379  return false;
1380  }
1381  if (item1->rowCount() != item2->rowCount()) {
1382  // qDebug() << "RowCount" << item1->text() << item1->rowCount() << item2->rowCount();
1383  return false;
1384  }
1385  if (item1->columnCount() != item2->columnCount()) {
1386  // qDebug() << "ColumnCount" << item1->text() << item1->columnCount() << item2->columnCount();
1387  return false;
1388  }
1389  for (int row = 0; row < item1->columnCount(); row++) {
1390  for (int col = 0; col < item1->columnCount(); col++) {
1391  if (!compareItems(item1->child(row, col), item2->child(row, col)))
1392  return false;
1393  }
1394  }
1395  return true;
1396 }
1397 
1398 static QStandardItem *itemFromText(QStandardItem *parent, const QString &text)
1399 {
1400  QStandardItem *item = nullptr;
1401  for (int i = 0; i < parent->columnCount(); i++) {
1402  for (int j = 0; j < parent->rowCount(); j++) {
1403  QStandardItem *child = parent->child(j, i);
1404  if (!child)
1405  continue;
1406 
1407  if (child->text() == text) {
1408  if (item)
1409  return nullptr;
1410  item = child;
1411  }
1412 
1413  QStandardItem *candidate = itemFromText(child, text);
1414  if (candidate) {
1415  if (item)
1416  return nullptr;
1417  item = candidate;
1418  }
1419  }
1420  }
1421  return item;
1422 }
1423 
1424 #ifdef QT_BUILD_INTERNAL
1425 static QModelIndex indexFromText(QStandardItemModel *model, const QString &text)
1426 {
1427  QStandardItem *item = itemFromText(model->invisibleRootItem(), text);
1428  /*QVERIFY(item);*/
1429  return model->indexFromItem(item);
1430 }
1431 
1432 
1433 struct FriendlyTreeView : public QTreeView
1434 {
1435  friend class tst_QStandardItemModel;
1436  Q_DECLARE_PRIVATE(QTreeView)
1437 };
1438 #endif
1439 
1440 #ifdef QT_BUILD_INTERNAL
1441 
1442 static void populateDragAndDropModel(QStandardItemModel &model, int nRow, int nCol)
1443 {
1444  const QString item = QStringLiteral("item ");
1445  const QString dash = QStringLiteral(" - ");
1446  for (int i = 0; i < nRow; ++i) {
1447  const QString iS = QString::number(i);
1448  QList<QStandardItem *> colItems1;
1449  for (int c = 0 ; c < nCol; c ++)
1450  colItems1 << new QStandardItem(item + iS + dash + QString::number(c));
1451  model.appendRow(colItems1);
1452 
1453  for (int j = 0; j < nRow; ++j) {
1454  const QString jS = QString::number(j);
1455  QList<QStandardItem *> colItems2;
1456  for (int c = 0 ; c < nCol; c ++)
1457  colItems2 << new QStandardItem(item + iS + QLatin1Char('/') + jS + dash + QString::number(c));
1458  colItems1.at(0)->appendRow(colItems2);
1459 
1460  for (int k = 0; k < nRow; ++k) {
1461  QList<QStandardItem *> colItems3;
1462  const QString kS = QString::number(k);
1463  for (int c = 0 ; c < nCol; c ++)
1464  colItems3 << new QStandardItem(item + iS + QLatin1Char('/') + jS
1465  + QLatin1Char('/') + kS
1466  + dash + QString::number(c));
1467  colItems2.at(0)->appendRow(colItems3);
1468  }
1469  }
1470  }
1471 }
1472 
1473 void tst_QStandardItemModel::treeDragAndDrop()
1474 {
1475  const int nRow = 5;
1476  const int nCol = 3;
1477 
1479  QStandardItemModel checkModel;
1480 
1481  populateDragAndDropModel(model, nRow, nCol);
1482  populateDragAndDropModel(checkModel, nRow, nCol);
1483 
1484  QVERIFY(compareModels(&model, &checkModel));
1485 
1486  FriendlyTreeView view;
1487  view.setModel(&model);
1488  view.expandAll();
1489  view.show();
1490 #if QT_CONFIG(draganddrop)
1491  view.setDragDropMode(QAbstractItemView::InternalMove);
1492 #endif
1493  view.setSelectionMode(QAbstractItemView::ExtendedSelection);
1494 
1495  QItemSelectionModel *selection = view.selectionModel();
1496 
1497  //
1498  // step1 drag "item 1" and "item 2" into "item 4"
1499  //
1500  {
1501  selection->clear();
1502  selection->select(QItemSelection(indexFromText(&model, QString("item 1 - 0")),
1503  indexFromText(&model, QString("item 1 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1504 
1505  selection->select(QItemSelection(indexFromText(&model, QString("item 2 - 0")),
1506  indexFromText(&model, QString("item 2 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1507 
1508  //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
1509  QModelIndexList indexes = view.selectedIndexes();
1510  QMimeData *data = model.mimeData(indexes);
1511  if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 4 - 0")))
1512  view.d_func()->clearOrRemove();
1513  delete data;
1514 
1515  QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
1516  QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
1517  item4->insertRow(0, checkModel.takeRow(1));
1518  item4->insertRow(1, checkModel.takeRow(1));
1519  QVERIFY(compareModels(&model, &checkModel));
1520  }
1521 
1522  //
1523  // step2 drag "item 3" and "item 3/0" into "item 4"
1524  //
1525  {
1526  selection->clear();
1527  selection->select(QItemSelection(indexFromText(&model, QString("item 3 - 0")),
1528  indexFromText(&model, QString("item 3 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1529 
1530  selection->select(QItemSelection(indexFromText(&model, QString("item 3/0 - 0")),
1531  indexFromText(&model, QString("item 3/0 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1532 
1533  //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
1534  QModelIndexList indexes = view.selectedIndexes();
1535  QMimeData *data = model.mimeData(indexes);
1536  if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 4 - 0")))
1537  view.d_func()->clearOrRemove();
1538  delete data;
1539 
1540  QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
1541  QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
1542  item4->insertRow(0, checkModel.takeRow(1));
1543 
1544  QVERIFY(compareModels(&model, &checkModel));
1545  }
1546 
1547  //
1548  // step2 drag "item 3" and "item 3/0/2" into "item 0/2"
1549  // ( remember "item 3" is now the first child of "item 4")
1550  //
1551  {
1552  selection->clear();
1553  selection->select(QItemSelection(indexFromText(&model, QString("item 3 - 0")),
1554  indexFromText(&model, QString("item 3 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1555 
1556  selection->select(QItemSelection(indexFromText(&model, QString("item 3/0/2 - 0")),
1557  indexFromText(&model, QString("item 3/0/2 - %0").arg(nCol-1))), QItemSelectionModel::Select);
1558 
1559  //code based from QAbstractItemView::startDrag and QAbstractItemView::dropEvent
1560  QModelIndexList indexes = view.selectedIndexes();
1561  QMimeData *data = model.mimeData(indexes);
1562  if(model.dropMimeData(data, Qt::MoveAction, 0, 0, indexFromText(&model, "item 0/2 - 0")))
1563  view.d_func()->clearOrRemove();
1564  delete data;
1565 
1566  QVERIFY(!compareModels(&model, &checkModel)); //the model must be different at this point
1567  QStandardItem *item02 = itemFromText(checkModel.invisibleRootItem(), "item 0/2 - 0");
1568  QStandardItem *item4 = itemFromText(checkModel.invisibleRootItem(), "item 4 - 0");
1569  item02->insertRow(0, item4->takeRow(0));
1570 
1571  QVERIFY(compareModels(&model, &checkModel));
1572  }
1573 }
1574 #endif
1575 
1576 void tst_QStandardItemModel::removeRowsAndColumns()
1577 {
1578 #define VERIFY_MODEL \
1579  for (int c = 0; c < col_list.count(); c++) \
1580  for (int r = 0; r < row_list.count(); r++) \
1581  QCOMPARE(model.item(r,c)->text() , row_list[r] + QLatin1Char('x') + col_list[c]);
1582 
1583  QStringList row_list = QString("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20").split(',');
1584  QStringList col_list = row_list;
1586  for (int c = 0; c < col_list.count(); c++)
1587  for (int r = 0; r < row_list.count(); r++)
1588  model.setItem(r, c, new QStandardItem(row_list[r] + QLatin1Char('x') + col_list[c]));
1589  VERIFY_MODEL
1590 
1591  row_list.remove(3);
1592  model.removeRow(3);
1593  VERIFY_MODEL
1594 
1595  col_list.remove(5);
1596  model.removeColumn(5);
1597  VERIFY_MODEL
1598 
1599  row_list.remove(2, 5);
1600  model.removeRows(2, 5);
1601  VERIFY_MODEL
1602 
1603  col_list.remove(1, 6);
1604  model.removeColumns(1, 6);
1605  VERIFY_MODEL
1606 
1607  QList<QStandardItem *> row_taken = model.takeRow(6);
1608  QCOMPARE(row_taken.count(), col_list.count());
1609  for (int c = 0; c < col_list.count(); c++)
1610  QCOMPARE(row_taken[c]->text() , row_list[6] + QLatin1Char('x') + col_list[c]);
1611  row_list.remove(6);
1612  VERIFY_MODEL
1613 
1614  QList<QStandardItem *> col_taken = model.takeColumn(10);
1615  QCOMPARE(col_taken.count(), row_list.count());
1616  for (int r = 0; r < row_list.count(); r++)
1617  QCOMPARE(col_taken[r]->text() , row_list[r] + QLatin1Char('x') + col_list[10]);
1618  col_list.remove(10);
1619  VERIFY_MODEL
1620 }
1621 
1622 void tst_QStandardItemModel::defaultItemRoles()
1623 {
1626 }
1627 
1628 void tst_QStandardItemModel::itemRoleNames()
1629 {
1630  QStringList row_list = QString("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20").split(',');
1631  QStringList col_list = row_list;
1633  for (int c = 0; c < col_list.count(); c++)
1634  for (int r = 0; r < row_list.count(); r++)
1635  model.setItem(r, c, new QStandardItem(row_list[r] + QLatin1Char('x') + col_list[c]));
1636  VERIFY_MODEL
1637 
1638  QHash<int, QByteArray> newRoleNames;
1639  newRoleNames.insert(Qt::DisplayRole, "Name");
1640  newRoleNames.insert(Qt::DecorationRole, "Avatar");
1641  model.setItemRoleNames(newRoleNames);
1642  QCOMPARE(model.roleNames(), newRoleNames);
1643  VERIFY_MODEL
1644 }
1645 
1646 void tst_QStandardItemModel::getMimeDataWithInvalidModelIndex()
1647 {
1649  QTest::ignoreMessage(QtWarningMsg, "QStandardItemModel::mimeData: No item associated with invalid index");
1651  QVERIFY(!data);
1652 }
1653 
1654 void tst_QStandardItemModel::supportedDragDropActions()
1655 {
1659 }
1660 
1661 void tst_QStandardItemModel::taskQTBUG_45114_setItemData()
1662 {
1665 
1666  QStandardItem *item = new QStandardItem("item");
1667  item->setData(1, Qt::UserRole + 1);
1668  item->setData(2, Qt::UserRole + 2);
1669  model.appendRow(item);
1670 
1671  QModelIndex index = item->index();
1672  QCOMPARE(model.itemData(index).size(), 3);
1673 
1674  QCOMPARE(spy.count(), 0);
1675 
1676  QMap<int, QVariant> roles;
1677 
1678  roles.insert(Qt::UserRole + 1, 1);
1679  roles.insert(Qt::UserRole + 2, 2);
1680  model.setItemData(index, roles);
1681 
1682  QCOMPARE(spy.count(), 0);
1683 
1684  roles.insert(Qt::UserRole + 1, 1);
1685  roles.insert(Qt::UserRole + 2, 2);
1686  roles.insert(Qt::UserRole + 3, QVariant());
1687  model.setItemData(index, roles);
1688 
1689  QCOMPARE(spy.count(), 0);
1690 
1691  roles.clear();
1692  roles.insert(Qt::UserRole + 1, 10);
1693  roles.insert(Qt::UserRole + 3, 12);
1694  model.setItemData(index, roles);
1695 
1696  QCOMPARE(spy.count(), 1);
1697  QMap<int, QVariant> itemRoles = model.itemData(index);
1698 
1699  QCOMPARE(itemRoles.size(), 4);
1700  QCOMPARE(itemRoles[Qt::UserRole + 1].toInt(), 10);
1701  QCOMPARE(itemRoles[Qt::UserRole + 2].toInt(), 2);
1702  QCOMPARE(itemRoles[Qt::UserRole + 3].toInt(), 12);
1703 
1704  roles.clear();
1705  roles.insert(Qt::UserRole + 3, 1);
1706  model.setItemData(index, roles);
1707 
1708  QCOMPARE(spy.count(), 2);
1709 
1710  roles.clear();
1711  roles.insert(Qt::UserRole + 3, QVariant());
1712  model.setItemData(index, roles);
1713 
1714  QCOMPARE(spy.count(), 3);
1715 
1716  itemRoles = model.itemData(index);
1717  QCOMPARE(itemRoles.size(), 3);
1718  QVERIFY(!itemRoles.keys().contains(Qt::UserRole + 3));
1719 }
1720 
1721 void tst_QStandardItemModel::setItemPersistentIndex()
1722 {
1723  QPersistentModelIndex persistentIndex;
1724  // setItem on an already existing item should not destroy the persistent index
1726  persistentIndex = m.index(0, 0);
1727  QVERIFY(!persistentIndex.isValid());
1728 
1729  m.setItem(0, 0, new QStandardItem);
1730  persistentIndex = m.index(0, 0);
1731  QVERIFY(persistentIndex.isValid());
1732  QCOMPARE(persistentIndex.row(), 0);
1733  QCOMPARE(persistentIndex.column(), 0);
1734 
1735  m.setItem(0, 0, new QStandardItem);
1736  QVERIFY(persistentIndex.isValid());
1737 
1738  m.setItem(0, 0, nullptr);
1739  QVERIFY(!persistentIndex.isValid());
1740 }
1741 
1742 void tst_QStandardItemModel::signalsOnTakeItem() // QTBUG-89145
1743 {
1745  m.insertColumns(0, 2);
1746  m.insertRows(0, 5);
1747  for (int i = 0; i < m.rowCount(); ++i) {
1748  for (int j = 0; j < m.columnCount(); ++j)
1749  m.setData(m.index(i, j), i + j);
1750  }
1751  const QModelIndex parentIndex = m.index(1, 0);
1752  m.insertColumns(0, 2, parentIndex);
1753  m.insertRows(0, 2, parentIndex);
1754  for (int i = 0; i < m.rowCount(parentIndex); ++i) {
1755  for (int j = 0; j < m.columnCount(parentIndex); ++j)
1756  m.setData(m.index(i, j, parentIndex), i + j + 100);
1757  }
1758  QAbstractItemModelTester mTester(&m, nullptr);
1759  QSignalSpy columnsRemovedSpy(&m, &QAbstractItemModel::columnsRemoved);
1760  QSignalSpy columnsAboutToBeRemovedSpy(&m, &QAbstractItemModel::columnsAboutToBeRemoved);
1761  QSignalSpy rowsRemovedSpy(&m, &QAbstractItemModel::rowsRemoved);
1762  QSignalSpy rowsAboutToBeRemovedSpy(&m, &QAbstractItemModel::rowsAboutToBeRemoved);
1763  QSignalSpy *const removeSpies[] = {&columnsRemovedSpy, &columnsAboutToBeRemovedSpy, &rowsRemovedSpy, &rowsAboutToBeRemovedSpy};
1764  QSignalSpy dataChangedSpy(&m, &QAbstractItemModel::dataChanged);
1765  QStandardItem *const takenItem = m.takeItem(1, 0);
1766  for (auto &&spy : removeSpies) {
1767  QCOMPARE(spy->count(), 1);
1768  const auto spyArgs = spy->takeFirst();
1769  QCOMPARE(spyArgs.at(0).value<QModelIndex>(), parentIndex);
1770  QCOMPARE(spyArgs.at(1).toInt(), 0);
1771  QCOMPARE(spyArgs.at(2).toInt(), 1);
1772  }
1773  QCOMPARE(dataChangedSpy.count(), 1);
1774  const auto dataChangedSpyArgs = dataChangedSpy.takeFirst();
1775  QCOMPARE(dataChangedSpyArgs.at(0).value<QModelIndex>(), m.index(1, 0));
1776  QCOMPARE(dataChangedSpyArgs.at(1).value<QModelIndex>(), m.index(1, 0));
1777  QCOMPARE(takenItem->data(Qt::EditRole).toInt(), 1);
1778  QCOMPARE(takenItem->rowCount(), 2);
1779  QCOMPARE(takenItem->columnCount(), 2);
1780  for (int i = 0; i < 2; ++i) {
1781  for (int j = 0; j < 2; ++j)
1782  QCOMPARE(takenItem->child(i, j)->data(Qt::EditRole).toInt(), i + j + 100);
1783  }
1784  QCOMPARE(takenItem->model(), nullptr);
1785  QCOMPARE(takenItem->child(0, 0)->model(), nullptr);
1786  QCOMPARE(m.index(1, 0).data(), QVariant());
1787 }
1788 
1789 void tst_QStandardItemModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466
1790 {
1792  QAbstractItemModelTester mTester(&model, nullptr);
1793  model.insertColumn(0);
1794  QCOMPARE(model.columnCount(), 1);
1795  model.insertRows(0, 3);
1796  for (int row = 0; row < 3; ++row)
1797  model.setData(model.index(row, 0), row);
1799  QSignalSpy layoutAboutToBeChangedSpy(&model, &QAbstractItemModel::layoutAboutToBeChanged);
1800  QSignalSpy layoutChangedSpy(&model, &QAbstractItemModel::layoutChanged);
1802  idxList.clear();
1803  for (int row = 0; row < 3; ++row)
1804  idxList << QPersistentModelIndex(model.index(row, 0));
1805  });
1806  connect(&model, &QAbstractItemModel::layoutChanged, this, [&idxList](){
1807  QCOMPARE(idxList.size(), 3);
1808  QCOMPARE(idxList.at(0).row(), 1);
1809  QCOMPARE(idxList.at(0).column(), 0);
1810  QCOMPARE(idxList.at(0).data().toInt(), 0);
1811  QCOMPARE(idxList.at(1).row(), 0);
1812  QCOMPARE(idxList.at(1).column(), 0);
1813  QCOMPARE(idxList.at(1).data().toInt(), -1);
1814  QCOMPARE(idxList.at(2).row(), 2);
1815  QCOMPARE(idxList.at(2).column(), 0);
1816  QCOMPARE(idxList.at(2).data().toInt(), 2);
1817  });
1818  model.setData(model.index(1, 0), -1);
1819  model.sort(0);
1820  QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
1821  QCOMPARE(layoutChangedSpy.size(), 1);
1822 }
1823 
1825 #include "tst_qstandarditemmodel.moc"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
CustomItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent=nullptr)
int type() const override
QStandardItem * clone() const override
virtual Qt::DropActions supportedDropActions() const
void columnsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
Q_INVOKABLE bool hasIndex(int row, int column, const QModelIndex &parent=QModelIndex()) const
void modelReset(QPrivateSignal)
bool removeRow(int row, const QModelIndex &parent=QModelIndex())
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
virtual bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex())
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
bool removeColumn(int column, const QModelIndex &parent=QModelIndex())
void layoutChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
bool insertColumn(int column, const QModelIndex &parent=QModelIndex())
virtual Q_INVOKABLE bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
void headerDataChanged(Qt::Orientation orientation, int first, int last)
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
virtual QMap< int, QVariant > itemData(const QModelIndex &index) const
virtual bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex())
virtual bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &roles)
virtual Qt::DropActions supportedDragActions() const
void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
void columnsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
static const QHash< int, QByteArray > & defaultRoleNames()
The QAbstractItemModelTester class helps testing QAbstractItemModel subclasses.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
The QFont class specifies a query for a font used for drawing text.
Definition: qfont.h:56
void setData(int key, const QVariant &value)
void setFlags(GraphicsItemFlags flags)
QVariant data(int key) const
virtual int type() const
GraphicsItemFlags flags() const
iterator insert(const Key &key, const T &value)
Definition: qhash.h:1228
The QIcon class provides scalable icons in different modes and states.
Definition: qicon.h:56
The QItemSelection class manages information about selected items in a model.
Q_CORE_EXPORT void select(const QModelIndex &topLeft, const QModelIndex &bottomRight)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
qsizetype size() const noexcept
Definition: qlist.h:414
QList< T > & fill(parameter_type t, qsizetype size=-1)
Definition: qlist.h:907
bool isEmpty() const noexcept
Definition: qlist.h:418
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
value_type takeFirst()
Definition: qlist.h:564
qsizetype count() const noexcept
Definition: qlist.h:415
void append(parameter_type t)
Definition: qlist.h:469
void clear()
Definition: qlist.h:445
Definition: qmap.h:222
iterator insert(const Key &key, const T &value)
Definition: qmap.h:719
T value(const Key &key, const T &defaultValue=T()) const
Definition: qmap.h:392
QList< Key > keys() const
Definition: qmap.h:418
bool contains(const Key &key) const
Definition: qmap.h:376
void clear()
Definition: qmap.h:324
size_type size() const
Definition: qmap.h:302
The QMimeData class provides a container for data that records information about its MIME type.
Definition: qmimedata.h:52
The QModelIndex class is used to locate data in a data model.
QVariant data(int role=Qt::DisplayRole) const
constexpr int row() const noexcept
QModelIndex parent() const
constexpr const QAbstractItemModel * model() const noexcept
constexpr int column() const noexcept
constexpr bool isValid() const noexcept
QModelIndex sibling(int row, int column) const
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
QObject * parent() const
Definition: qobject.h:409
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Definition: qobject.cpp:3048
The QPersistentModelIndex class is used to locate data in a data model.
QVariant data(int role=Qt::DisplayRole) const
QPropertyBinding< T > setBinding(const QPropertyBinding< T > &newBinding)
Definition: qproperty.h:443
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
QVariant data(const QModelIndex &item, int role=Qt::DisplayRole) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QHash< int, QByteArray > roleNames() const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
virtual void clear()
bool insertColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
bool removeColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
The QStandardItem class provides an item for use with the QStandardItemModel class.
QStandardItem * child(int row, int column=0) const
void appendRows(const QList< QStandardItem * > &items)
void insertColumns(int column, int count)
void insertRows(int row, const QList< QStandardItem * > &items)
virtual QVariant data(int role=Qt::UserRole+1) const
QStandardItem * parent() const
void insertColumn(int column, const QList< QStandardItem * > &items)
QList< QStandardItem * > takeRow(int row)
QString text() const
void appendRow(const QList< QStandardItem * > &items)
QStandardItemModel * model() const
void insertRow(int row, const QList< QStandardItem * > &items)
The QStandardItemModel class provides a generic model for storing custom data.\inmodule QtGui.
bool removeColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
QList< QStandardItem * > takeRow(int row)
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
bool clearItemData(const QModelIndex &index) override
void insertRow(int row, const QList< QStandardItem * > &items)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QMap< int, QVariant > itemData(const QModelIndex &index) const override
void itemChanged(QStandardItem *item)
void insertColumn(int column, const QList< QStandardItem * > &items)
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &roles) override
bool insertColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QStandardItem * invisibleRootItem() const
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role=Qt::EditRole) override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
The QString class provides a Unicode character string.
Definition: qstring.h:388
const QChar at(qsizetype i) const
Definition: qstring.h:1212
static QString number(int, int base=10)
Definition: qstring.cpp:7538
The QStringList class provides a list of strings.
The QTreeView class provides a default model/view implementation of a tree view.
Definition: qtreeview.h:56
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
bool isValid() const
Definition: qvariant.h:582
int toInt(bool *ok=nullptr) const
Definition: qvariant.cpp:1833
QString toString() const
Definition: qvariant.cpp:1416
void columnsRemoved(const QModelIndex &parent, int first, int last)
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
void columnsInserted(const QModelIndex &parent, int first, int last)
void rowsInserted(const QModelIndex &parent, int first, int last)
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
void modelChanged(ModelChanged change, const QModelIndex &parent, int first, int last)
void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
void rowsRemoved(const QModelIndex &parent, int first, int last)
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
QString text
[meta data]
QSignalSpy spy(myCustomObject, SIGNAL(mySignal(int, QString, double)))
[0]
QCOMPARE(spy.count(), 1)
union Alignment_ Alignment
QColor backgroundColor(const QPalette &pal, const QWidget *widget)
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message)
Definition: qtestcase.cpp:2292
CheckState
Definition: qnamespace.h:1495
@ PartiallyChecked
Definition: qnamespace.h:1497
@ AlignVCenter
Definition: qnamespace.h:180
@ AlignLeft
Definition: qnamespace.h:169
Orientation
Definition: qnamespace.h:123
@ Horizontal
Definition: qnamespace.h:124
@ Vertical
Definition: qnamespace.h:125
@ blue
Definition: qnamespace.h:68
@ green
Definition: qnamespace.h:67
ItemDataRole
Definition: qnamespace.h:1501
@ AccessibleDescriptionRole
Definition: qnamespace.h:1516
@ AccessibleTextRole
Definition: qnamespace.h:1515
@ WhatsThisRole
Definition: qnamespace.h:1507
@ FontRole
Definition: qnamespace.h:1509
@ TextAlignmentRole
Definition: qnamespace.h:1510
@ ForegroundRole
Definition: qnamespace.h:1512
@ UserRole
Definition: qnamespace.h:1527
@ DecorationRole
Definition: qnamespace.h:1503
@ BackgroundRole
Definition: qnamespace.h:1511
@ EditRole
Definition: qnamespace.h:1504
@ CheckStateRole
Definition: qnamespace.h:1513
@ StatusTipRole
Definition: qnamespace.h:1506
@ ToolTipRole
Definition: qnamespace.h:1505
@ DisplayRole
Definition: qnamespace.h:1502
@ SizeHintRole
Definition: qnamespace.h:1518
SortOrder
Definition: qnamespace.h:146
@ DescendingOrder
Definition: qnamespace.h:148
@ AscendingOrder
Definition: qnamespace.h:147
@ CopyAction
Definition: qnamespace.h:1485
@ MoveAction
Definition: qnamespace.h:1486
auto makePropertyBinding(Functor &&f, const QPropertyBindingSourceLocation &location=QT_PROPERTY_DEFAULT_BINDING_LOCATION, std::enable_if_t< std::is_invocable_v< Functor >> *=nullptr)
Definition: qproperty.h:222
@ ItemIsEnabled
Definition: qnamespace.h:1537
@ ItemIsDropEnabled
Definition: qnamespace.h:1535
@ MatchRecursive
Definition: qnamespace.h:1556
@ MatchExactly
Definition: qnamespace.h:1546
#define QString()
Definition: parse-defines.h:51
QList< QModelIndex > QModelIndexList
QList< QString > QStringList
Definition: qcontainerfwd.h:64
@ text
QList< QVariant > QVariantList
Definition: qjsonarray.h:50
#define qDebug
[1]
Definition: qlogging.h:177
@ QtWarningMsg
Definition: qlogging.h:62
#define Q_DECLARE_METATYPE(TYPE)
Definition: qmetatype.h:1417
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLenum GLuint GLint level
GLboolean r
[2]
GLuint index
[2]
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint first
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLenum GLsizei void * row
Definition: qopenglext.h:2747
SSL_CTX int(*) void arg)
#define QStringLiteral(str)
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
QSqlQueryModel * model
[16]
QIcon icon
[15]
QGraphicsItem * item
QItemSelection * selection
[0]
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
QQuickView * view
[0]
QStringList list
[0]
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
const int rowCount
Definition: testtable1.cpp:31
const int columnCount
Definition: testtable2.cpp:31
QThreadStorage< int * > dummy[8]
#define VERIFY_MODEL
C sorted(C c)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent