1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <qabstractitemview.h>
43 #include <QtTest/QtTest>
44 #include <QtGui/QtGui>
45 #include <QtWidgets/QtWidgets>
46 #include <private/qabstractitemview_p.h>
48 Q_DECLARE_METATYPE(QModelIndex)
49 #ifndef QT_NO_DRAGANDDROP
50 Q_DECLARE_METATYPE(QAbstractItemView::DragDropMode)
52 Q_DECLARE_METATYPE(QAbstractItemView::EditTriggers)
53 Q_DECLARE_METATYPE(QAbstractItemView::EditTrigger)
55 static void initStandardTreeModel(QStandardItemModel *model)
58 item = new QStandardItem(QLatin1String("Row 1 Item"));
59 model->insertRow(0, item);
61 item = new QStandardItem(QLatin1String("Row 2 Item"));
62 item->setCheckable(true);
63 model->insertRow(1, item);
65 QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
66 item->setChild(0, childItem);
68 item = new QStandardItem(QLatin1String("Row 3 Item"));
69 item->setIcon(QIcon());
70 model->insertRow(2, item);
73 struct PublicView : public QTreeView
75 inline void executeDelayedItemsLayout()
76 { QTreeView::executeDelayedItemsLayout(); }
78 enum PublicCursorAction {
79 MoveUp = QAbstractItemView::MoveUp,
80 MoveDown = QAbstractItemView::MoveDown,
81 MoveLeft = QAbstractItemView::MoveLeft,
82 MoveRight = QAbstractItemView::MoveRight,
83 MoveHome = QAbstractItemView::MoveHome,
84 MoveEnd = QAbstractItemView::MoveEnd,
85 MovePageUp = QAbstractItemView::MovePageUp,
86 MovePageDown = QAbstractItemView::MovePageDown,
87 MoveNext = QAbstractItemView::MoveNext,
88 MovePrevious = QAbstractItemView::MovePrevious
91 inline QModelIndex moveCursor(PublicCursorAction ca, Qt::KeyboardModifiers kbm)
92 { return QTreeView::moveCursor((CursorAction)ca, kbm); }
94 inline void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
96 QTreeView::setSelection(rect, command);
100 return QTreeView::state();
103 inline int rowHeight(QModelIndex idx) { return QTreeView::rowHeight(idx); }
104 inline int indexRowSizeHint(const QModelIndex &index) const { return QTreeView::indexRowSizeHint(index); }
106 inline QModelIndexList selectedIndexes() const { return QTreeView::selectedIndexes(); }
108 inline QStyleOptionViewItem viewOptions() const { return QTreeView::viewOptions(); }
109 inline int sizeHintForColumn(int column) const { return QTreeView::sizeHintForColumn(column); }
110 QAbstractItemViewPrivate* aiv_priv() { return static_cast<QAbstractItemViewPrivate*>(d_ptr.data()); }
113 class tst_QTreeView : public QObject
119 virtual ~tst_QTreeView();
124 void cleanupTestCase();
128 void selectionOrderTest();
133 // one test per QTreeView property
135 void alternatingRowColors();
136 void currentIndex_data();
138 #ifndef QT_NO_DRAGANDDROP
139 void dragDropMode_data();
141 void dragDropModeFromDragEnabledAndAcceptDrops_data();
142 void dragDropModeFromDragEnabledAndAcceptDrops();
143 void dragDropOverwriteMode();
145 void editTriggers_data();
147 void hasAutoScroll();
148 void horizontalScrollMode();
153 void itemDelegateForColumnOrRow();
154 void keyboardSearch();
156 void openPersistentEditor();
159 // specialized tests below
168 void expandAndCollapse_data();
169 void expandAndCollapse();
170 void expandAndCollapseAll();
171 void expandWithNoChildren();
172 void keyboardNavigation();
173 void headerSections();
174 void moveCursor_data();
176 void setSelection_data();
178 void extendedSelection_data();
179 void extendedSelection();
183 void mouseDoubleClick();
184 void rowsAboutToBeRemoved();
185 void headerSections_unhideSection();
188 void rowsAboutToBeRemoved_move();
189 void resizeColumnToContents();
190 void insertAfterSelect();
191 void removeAfterSelect();
193 void spanningItems();
195 void setSortingEnabled();
199 void removeAndInsertExpandedCol0();
200 void selectionWithHiddenItems();
203 void disabledButCheckable();
204 void sortByColumn_data();
207 void evilModel_data();
210 void indexRowSizeHint();
211 void addRowsWhileSectionsAreHidden();
212 void filterProxyModelCrash();
213 void renderToPixmap_data();
214 void renderToPixmap();
215 void styleOptionViewItem();
216 void keyboardNavigationWithDisabled();
218 // task-specific tests:
219 void task174627_moveLeftToRoot();
220 void task171902_expandWith1stColHidden();
221 void task203696_hidingColumnsAndRowsn();
222 void task211293_removeRootIndex();
223 void task216717_updateChildren();
224 void task220298_selectColumns();
225 void task224091_appendColumns();
226 void task225539_deleteModel();
227 void task230123_setItemsExpandable();
228 void task202039_closePersistentEditor();
229 void task238873_avoidAutoReopening();
230 void task244304_clickOnDecoration();
231 void task246536_scrollbarsNotWorking();
232 void task250683_wrongSectionSize();
233 void task239271_addRowsWithFirstColumnHidden();
234 void task254234_proxySort();
235 void task248022_changeSelection();
236 void task245654_changeModelAndExpandAll();
237 void doubleClickedWithSpans();
238 void taskQTBUG_6450_selectAllWith1stColumnHidden();
239 void taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint();
240 void taskQTBUG_11466_keyboardNavigationRegression();
241 void taskQTBUG_13567_removeLastItemRegression();
242 void taskQTBUG_25333_adjustViewOptionsForIndex();
245 class QtTestModel: public QAbstractItemModel
248 QtTestModel(QObject *parent = 0): QAbstractItemModel(parent),
249 fetched(false), rows(0), cols(0), levels(INT_MAX), wrongIndex(false) { init(); }
251 QtTestModel(int _rows, int _cols, QObject *parent = 0): QAbstractItemModel(parent),
252 fetched(false), rows(_rows), cols(_cols), levels(INT_MAX), wrongIndex(false) { init(); }
255 decorationsEnabled = false;
258 inline qint32 level(const QModelIndex &index) const {
259 return index.isValid() ? qint32(index.internalId()) : qint32(-1);
262 bool canFetchMore(const QModelIndex &) const {
266 void fetchMore(const QModelIndex &) {
270 bool hasChildren(const QModelIndex &parent = QModelIndex()) const {
271 bool hasFetched = fetched;
273 bool r = QAbstractItemModel::hasChildren(parent);
274 fetched = hasFetched;
278 int rowCount(const QModelIndex& parent = QModelIndex()) const {
280 qFatal("%s: rowCount should not be called before fetching", Q_FUNC_INFO);
281 if ((parent.column() > 0) || (level(parent) > levels))
285 int columnCount(const QModelIndex& parent = QModelIndex()) const {
286 if ((parent.column() > 0) || (level(parent) > levels))
291 bool isEditable(const QModelIndex &index) const {
297 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
299 if (row < 0 || column < 0 || (level(parent) > levels) || column >= cols || row >= rows) {
300 return QModelIndex();
302 QModelIndex i = createIndex(row, column, level(parent) + 1);
303 parentHash[i] = parent;
307 QModelIndex parent(const QModelIndex &index) const
309 if (!parentHash.contains(index))
310 return QModelIndex();
311 return parentHash[index];
314 QVariant data(const QModelIndex &idx, int role) const
319 if (role == Qt::DisplayRole) {
320 if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
322 qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(),
323 idx.internalPointer());
326 return QString("[%1,%2,%3] - this item is extra wide").arg(idx.row()).arg(idx.column()).arg(level(idx));
327 return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(level(idx));
329 if (decorationsEnabled && role == Qt::DecorationRole) {
331 pm.fill(QColor::fromHsv((idx.column() % 16)*8 + 64, 254, (idx.row() % 16)*8 + 32));
339 beginRemoveRows(QModelIndex(), rows - 1, rows - 1);
346 beginRemoveRows(QModelIndex(), 0, rows - 1);
351 void removeLastColumn()
353 beginRemoveColumns(QModelIndex(), cols - 1, cols - 1);
358 void removeAllColumns()
360 beginRemoveColumns(QModelIndex(), 0, cols - 1);
367 beginInsertRows(QModelIndex(), rows - 1, rows - 1);
372 void setDecorationsEnabled(bool enable)
374 decorationsEnabled = enable;
377 mutable bool fetched;
378 bool decorationsEnabled;
381 mutable bool wrongIndex;
382 mutable QMap<QModelIndex,QModelIndex> parentHash;
385 tst_QTreeView::tst_QTreeView()
389 tst_QTreeView::~tst_QTreeView()
393 void tst_QTreeView::initTestCase()
395 #ifdef Q_OS_WINCE //disable magic for WindowsCE
396 qApp->setAutoMaximizeThreshold(-1);
398 qRegisterMetaType<QModelIndex>("QModelIndex");
401 void tst_QTreeView::cleanupTestCase()
405 void tst_QTreeView::init()
409 void tst_QTreeView::cleanup()
413 // Testing get/set functions
414 void tst_QTreeView::getSetCheck()
418 // int QTreeView::indentation()
419 // void QTreeView::setIndentation(int)
420 QCOMPARE(obj1.indentation(), 20);
421 obj1.setIndentation(0);
422 QCOMPARE(obj1.indentation(), 0);
423 obj1.setIndentation(INT_MIN);
424 QCOMPARE(obj1.indentation(), INT_MIN);
425 obj1.setIndentation(INT_MAX);
426 QCOMPARE(obj1.indentation(), INT_MAX);
428 // bool QTreeView::rootIsDecorated()
429 // void QTreeView::setRootIsDecorated(bool)
430 QCOMPARE(obj1.rootIsDecorated(), true);
431 obj1.setRootIsDecorated(false);
432 QCOMPARE(obj1.rootIsDecorated(), false);
433 obj1.setRootIsDecorated(true);
434 QCOMPARE(obj1.rootIsDecorated(), true);
436 // bool QTreeView::uniformRowHeights()
437 // void QTreeView::setUniformRowHeights(bool)
438 QCOMPARE(obj1.uniformRowHeights(), false);
439 obj1.setUniformRowHeights(false);
440 QCOMPARE(obj1.uniformRowHeights(), false);
441 obj1.setUniformRowHeights(true);
442 QCOMPARE(obj1.uniformRowHeights(), true);
444 // bool QTreeView::itemsExpandable()
445 // void QTreeView::setItemsExpandable(bool)
446 QCOMPARE(obj1.itemsExpandable(), true);
447 obj1.setItemsExpandable(false);
448 QCOMPARE(obj1.itemsExpandable(), false);
449 obj1.setItemsExpandable(true);
450 QCOMPARE(obj1.itemsExpandable(), true);
452 // bool QTreeView::allColumnsShowFocus
453 // void QTreeView::setAllColumnsShowFocus
454 QCOMPARE(obj1.allColumnsShowFocus(), false);
455 obj1.setAllColumnsShowFocus(false);
456 QCOMPARE(obj1.allColumnsShowFocus(), false);
457 obj1.setAllColumnsShowFocus(true);
458 QCOMPARE(obj1.allColumnsShowFocus(), true);
460 // bool QTreeView::isAnimated
461 // void QTreeView::setAnimated
462 QCOMPARE(obj1.isAnimated(), false);
463 obj1.setAnimated(false);
464 QCOMPARE(obj1.isAnimated(), false);
465 obj1.setAnimated(true);
466 QCOMPARE(obj1.isAnimated(), true);
468 // bool QTreeView::setSortingEnabled
469 // void QTreeView::isSortingEnabled
470 QCOMPARE(obj1.isSortingEnabled(), false);
471 obj1.setSortingEnabled(false);
472 QCOMPARE(obj1.isSortingEnabled(), false);
473 obj1.setSortingEnabled(true);
474 QCOMPARE(obj1.isSortingEnabled(), true);
477 void tst_QTreeView::construction()
481 // QAbstractItemView properties
482 QVERIFY(!view.alternatingRowColors());
483 QCOMPARE(view.currentIndex(), QModelIndex());
484 #ifndef QT_NO_DRAGANDDROP
485 QCOMPARE(view.dragDropMode(), QAbstractItemView::NoDragDrop);
486 QVERIFY(!view.dragDropOverwriteMode());
487 QVERIFY(!view.dragEnabled());
489 QCOMPARE(view.editTriggers(), QAbstractItemView::EditKeyPressed | QAbstractItemView::DoubleClicked);
490 QVERIFY(view.hasAutoScroll());
491 QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerPixel);
492 QCOMPARE(view.iconSize(), QSize());
493 QCOMPARE(view.indexAt(QPoint()), QModelIndex());
494 QVERIFY(!view.indexWidget(QModelIndex()));
495 QVERIFY(qobject_cast<QStyledItemDelegate *>(view.itemDelegate()));
496 QVERIFY(!view.itemDelegateForColumn(-1));
497 QVERIFY(!view.itemDelegateForColumn(0));
498 QVERIFY(!view.itemDelegateForColumn(1));
499 QVERIFY(!view.itemDelegateForRow(-1));
500 QVERIFY(!view.itemDelegateForRow(0));
501 QVERIFY(!view.itemDelegateForRow(1));
502 QVERIFY(!view.model());
503 QCOMPARE(view.rootIndex(), QModelIndex());
504 QCOMPARE(view.selectionBehavior(), QAbstractItemView::SelectRows);
505 QCOMPARE(view.selectionMode(), QAbstractItemView::SingleSelection);
506 QVERIFY(!view.selectionModel());
507 #ifndef QT_NO_DRAGANDDROP
508 QVERIFY(view.showDropIndicator());
510 QCOMPARE(view.QAbstractItemView::sizeHintForColumn(-1), -1); // <- protected in QTreeView
511 QCOMPARE(view.QAbstractItemView::sizeHintForColumn(0), -1); // <- protected in QTreeView
512 QCOMPARE(view.QAbstractItemView::sizeHintForColumn(1), -1); // <- protected in QTreeView
513 QCOMPARE(view.sizeHintForIndex(QModelIndex()), QSize());
514 QCOMPARE(view.sizeHintForRow(-1), -1);
515 QCOMPARE(view.sizeHintForRow(0), -1);
516 QCOMPARE(view.sizeHintForRow(1), -1);
517 QVERIFY(!view.tabKeyNavigation());
518 QCOMPARE(view.textElideMode(), Qt::ElideRight);
519 QCOMPARE(view.verticalScrollMode(), QAbstractItemView::ScrollPerItem);
520 QCOMPARE(view.visualRect(QModelIndex()), QRect());
522 // QTreeView properties
523 QVERIFY(!view.allColumnsShowFocus());
524 QCOMPARE(view.autoExpandDelay(), -1);
525 QCOMPARE(view.columnAt(-1), -1);
526 QCOMPARE(view.columnAt(0), -1);
527 QCOMPARE(view.columnAt(1), -1);
528 QCOMPARE(view.columnViewportPosition(-1), -1);
529 QCOMPARE(view.columnViewportPosition(0), -1);
530 QCOMPARE(view.columnViewportPosition(1), -1);
531 QCOMPARE(view.columnWidth(-1), 0);
532 QCOMPARE(view.columnWidth(0), 0);
533 QCOMPARE(view.columnWidth(1), 0);
534 QVERIFY(view.header());
535 QCOMPARE(view.indentation(), 20);
536 QCOMPARE(view.indexAbove(QModelIndex()), QModelIndex());
537 QCOMPARE(view.indexBelow(QModelIndex()), QModelIndex());
538 QVERIFY(!view.isAnimated());
539 QVERIFY(!view.isColumnHidden(-1));
540 QVERIFY(!view.isColumnHidden(0));
541 QVERIFY(!view.isColumnHidden(1));
542 QVERIFY(!view.isExpanded(QModelIndex()));
543 QVERIFY(!view.isRowHidden(-1, QModelIndex()));
544 QVERIFY(!view.isRowHidden(0, QModelIndex()));
545 QVERIFY(!view.isRowHidden(1, QModelIndex()));
546 QVERIFY(!view.isFirstColumnSpanned(-1, QModelIndex()));
547 QVERIFY(!view.isFirstColumnSpanned(0, QModelIndex()));
548 QVERIFY(!view.isFirstColumnSpanned(1, QModelIndex()));
549 QVERIFY(!view.isSortingEnabled());
550 QVERIFY(view.itemsExpandable());
551 QVERIFY(view.rootIsDecorated());
552 QVERIFY(!view.uniformRowHeights());
553 QCOMPARE(view.visualRect(QModelIndex()), QRect());
554 QVERIFY(!view.wordWrap());
557 void tst_QTreeView::alternatingRowColors()
560 QVERIFY(!view.alternatingRowColors());
561 view.setAlternatingRowColors(true);
562 QVERIFY(view.alternatingRowColors());
563 view.setAlternatingRowColors(false);
564 QVERIFY(!view.alternatingRowColors());
566 // ### Test visual effect.
569 void tst_QTreeView::currentIndex_data()
571 QTest::addColumn<int>("row");
572 QTest::addColumn<int>("column");
573 QTest::addColumn<int>("indexRow");
574 QTest::addColumn<int>("indexColumn");
575 QTest::addColumn<int>("parentIndexRow");
576 QTest::addColumn<int>("parentIndexColumn");
578 QTest::newRow("-1, -1") << -1 << -1 << -1 << -1 << -1 << -1;
579 QTest::newRow("-1, 0") << -1 << 0 << -1 << -1 << -1 << -1;
580 QTest::newRow("0, -1") << 0 << -1 << -1 << -1 << -1 << -1;
581 QTest::newRow("0, 0") << 0 << 0 << 0 << 0 << -1 << -1;
582 QTest::newRow("0, 1") << 0 << 0 << 0 << 0 << -1 << -1;
583 QTest::newRow("1, 0") << 1 << 0 << 1 << 0 << -1 << -1;
584 QTest::newRow("1, 1") << 1 << 1 << -1 << -1 << -1 << -1;
585 QTest::newRow("2, 0") << 2 << 0 << 2 << 0 << -1 << -1;
586 QTest::newRow("2, 1") << 2 << 1 << -1 << -1 << -1 << -1;
587 QTest::newRow("3, -1") << 3 << -1 << -1 << -1 << -1 << -1;
588 QTest::newRow("3, 0") << 3 << 0 << -1 << -1 << -1 << -1;
589 QTest::newRow("3, 1") << 3 << 1 << -1 << -1 << -1 << -1;
592 void tst_QTreeView::currentIndex()
596 QFETCH(int, indexRow);
597 QFETCH(int, indexColumn);
598 QFETCH(int, parentIndexRow);
599 QFETCH(int, parentIndexColumn);
602 QStandardItemModel treeModel;
603 initStandardTreeModel(&treeModel);
604 view.setModel(&treeModel);
606 QCOMPARE(view.currentIndex(), QModelIndex());
607 view.setCurrentIndex(view.model()->index(row, column));
608 QCOMPARE(view.currentIndex().row(), indexRow);
609 QCOMPARE(view.currentIndex().column(), indexColumn);
610 QCOMPARE(view.currentIndex().parent().row(), parentIndexRow);
611 QCOMPARE(view.currentIndex().parent().column(), parentIndexColumn);
613 // ### Test child and grandChild indexes.
616 #ifndef QT_NO_DRAGANDDROP
618 void tst_QTreeView::dragDropMode_data()
620 QTest::addColumn<QAbstractItemView::DragDropMode>("dragDropMode");
621 QTest::addColumn<bool>("acceptDrops");
622 QTest::addColumn<bool>("dragEnabled");
623 QTest::newRow("NoDragDrop") << QAbstractItemView::NoDragDrop << false << false;
624 QTest::newRow("DragOnly") << QAbstractItemView::DragOnly << false << true;
625 QTest::newRow("DropOnly") << QAbstractItemView::DropOnly << true << false;
626 QTest::newRow("DragDrop") << QAbstractItemView::DragDrop << true << true;
627 QTest::newRow("InternalMove") << QAbstractItemView::InternalMove << true << true;
630 void tst_QTreeView::dragDropMode()
632 QFETCH(QAbstractItemView::DragDropMode, dragDropMode);
633 QFETCH(bool, acceptDrops);
634 QFETCH(bool, dragEnabled);
637 QCOMPARE(view.dragDropMode(), QAbstractItemView::NoDragDrop);
638 QVERIFY(!view.acceptDrops());
639 QVERIFY(!view.dragEnabled());
641 view.setDragDropMode(dragDropMode);
642 QCOMPARE(view.dragDropMode(), dragDropMode);
643 QCOMPARE(view.acceptDrops(), acceptDrops);
644 QCOMPARE(view.dragEnabled(), dragEnabled);
646 // ### Test effects of this mode
649 void tst_QTreeView::dragDropModeFromDragEnabledAndAcceptDrops_data()
651 QTest::addColumn<bool>("dragEnabled");
652 QTest::addColumn<bool>("acceptDrops");
653 QTest::addColumn<QAbstractItemView::DragDropMode>("dragDropMode");
654 QTest::addColumn<QAbstractItemView::DragDropMode>("setBehavior");
656 QTest::newRow("NoDragDrop -1") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DragDropMode(-1);
657 QTest::newRow("NoDragDrop 0") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::NoDragDrop;
658 QTest::newRow("NoDragDrop 1") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DragOnly;
659 QTest::newRow("NoDragDrop 2") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DropOnly;
660 QTest::newRow("NoDragDrop 3") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::DragDrop;
661 QTest::newRow("NoDragDrop 4") << false << false << QAbstractItemView::NoDragDrop << QAbstractItemView::InternalMove;
662 QTest::newRow("DragOnly -1") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DragDropMode(-1);
663 QTest::newRow("DragOnly 0") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::NoDragDrop;
664 QTest::newRow("DragOnly 1") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DragOnly;
665 QTest::newRow("DragOnly 2") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DropOnly;
666 QTest::newRow("DragOnly 3") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::DragDrop;
667 QTest::newRow("DragOnly 4") << true << false << QAbstractItemView::DragOnly << QAbstractItemView::InternalMove;
668 QTest::newRow("DropOnly -1") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DragDropMode(-1);
669 QTest::newRow("DropOnly 0") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::NoDragDrop;
670 QTest::newRow("DropOnly 1") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DragOnly;
671 QTest::newRow("DropOnly 2") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DropOnly;
672 QTest::newRow("DropOnly 3") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::DragDrop;
673 QTest::newRow("DropOnly 4") << false << true << QAbstractItemView::DropOnly << QAbstractItemView::InternalMove;
674 QTest::newRow("DragDrop -1") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragDropMode(-1);
675 QTest::newRow("DragDrop 0") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragDropMode(-1);
676 QTest::newRow("DragDrop 1") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::NoDragDrop;
677 QTest::newRow("DragDrop 2") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragOnly;
678 QTest::newRow("DragDrop 3") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DropOnly;
679 QTest::newRow("DragDrop 4") << true << true << QAbstractItemView::DragDrop << QAbstractItemView::DragDrop;
680 QTest::newRow("DragDrop 5") << true << true << QAbstractItemView::InternalMove << QAbstractItemView::InternalMove;
683 void tst_QTreeView::dragDropModeFromDragEnabledAndAcceptDrops()
685 QFETCH(bool, acceptDrops);
686 QFETCH(bool, dragEnabled);
687 QFETCH(QAbstractItemView::DragDropMode, dragDropMode);
688 QFETCH(QAbstractItemView::DragDropMode, setBehavior);
691 QCOMPARE(view.dragDropMode(), QAbstractItemView::NoDragDrop);
693 if (setBehavior != QAbstractItemView::DragDropMode(-1))
694 view.setDragDropMode(setBehavior);
696 view.setAcceptDrops(acceptDrops);
697 view.setDragEnabled(dragEnabled);
698 QCOMPARE(view.dragDropMode(), dragDropMode);
700 // ### Test effects of this mode
703 void tst_QTreeView::dragDropOverwriteMode()
706 QVERIFY(!view.dragDropOverwriteMode());
707 view.setDragDropOverwriteMode(true);
708 QVERIFY(view.dragDropOverwriteMode());
709 view.setDragDropOverwriteMode(false);
710 QVERIFY(!view.dragDropOverwriteMode());
712 // ### This property changes the behavior of dropIndicatorPosition(),
713 // which is protected and called only from within QListWidget and
714 // QTableWidget, from their reimplementations of dropMimeData(). Hard to
719 void tst_QTreeView::editTriggers_data()
721 QTest::addColumn<QAbstractItemView::EditTriggers>("editTriggers");
722 QTest::addColumn<QAbstractItemView::EditTrigger>("triggeredTrigger");
723 QTest::addColumn<bool>("editorOpened");
726 QTest::newRow("NoEditTriggers 0") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
727 << QAbstractItemView::NoEditTriggers << false;
728 QTest::newRow("NoEditTriggers 1") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
729 << QAbstractItemView::CurrentChanged << false;
730 QTest::newRow("NoEditTriggers 2") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
731 << QAbstractItemView::DoubleClicked << false;
732 QTest::newRow("NoEditTriggers 3") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
733 << QAbstractItemView::SelectedClicked << false;
734 QTest::newRow("NoEditTriggers 4") << QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)
735 << QAbstractItemView::EditKeyPressed << false;
738 QTest::newRow("CurrentChanged 0") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
739 << QAbstractItemView::NoEditTriggers << false;
740 QTest::newRow("CurrentChanged 1") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
741 << QAbstractItemView::CurrentChanged << true;
742 QTest::newRow("CurrentChanged 2") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
743 << QAbstractItemView::DoubleClicked << false;
744 QTest::newRow("CurrentChanged 3") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
745 << QAbstractItemView::SelectedClicked << false;
746 QTest::newRow("CurrentChanged 4") << QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)
747 << QAbstractItemView::EditKeyPressed << false;
750 QTest::newRow("DoubleClicked 0") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
751 << QAbstractItemView::NoEditTriggers << false;
752 QTest::newRow("DoubleClicked 1") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
753 << QAbstractItemView::CurrentChanged << false;
754 QTest::newRow("DoubleClicked 2") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
755 << QAbstractItemView::DoubleClicked << true;
756 QTest::newRow("DoubleClicked 3") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
757 << QAbstractItemView::SelectedClicked << false;
758 QTest::newRow("DoubleClicked 4") << QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)
759 << QAbstractItemView::EditKeyPressed << false;
762 QTest::newRow("SelectedClicked 0") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
763 << QAbstractItemView::NoEditTriggers << false;
764 QTest::newRow("SelectedClicked 1") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
765 << QAbstractItemView::CurrentChanged << false;
766 QTest::newRow("SelectedClicked 2") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
767 << QAbstractItemView::DoubleClicked << false;
768 QTest::newRow("SelectedClicked 3") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
769 << QAbstractItemView::SelectedClicked << true;
770 QTest::newRow("SelectedClicked 4") << QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)
771 << QAbstractItemView::EditKeyPressed << false;
774 QTest::newRow("EditKeyPressed 0") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
775 << QAbstractItemView::NoEditTriggers << false;
776 QTest::newRow("EditKeyPressed 1") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
777 << QAbstractItemView::CurrentChanged << false;
778 QTest::newRow("EditKeyPressed 2") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
779 << QAbstractItemView::DoubleClicked << false;
780 QTest::newRow("EditKeyPressed 3") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
781 << QAbstractItemView::SelectedClicked << false;
782 QTest::newRow("EditKeyPressed 4") << QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)
783 << QAbstractItemView::EditKeyPressed << true;
786 void tst_QTreeView::editTriggers()
788 QFETCH(QAbstractItemView::EditTriggers, editTriggers);
789 QFETCH(QAbstractItemView::EditTrigger, triggeredTrigger);
790 QFETCH(bool, editorOpened);
793 QStandardItemModel treeModel;
794 initStandardTreeModel(&treeModel);
795 view.setModel(&treeModel);
798 QCOMPARE(view.editTriggers(), QAbstractItemView::EditKeyPressed | QAbstractItemView::DoubleClicked);
800 // Initialize the first index
801 view.setCurrentIndex(view.model()->index(0, 0));
803 // Verify that we don't have any editor initially
804 QVERIFY(!qFindChild<QLineEdit *>(&view, QString()));
807 view.setEditTriggers(editTriggers);
809 // Interact with the view
810 switch (triggeredTrigger) {
811 case QAbstractItemView::NoEditTriggers:
812 // Do nothing, the editor shouldn't be there
814 case QAbstractItemView::CurrentChanged:
815 // Change the index to open an editor
816 view.setCurrentIndex(view.model()->index(1, 0));
818 case QAbstractItemView::DoubleClicked:
819 // Doubleclick the center of the current cell
820 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
821 view.visualRect(view.model()->index(0, 0)).center());
822 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0,
823 view.visualRect(view.model()->index(0, 0)).center());
825 case QAbstractItemView::SelectedClicked:
826 // Click the center of the current cell
827 view.selectionModel()->select(view.model()->index(0, 0), QItemSelectionModel::Select);
828 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
829 view.visualRect(view.model()->index(0, 0)).center());
830 QTest::qWait(int(QApplication::doubleClickInterval() * 1.5));
832 case QAbstractItemView::EditKeyPressed:
835 // Mac OS X uses Enter for editing
836 QTest::keyPress(&view, Qt::Key_Enter);
838 // All other platforms use F2
839 QTest::keyPress(&view, Qt::Key_F2);
846 // Check if we got an editor
848 QEXPECT_FAIL("EditKeyPressed 4", "QTBUG-23696", Continue);
850 QTRY_COMPARE(qFindChild<QLineEdit *>(&view, QString()) != 0, editorOpened);
853 void tst_QTreeView::hasAutoScroll()
856 QVERIFY(view.hasAutoScroll());
857 view.setAutoScroll(false);
858 QVERIFY(!view.hasAutoScroll());
859 view.setAutoScroll(true);
860 QVERIFY(view.hasAutoScroll());
863 void tst_QTreeView::horizontalScrollMode()
865 QStandardItemModel model;
866 for (int i = 0; i < 100; ++i) {
867 model.appendRow(QList<QStandardItem *>()
868 << new QStandardItem("An item that has very long text and should"
869 " cause the horizontal scroll bar to appear.")
870 << new QStandardItem("An item that has very long text and should"
871 " cause the horizontal scroll bar to appear."));
875 view.setModel(&model);
876 view.setFixedSize(100, 100);
877 view.header()->resizeSection(0, 200);
880 QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerPixel);
881 QCOMPARE(view.horizontalScrollBar()->minimum(), 0);
882 QVERIFY(view.horizontalScrollBar()->maximum() > 2);
884 view.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
885 QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerItem);
886 QCOMPARE(view.horizontalScrollBar()->minimum(), 0);
887 QCOMPARE(view.horizontalScrollBar()->maximum(), 1);
889 view.setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
890 QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerPixel);
891 QCOMPARE(view.horizontalScrollBar()->minimum(), 0);
892 QVERIFY(view.horizontalScrollBar()->maximum() > 2);
895 class RepaintTreeView : public QTreeView
898 RepaintTreeView() : repainted(false) { }
902 void paintEvent(QPaintEvent *event)
903 { repainted = true; QTreeView::paintEvent(event); }
906 void tst_QTreeView::iconSize()
908 RepaintTreeView view;
909 QCOMPARE(view.iconSize(), QSize());
911 QStandardItemModel treeModel;
912 initStandardTreeModel(&treeModel);
913 view.setModel(&treeModel);
914 QCOMPARE(view.iconSize(), QSize());
915 QVERIFY(!view.repainted);
919 QVERIFY(QTest::qWaitForWindowExposed(&view));
920 QTRY_VERIFY(view.repainted);
921 QCOMPARE(view.iconSize(), QSize());
923 view.repainted = false;
924 view.setIconSize(QSize());
925 QTRY_VERIFY(!view.repainted);
926 QCOMPARE(view.iconSize(), QSize());
928 view.setIconSize(QSize(10, 10));
929 QTRY_VERIFY(view.repainted);
930 QCOMPARE(view.iconSize(), QSize(10, 10));
932 view.repainted = false;
933 view.setIconSize(QSize(10000, 10000));
934 QTRY_VERIFY(view.repainted);
935 QCOMPARE(view.iconSize(), QSize(10000, 10000));
938 void tst_QTreeView::indexAt()
941 model.rows = model.cols = 5;
944 QCOMPARE(view.indexAt(QPoint()), QModelIndex());
945 view.setModel(&model);
946 QVERIFY(view.indexAt(QPoint()) != QModelIndex());
948 QSize itemSize = view.visualRect(model.index(0, 0)).size();
949 for (int i = 0; i < model.rowCount(); ++i) {
950 QPoint pos(itemSize.width() / 2, (i * itemSize.height()) + (itemSize.height() / 2));
951 QModelIndex index = view.indexAt(pos);
952 QCOMPARE(index, model.index(i, 0));
956 // ### this is wrong; the widget _will_ affect the item size
957 for (int j = 0; j < model.rowCount(); ++j)
958 view.setIndexWidget(model.index(j, 0), new QPushButton);
961 for (int k = 0; k < model.rowCount(); ++k) {
962 QPoint pos(itemSize.width() / 2, (k * itemSize.height()) + (itemSize.height() / 2));
963 QModelIndex index = view.indexAt(pos);
964 QCOMPARE(index, model.index(k, 0));
968 view.resize(600, 600);
969 view.header()->setStretchLastSection(false);
970 QCOMPARE(view.indexAt(QPoint(550, 20)), QModelIndex());
973 void tst_QTreeView::indexWidget()
976 QStandardItemModel treeModel;
977 initStandardTreeModel(&treeModel);
978 view.setModel(&treeModel);
980 QModelIndex index = view.model()->index(0, 0);
982 QVERIFY(!view.indexWidget(QModelIndex()));
983 QVERIFY(!view.indexWidget(index));
985 QString text = QLatin1String("TestLabel");
987 QWidget *label = new QLabel(text);
988 view.setIndexWidget(QModelIndex(), label);
989 QVERIFY(!view.indexWidget(QModelIndex()));
990 QVERIFY(!label->parent());
991 view.setIndexWidget(index, label);
992 QCOMPARE(view.indexWidget(index), label);
993 QCOMPARE(label->parentWidget(), view.viewport());
996 QTextEdit *widget = new QTextEdit(text);
997 widget->setFixedSize(200,100);
998 view.setIndexWidget(index, widget);
999 QCOMPARE(view.indexWidget(index), static_cast<QWidget *>(widget));
1001 QCOMPARE(widget->parentWidget(), view.viewport());
1002 QCOMPARE(widget->geometry(), view.visualRect(index).intersected(widget->geometry()));
1003 QCOMPARE(widget->toPlainText(), text);
1005 //now let's try to do that later when the widget is already shown
1007 index = view.model()->index(1, 0);
1008 QVERIFY(!view.indexWidget(index));
1010 widget = new QTextEdit(text);
1011 widget->setFixedSize(200,100);
1012 view.setIndexWidget(index, widget);
1013 QCOMPARE(view.indexWidget(index), static_cast<QWidget *>(widget));
1015 QCOMPARE(widget->parentWidget(), view.viewport());
1016 QCOMPARE(widget->geometry(), view.visualRect(index).intersect(widget->geometry()));
1017 QCOMPARE(widget->toPlainText(), text);
1020 void tst_QTreeView::itemDelegate()
1022 QPointer<QAbstractItemDelegate> oldDelegate;
1023 QPointer<QItemDelegate> otherItemDelegate;
1027 QVERIFY(qobject_cast<QStyledItemDelegate *>(view.itemDelegate()));
1028 QPointer<QAbstractItemDelegate> oldDelegate = view.itemDelegate();
1030 otherItemDelegate = new QItemDelegate;
1031 view.setItemDelegate(otherItemDelegate);
1032 QVERIFY(!otherItemDelegate->parent());
1033 QVERIFY(oldDelegate);
1035 QCOMPARE(view.itemDelegate(), (QAbstractItemDelegate *)otherItemDelegate);
1037 view.setItemDelegate(0);
1038 QVERIFY(!view.itemDelegate()); // <- view does its own drawing?
1039 QVERIFY(otherItemDelegate);
1042 // This is strange. Why doesn't setItemDelegate() reparent the delegate?
1043 QVERIFY(!oldDelegate);
1044 QVERIFY(otherItemDelegate);
1046 delete otherItemDelegate;
1049 void tst_QTreeView::itemDelegateForColumnOrRow()
1052 QAbstractItemDelegate *defaultDelegate = view.itemDelegate();
1053 QVERIFY(defaultDelegate);
1055 QVERIFY(!view.itemDelegateForRow(0));
1056 QVERIFY(!view.itemDelegateForColumn(0));
1057 QCOMPARE(view.itemDelegate(QModelIndex()), defaultDelegate);
1059 QStandardItemModel model;
1060 for (int i = 0; i < 100; ++i) {
1061 model.appendRow(QList<QStandardItem *>()
1062 << new QStandardItem("An item that has very long text and should"
1063 " cause the horizontal scroll bar to appear.")
1064 << new QStandardItem("An item that has very long text and should"
1065 " cause the horizontal scroll bar to appear.")
1066 << new QStandardItem("An item that has very long text and should"
1067 " cause the horizontal scroll bar to appear."));
1069 view.setModel(&model);
1071 QVERIFY(!view.itemDelegateForRow(0));
1072 QVERIFY(!view.itemDelegateForColumn(0));
1073 QCOMPARE(view.itemDelegate(QModelIndex()), defaultDelegate);
1074 QCOMPARE(view.itemDelegate(view.model()->index(0, 0)), defaultDelegate);
1076 QPointer<QAbstractItemDelegate> rowDelegate = new QItemDelegate;
1077 view.setItemDelegateForRow(0, rowDelegate);
1078 QVERIFY(!rowDelegate->parent());
1079 QCOMPARE(view.itemDelegateForRow(0), (QAbstractItemDelegate *)rowDelegate);
1080 QCOMPARE(view.itemDelegate(view.model()->index(0, 0)), (QAbstractItemDelegate *)rowDelegate);
1081 QCOMPARE(view.itemDelegate(view.model()->index(0, 1)), (QAbstractItemDelegate *)rowDelegate);
1082 QCOMPARE(view.itemDelegate(view.model()->index(1, 0)), defaultDelegate);
1083 QCOMPARE(view.itemDelegate(view.model()->index(1, 1)), defaultDelegate);
1085 QPointer<QAbstractItemDelegate> columnDelegate = new QItemDelegate;
1086 view.setItemDelegateForColumn(1, columnDelegate);
1087 QVERIFY(!columnDelegate->parent());
1088 QCOMPARE(view.itemDelegateForColumn(1), (QAbstractItemDelegate *)columnDelegate);
1089 QCOMPARE(view.itemDelegate(view.model()->index(0, 0)), (QAbstractItemDelegate *)rowDelegate);
1090 QCOMPARE(view.itemDelegate(view.model()->index(0, 1)), (QAbstractItemDelegate *)rowDelegate); // row wins
1091 QCOMPARE(view.itemDelegate(view.model()->index(1, 0)), defaultDelegate);
1092 QCOMPARE(view.itemDelegate(view.model()->index(1, 1)), (QAbstractItemDelegate *)columnDelegate);
1094 view.setItemDelegateForRow(0, 0);
1095 QVERIFY(!view.itemDelegateForRow(0));
1096 QVERIFY(rowDelegate); // <- wasn't deleted
1098 view.setItemDelegateForColumn(1, 0);
1099 QVERIFY(!view.itemDelegateForColumn(1));
1100 QVERIFY(columnDelegate); // <- wasn't deleted
1103 delete columnDelegate;
1106 void tst_QTreeView::keyboardSearch()
1109 QStandardItemModel model;
1110 model.appendRow(new QStandardItem("Andreas"));
1111 model.appendRow(new QStandardItem("Baldrian"));
1112 model.appendRow(new QStandardItem("Cecilie"));
1113 view.setModel(&model);
1116 // Nothing is selected
1117 QVERIFY(!view.selectionModel()->hasSelection());
1118 QVERIFY(!view.selectionModel()->isSelected(model.index(0, 0)));
1120 // First item is selected
1121 view.keyboardSearch(QLatin1String("A"));
1122 QTRY_VERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
1124 // First item is still selected
1125 view.keyboardSearch(QLatin1String("n"));
1126 QVERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
1128 // No "AnB" item - keep the same selection.
1129 view.keyboardSearch(QLatin1String("B"));
1130 QVERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
1133 QTest::qWait(QApplication::keyboardInputInterval() * 2);
1135 // The item that starts with B is selected.
1136 view.keyboardSearch(QLatin1String("B"));
1137 QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
1140 void tst_QTreeView::setModel()
1144 QCOMPARE(view.model(), (QAbstractItemModel*)0);
1145 QCOMPARE(view.selectionModel(), (QItemSelectionModel*)0);
1146 QCOMPARE(view.header()->model(), (QAbstractItemModel*)0);
1147 QCOMPARE(view.header()->selectionModel(), (QItemSelectionModel*)0);
1149 for (int x = 0; x < 2; ++x) {
1150 QtTestModel *model = new QtTestModel(10, 8);
1151 QAbstractItemModel *oldModel = view.model();
1152 QSignalSpy modelDestroyedSpy(oldModel ? oldModel : model, SIGNAL(destroyed()));
1153 // set the same model twice
1154 for (int i = 0; i < 2; ++i) {
1155 QItemSelectionModel *oldSelectionModel = view.selectionModel();
1156 QItemSelectionModel *dummy = new QItemSelectionModel(model);
1157 QSignalSpy selectionModelDestroyedSpy(
1158 oldSelectionModel ? oldSelectionModel : dummy, SIGNAL(destroyed()));
1159 view.setModel(model);
1160 // QCOMPARE(selectionModelDestroyedSpy.count(), (x == 0 || i == 1) ? 0 : 1);
1161 QCOMPARE(view.model(), (QAbstractItemModel *)model);
1162 QCOMPARE(view.header()->model(), (QAbstractItemModel *)model);
1163 QCOMPARE(view.selectionModel() != oldSelectionModel, (i == 0));
1165 QTRY_COMPARE(modelDestroyedSpy.count(), 0);
1168 QCOMPARE(view.model(), (QAbstractItemModel*)0);
1169 // ### shouldn't selectionModel also be 0 now?
1170 // QCOMPARE(view.selectionModel(), (QItemSelectionModel*)0);
1175 void tst_QTreeView::openPersistentEditor()
1178 QStandardItemModel treeModel;
1179 initStandardTreeModel(&treeModel);
1180 view.setModel(&treeModel);
1183 QVERIFY(!qFindChild<QLineEdit *>(view.viewport()));
1184 view.openPersistentEditor(view.model()->index(0, 0));
1185 QVERIFY(qFindChild<QLineEdit *>(view.viewport()));
1187 view.closePersistentEditor(view.model()->index(0, 0));
1188 QVERIFY(!qFindChild<QLineEdit *>(view.viewport())->isVisible());
1190 qApp->sendPostedEvents(0, QEvent::DeferredDelete);
1191 QVERIFY(!qFindChild<QLineEdit *>(view.viewport()));
1194 void tst_QTreeView::rootIndex()
1197 QCOMPARE(view.rootIndex(), QModelIndex());
1198 QStandardItemModel treeModel;
1199 initStandardTreeModel(&treeModel);
1200 view.setModel(&treeModel);
1201 QCOMPARE(view.rootIndex(), QModelIndex());
1203 view.setRootIndex(view.model()->index(1, 0));
1205 QCOMPARE(view.model()->data(view.model()->index(0, view.header()->visualIndex(0), view.rootIndex()), Qt::DisplayRole)
1206 .toString(), QString("Row 2 Child Item"));
1209 void tst_QTreeView::setHeader()
1212 QVERIFY(view.header() != 0);
1213 QCOMPARE(view.header()->orientation(), Qt::Horizontal);
1214 QCOMPARE(view.header()->parent(), (QObject *)&view);
1215 for (int x = 0; x < 2; ++x) {
1216 QSignalSpy destroyedSpy(view.header(), SIGNAL(destroyed()));
1217 Qt::Orientation orient = x ? Qt::Vertical : Qt::Horizontal;
1218 QHeaderView *head = new QHeaderView(orient);
1219 view.setHeader(head);
1220 QCOMPARE(destroyedSpy.count(), 1);
1221 QCOMPARE(head->parent(), (QObject *)&view);
1222 QCOMPARE(view.header(), head);
1223 view.setHeader(head);
1224 QCOMPARE(view.header(), head);
1225 // Itemviews in Qt < 4.2 have asserts for this. Qt >= 4.2 should handle this gracefully
1226 view.setHeader((QHeaderView *)0);
1227 QCOMPARE(view.header(), head);
1231 void tst_QTreeView::columnHidden()
1234 QtTestModel model(10, 8);
1235 view.setModel(&model);
1237 for (int c = 0; c < model.columnCount(); ++c)
1238 QCOMPARE(view.isColumnHidden(c), false);
1239 // hide even columns
1240 for (int c = 0; c < model.columnCount(); c+=2)
1241 view.setColumnHidden(c, true);
1242 for (int c = 0; c < model.columnCount(); ++c)
1243 QCOMPARE(view.isColumnHidden(c), (c & 1) == 0);
1245 // hide odd columns too
1246 for (int c = 1; c < model.columnCount(); c+=2)
1247 view.setColumnHidden(c, true);
1248 for (int c = 0; c < model.columnCount(); ++c)
1249 QCOMPARE(view.isColumnHidden(c), true);
1253 void tst_QTreeView::rowHidden()
1255 QtTestModel model(4, 6);
1258 view.resize(500,500);
1259 view.setModel(&model);
1262 QCOMPARE(view.isRowHidden(-1, QModelIndex()), false);
1263 QCOMPARE(view.isRowHidden(999999, QModelIndex()), false);
1264 view.setRowHidden(-1, QModelIndex(), true);
1265 view.setRowHidden(999999, QModelIndex(), true);
1266 QCOMPARE(view.isRowHidden(-1, QModelIndex()), false);
1267 QCOMPARE(view.isRowHidden(999999, QModelIndex()), false);
1269 view.setRowHidden(0, QModelIndex(), true);
1270 QCOMPARE(view.isRowHidden(0, QModelIndex()), true);
1271 view.setRowHidden(0, QModelIndex(), false);
1272 QCOMPARE(view.isRowHidden(0, QModelIndex()), false);
1274 QStack<QModelIndex> parents;
1275 parents.push(QModelIndex());
1276 while (!parents.isEmpty()) {
1277 QModelIndex p = parents.pop();
1278 if (model.canFetchMore(p))
1280 int rows = model.rowCount(p);
1282 for (int r = 0; r < rows; ++r) {
1283 view.setRowHidden(r, p, true);
1284 QCOMPARE(view.isRowHidden(r, p), true);
1287 for (int r = 0; r < rows; ++r) {
1288 view.setRowHidden(r, p, false);
1289 QCOMPARE(view.isRowHidden(r, p), false);
1291 // hide only even rows
1292 for (int r = 0; r < rows; ++r) {
1293 bool hide = (r & 1) == 0;
1294 view.setRowHidden(r, p, hide);
1295 QCOMPARE(view.isRowHidden(r, p), hide);
1297 for (int r = 0; r < rows; ++r)
1298 parents.push(model.index(r, 0, p));
1301 parents.push(QModelIndex());
1302 while (!parents.isEmpty()) {
1303 QModelIndex p = parents.pop();
1304 // all even rows should still be hidden
1305 for (int r = 0; r < model.rowCount(p); ++r)
1306 QCOMPARE(view.isRowHidden(r, p), (r & 1) == 0);
1307 if (model.rowCount(p) > 0) {
1308 for (int r = 0; r < model.rowCount(p); ++r)
1309 parents.push(model.index(r, 0, p));
1314 void tst_QTreeView::noDelegate()
1316 QtTestModel model(10, 7);
1318 view.setModel(&model);
1319 view.setItemDelegate(0);
1320 QCOMPARE(view.itemDelegate(), (QAbstractItemDelegate *)0);
1323 void tst_QTreeView::noModel()
1327 view.setRowHidden(0, QModelIndex(), true);
1330 void tst_QTreeView::emptyModel()
1334 view.setModel(&model);
1336 QVERIFY(!model.wrongIndex);
1339 void tst_QTreeView::removeRows()
1341 QtTestModel model(7, 10);
1345 view.setModel(&model);
1348 model.removeLastRow();
1349 QVERIFY(!model.wrongIndex);
1351 model.removeAllRows();
1352 QVERIFY(!model.wrongIndex);
1355 void tst_QTreeView::removeCols()
1357 QtTestModel model(5, 8);
1360 view.setModel(&model);
1362 model.fetched = true;
1363 model.removeLastColumn();
1364 QVERIFY(!model.wrongIndex);
1365 QCOMPARE(view.header()->count(), model.cols);
1367 model.removeAllColumns();
1368 QVERIFY(!model.wrongIndex);
1369 QCOMPARE(view.header()->count(), model.cols);
1372 void tst_QTreeView::expandAndCollapse_data()
1374 QTest::addColumn<bool>("animationEnabled");
1375 QTest::newRow("normal") << false;
1376 QTest::newRow("animated") << true;
1380 void tst_QTreeView::expandAndCollapse()
1382 QFETCH(bool, animationEnabled);
1384 QtTestModel model(10, 9);
1387 view.setUniformRowHeights(true);
1388 view.setModel(&model);
1389 view.setAnimated(animationEnabled);
1392 QModelIndex a = model.index(0, 0, QModelIndex());
1393 QModelIndex b = model.index(0, 0, a);
1395 QSignalSpy expandedSpy(&view, SIGNAL(expanded(const QModelIndex&)));
1396 QSignalSpy collapsedSpy(&view, SIGNAL(collapsed(const QModelIndex&)));
1399 for (int y = 0; y < 2; ++y) {
1400 view.setVisible(y == 0);
1401 for (int x = 0; x < 2; ++x) {
1402 view.setItemsExpandable(x == 0);
1405 view.expand(QModelIndex());
1406 QCOMPARE(view.isExpanded(QModelIndex()), false);
1407 view.collapse(QModelIndex());
1408 QCOMPARE(expandedSpy.count(), 0);
1409 QCOMPARE(collapsedSpy.count(), 0);
1411 // expand a first level item
1412 QVERIFY(!view.isExpanded(a));
1414 QVERIFY(view.isExpanded(a));
1415 QCOMPARE(expandedSpy.count(), 1);
1416 QCOMPARE(collapsedSpy.count(), 0);
1417 args = expandedSpy.takeFirst();
1418 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
1421 QVERIFY(view.isExpanded(a));
1422 QCOMPARE(expandedSpy.count(), 0);
1423 QCOMPARE(collapsedSpy.count(), 0);
1425 // expand a second level item
1426 QVERIFY(!view.isExpanded(b));
1428 QVERIFY(view.isExpanded(a));
1429 QVERIFY(view.isExpanded(b));
1430 QCOMPARE(expandedSpy.count(), 1);
1431 QCOMPARE(collapsedSpy.count(), 0);
1432 args = expandedSpy.takeFirst();
1433 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
1436 QVERIFY(view.isExpanded(b));
1437 QCOMPARE(expandedSpy.count(), 0);
1438 QCOMPARE(collapsedSpy.count(), 0);
1440 // collapse the first level item
1442 QVERIFY(!view.isExpanded(a));
1443 QVERIFY(view.isExpanded(b));
1444 QCOMPARE(expandedSpy.count(), 0);
1445 QCOMPARE(collapsedSpy.count(), 1);
1446 args = collapsedSpy.takeFirst();
1447 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
1450 QVERIFY(!view.isExpanded(a));
1451 QCOMPARE(expandedSpy.count(), 0);
1452 QCOMPARE(collapsedSpy.count(), 0);
1454 // expand the first level item again
1456 QVERIFY(view.isExpanded(a));
1457 QVERIFY(view.isExpanded(b));
1458 QCOMPARE(expandedSpy.count(), 1);
1459 QCOMPARE(collapsedSpy.count(), 0);
1460 args = expandedSpy.takeFirst();
1461 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
1463 // collapse the second level item
1465 QVERIFY(view.isExpanded(a));
1466 QVERIFY(!view.isExpanded(b));
1467 QCOMPARE(expandedSpy.count(), 0);
1468 QCOMPARE(collapsedSpy.count(), 1);
1469 args = collapsedSpy.takeFirst();
1470 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
1472 // collapse the first level item
1474 QVERIFY(!view.isExpanded(a));
1475 QVERIFY(!view.isExpanded(b));
1476 QCOMPARE(expandedSpy.count(), 0);
1477 QCOMPARE(collapsedSpy.count(), 1);
1478 args = collapsedSpy.takeFirst();
1479 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
1481 // expand and remove row
1482 QPersistentModelIndex c = model.index(9, 0, b);
1485 model.removeLastRow(); // remove c
1486 QVERIFY(view.isExpanded(a));
1487 QVERIFY(view.isExpanded(b));
1488 QVERIFY(!view.isExpanded(c));
1489 QCOMPARE(expandedSpy.count(), 2);
1490 QCOMPARE(collapsedSpy.count(), 0);
1491 args = expandedSpy.takeFirst();
1492 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
1493 args = expandedSpy.takeFirst();
1494 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
1498 QVERIFY(!view.isExpanded(a));
1499 QVERIFY(!view.isExpanded(b));
1500 QVERIFY(!view.isExpanded(c));
1501 QCOMPARE(expandedSpy.count(), 0);
1502 QCOMPARE(collapsedSpy.count(), 2);
1503 args = collapsedSpy.takeFirst();
1504 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a);
1505 args = collapsedSpy.takeFirst();
1506 QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b);
1511 void tst_QTreeView::expandAndCollapseAll()
1513 QtTestModel model(3, 2);
1516 view.setUniformRowHeights(true);
1517 view.setModel(&model);
1519 QSignalSpy expandedSpy(&view, SIGNAL(expanded(const QModelIndex&)));
1520 QSignalSpy collapsedSpy(&view, SIGNAL(collapsed(const QModelIndex&)));
1525 QCOMPARE(collapsedSpy.count(), 0);
1527 QStack<QModelIndex> parents;
1528 parents.push(QModelIndex());
1530 while (!parents.isEmpty()) {
1531 QModelIndex p = parents.pop();
1532 int rows = model.rowCount(p);
1533 for (int r = 0; r < rows; ++r)
1534 QVERIFY(view.isExpanded(model.index(r, 0, p)));
1536 for (int r = 0; r < rows; ++r)
1537 parents.push(model.index(r, 0, p));
1539 // ### why is expanded() signal not emitted?
1540 // QCOMPARE(expandedSpy.count(), count);
1544 QCOMPARE(expandedSpy.count(), 0);
1546 parents.push(QModelIndex());
1548 while (!parents.isEmpty()) {
1549 QModelIndex p = parents.pop();
1550 int rows = model.rowCount(p);
1551 for (int r = 0; r < rows; ++r)
1552 QVERIFY(!view.isExpanded(model.index(r, 0, p)));
1554 for (int r = 0; r < rows; ++r)
1555 parents.push(model.index(r, 0, p));
1557 // ### why is collapsed() signal not emitted?
1558 // QCOMPARE(collapsedSpy.count(), count);
1561 void tst_QTreeView::expandWithNoChildren()
1564 QStandardItemModel model(1,1);
1565 tree.setModel(&model);
1566 tree.setAnimated(true);
1567 tree.doItemsLayout();
1568 //this test should not output warnings
1569 tree.expand(model.index(0,0));
1574 void tst_QTreeView::keyboardNavigation()
1576 const int rows = 10;
1577 const int columns = 7;
1579 QtTestModel model(rows, columns);
1582 view.setModel(&model);
1585 QVector<Qt::Key> keymoves;
1586 keymoves << Qt::Key_Down << Qt::Key_Right << Qt::Key_Right << Qt::Key_Right
1587 << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down
1588 << Qt::Key_Right << Qt::Key_Right << Qt::Key_Right
1589 << Qt::Key_Left << Qt::Key_Up << Qt::Key_Left << Qt::Key_Left
1590 << Qt::Key_Up << Qt::Key_Down << Qt::Key_Up << Qt::Key_Up
1591 << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up
1592 << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down;
1596 QModelIndex index = model.index(row, column, QModelIndex());
1597 view.setCurrentIndex(index);
1598 QCOMPARE(view.currentIndex(), index);
1600 for (int i = 0; i < keymoves.size(); ++i) {
1601 Qt::Key key = keymoves.at(i);
1602 QTest::keyClick(&view, key);
1607 index = index.sibling(row - 1, column);
1609 } else if (index.parent() != QModelIndex()) {
1610 index = index.parent();
1615 if (view.isExpanded(index)) {
1617 index = index.child(row, column);
1619 row = qMin(rows - 1, row + 1);
1620 index = index.sibling(row, column);
1623 case Qt::Key_Left: {
1624 QScrollBar *b = view.horizontalScrollBar();
1625 if (b->value() == b->minimum())
1626 QVERIFY(!view.isExpanded(index));
1627 // windows style right will walk to the parent
1628 if (view.currentIndex() != index) {
1629 QCOMPARE(view.currentIndex(), index.parent());
1630 index = view.currentIndex();
1632 column = index.column();
1637 QVERIFY(view.isExpanded(index));
1638 // windows style right will walk to the first child
1639 if (view.currentIndex() != index) {
1640 QCOMPARE(view.currentIndex().parent(), index);
1641 row = view.currentIndex().row();
1642 column = view.currentIndex().column();
1643 index = view.currentIndex();
1650 QCOMPARE(view.currentIndex().row(), row);
1651 QCOMPARE(view.currentIndex().column(), column);
1652 QCOMPARE(view.currentIndex(), index);
1656 class Dmodel : public QtTestModel
1659 Dmodel() : QtTestModel(10, 10){}
1661 int columnCount(const QModelIndex &parent) const
1663 if (parent.row() == 5)
1665 return QtTestModel::columnCount(parent);
1669 void tst_QTreeView::headerSections()
1674 QHeaderView *header = view.header();
1676 view.setModel(&model);
1677 QModelIndex index = model.index(5, 0);
1678 view.setRootIndex(index);
1679 QCOMPARE(model.columnCount(QModelIndex()), 10);
1680 QCOMPARE(model.columnCount(index), 1);
1681 QCOMPARE(header->count(), model.columnCount(index));
1684 void tst_QTreeView::moveCursor_data()
1686 QTest::addColumn<bool>("uniformRowHeights");
1687 QTest::addColumn<bool>("scrollPerPixel");
1688 QTest::newRow("uniformRowHeights = false, scrollPerPixel = false")
1690 QTest::newRow("uniformRowHeights = true, scrollPerPixel = false")
1692 QTest::newRow("uniformRowHeights = false, scrollPerPixel = true")
1694 QTest::newRow("uniformRowHeights = true, scrollPerPixel = true")
1698 void tst_QTreeView::moveCursor()
1700 QFETCH(bool, uniformRowHeights);
1701 QFETCH(bool, scrollPerPixel);
1702 QtTestModel model(8, 6);
1705 view.setUniformRowHeights(uniformRowHeights);
1706 view.setModel(&model);
1707 view.setRowHidden(0, QModelIndex(), true);
1708 view.setVerticalScrollMode(scrollPerPixel ?
1709 QAbstractItemView::ScrollPerPixel :
1710 QAbstractItemView::ScrollPerItem);
1711 QVERIFY(view.isRowHidden(0, QModelIndex()));
1712 view.setColumnHidden(0, true);
1713 QVERIFY(view.isColumnHidden(0));
1715 qApp->setActiveWindow(&view);
1717 //here the first visible index should be selected
1718 //because the view got the focus
1719 QModelIndex expected = model.index(1, 1, QModelIndex());
1720 QCOMPARE(view.currentIndex(), expected);
1722 //then pressing down should go to the next line
1723 QModelIndex actual = view.moveCursor(PublicView::MoveDown, Qt::NoModifier);
1724 expected = model.index(2, 1, QModelIndex());
1725 QCOMPARE(actual, expected);
1727 view.setRowHidden(0, QModelIndex(), false);
1728 view.setColumnHidden(0, false);
1730 // PageUp was broken with uniform row heights turned on
1731 view.setCurrentIndex(model.index(1, 0));
1732 actual = view.moveCursor(PublicView::MovePageUp, Qt::NoModifier);
1733 expected = model.index(0, 0, QModelIndex());
1734 QCOMPARE(actual, expected);
1736 //let's try another column
1737 view.setCurrentIndex(model.index(1, 1));
1738 view.setSelectionBehavior(QAbstractItemView::SelectItems);
1739 QTest::keyClick(view.viewport(), Qt::Key_Up);
1740 expected = model.index(0, 1, QModelIndex());
1741 QCOMPARE(view.currentIndex(), expected);
1742 QTest::keyClick(view.viewport(), Qt::Key_Down);
1743 expected = model.index(1, 1, QModelIndex());
1744 QCOMPARE(view.currentIndex(), expected);
1745 QTest::keyClick(view.viewport(), Qt::Key_Up);
1746 expected = model.index(0, 1, QModelIndex());
1747 QCOMPARE(view.currentIndex(), expected);
1748 view.setColumnHidden(0, true);
1749 QTest::keyClick(view.viewport(), Qt::Key_Left);
1750 expected = model.index(0, 1, QModelIndex()); //it shouldn't have changed
1751 QCOMPARE(view.currentIndex(), expected);
1752 view.setColumnHidden(0, false);
1753 QTest::keyClick(view.viewport(), Qt::Key_Left);
1754 expected = model.index(0, 0, QModelIndex());
1755 QCOMPARE(view.currentIndex(), expected);
1758 class TestDelegate : public QItemDelegate
1761 TestDelegate(QObject *parent) : QItemDelegate(parent) {}
1762 QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(200, 50); }
1765 typedef QList<QPoint> PointList;
1766 Q_DECLARE_METATYPE(PointList)
1768 void tst_QTreeView::setSelection_data()
1770 QTest::addColumn<QRect>("selectionRect");
1771 QTest::addColumn<int>("selectionMode");
1772 QTest::addColumn<int>("selectionCommand");
1773 QTest::addColumn<PointList>("expectedItems");
1774 QTest::addColumn<int>("verticalOffset");
1776 QTest::newRow("(0,0,50,20),rows") << QRect(0,0,50,20)
1777 << int(QAbstractItemView::SingleSelection)
1778 << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
1780 << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
1784 QTest::newRow("(0,0,50,90),rows") << QRect(0,0,50,90)
1785 << int(QAbstractItemView::ExtendedSelection)
1786 << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
1788 << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
1789 << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
1793 QTest::newRow("(50,0,0,90),rows,invalid rect") << QRect(QPoint(50, 0), QPoint(0, 90))
1794 << int(QAbstractItemView::ExtendedSelection)
1795 << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
1797 << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
1798 << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
1802 QTest::newRow("(0,-20,20,50),rows") << QRect(0,-20,20,50)
1803 << int(QAbstractItemView::ExtendedSelection)
1804 << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
1806 << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
1807 << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
1810 QTest::newRow("(0,-50,20,90),rows") << QRect(0,-50,20,90)
1811 << int(QAbstractItemView::ExtendedSelection)
1812 << int(QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows)
1814 << QPoint(0,0) << QPoint(1,0) << QPoint(2,0) << QPoint(3,0) << QPoint(4,0)
1815 << QPoint(0,1) << QPoint(1,1) << QPoint(2,1) << QPoint(3,1) << QPoint(4,1)
1821 void tst_QTreeView::setSelection()
1823 QFETCH(QRect, selectionRect);
1824 QFETCH(int, selectionMode);
1825 QFETCH(int, selectionCommand);
1826 QFETCH(PointList, expectedItems);
1827 QFETCH(int, verticalOffset);
1829 QtTestModel model(10, 5);
1831 model.setDecorationsEnabled(true);
1833 view.resize(400, 300);
1835 view.setRootIsDecorated(false);
1836 view.setItemDelegate(new TestDelegate(&view));
1837 view.setSelectionMode(QAbstractItemView::SelectionMode(selectionMode));
1838 view.setModel(&model);
1839 view.setUniformRowHeights(true);
1840 view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
1841 view.scrollTo(model.index(verticalOffset, 0), QAbstractItemView::PositionAtTop);
1842 view.setSelection(selectionRect, QItemSelectionModel::SelectionFlags(selectionCommand));
1843 QItemSelectionModel *selectionModel = view.selectionModel();
1844 QVERIFY(selectionModel);
1846 QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
1847 QCOMPARE(selectedIndexes.count(), expectedItems.count());
1848 for (int i = 0; i < selectedIndexes.count(); ++i) {
1849 QModelIndex idx = selectedIndexes.at(i);
1850 QVERIFY(expectedItems.contains(QPoint(idx.column(), idx.row())));
1854 void tst_QTreeView::indexAbove()
1856 QtTestModel model(6, 7);
1860 QCOMPARE(view.indexAbove(QModelIndex()), QModelIndex());
1861 view.setModel(&model);
1862 QCOMPARE(view.indexAbove(QModelIndex()), QModelIndex());
1864 QStack<QModelIndex> parents;
1865 parents.push(QModelIndex());
1866 while (!parents.isEmpty()) {
1867 QModelIndex p = parents.pop();
1868 if (model.canFetchMore(p))
1870 int rows = model.rowCount(p);
1871 for (int r = rows - 1; r > 0; --r) {
1872 QModelIndex idx = model.index(r, 0, p);
1873 QModelIndex expected = model.index(r - 1, 0, p);
1874 QCOMPARE(view.indexAbove(idx), expected);
1877 for (int r = 0; r < rows; r+=2)
1878 view.setRowHidden(r, p, true);
1879 for (int r = rows - 1; r > 0; r-=2) {
1880 QModelIndex idx = model.index(r, 0, p);
1881 QModelIndex expected = model.index(r - 2, 0, p);
1882 QCOMPARE(view.indexAbove(idx), expected);
1884 // for (int r = 0; r < rows; ++r)
1885 // parents.push(model.index(r, 0, p));
1889 void tst_QTreeView::indexBelow()
1891 QtTestModel model(2, 1);
1894 view.setModel(&model);
1897 QModelIndex i = model.index(0, 0, view.rootIndex());
1898 QVERIFY(i.isValid());
1899 QCOMPARE(i.row(), 0);
1901 i = view.indexBelow(i);
1902 QVERIFY(i.isValid());
1903 QCOMPARE(i.row(), 1);
1904 i = view.indexBelow(i);
1905 QVERIFY(!i.isValid());
1908 void tst_QTreeView::clicked()
1910 QtTestModel model(10, 2);
1913 view.setModel(&model);
1916 QModelIndex firstIndex = model.index(0, 0, QModelIndex());
1917 QVERIFY(firstIndex.isValid());
1918 int itemHeight = view.visualRect(firstIndex).height();
1919 int itemOffset = view.visualRect(firstIndex).width() / 2;
1920 view.resize(200, itemHeight * (model.rows + 2));
1922 for (int i = 0; i < model.rowCount(); ++i) {
1923 QPoint p(itemOffset, 1 + itemHeight * i);
1924 QModelIndex index = view.indexAt(p);
1925 if (!index.isValid())
1927 QSignalSpy spy(&view, SIGNAL(clicked(const QModelIndex&)));
1928 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
1929 QTRY_COMPARE(spy.count(), 1);
1933 void tst_QTreeView::mouseDoubleClick()
1935 // Test double clicks outside the viewport.
1936 // (Should be a no-op and should not expand any item.)
1938 QStandardItemModel model(20, 2);
1939 for (int i = 0; i < model.rowCount(); i++) {
1940 QModelIndex index = model.index(i, 0, QModelIndex());
1941 model.insertRows(0, 20, index);
1942 model.insertColumns(0,2,index);
1943 for (int i1 = 0; i1 < model.rowCount(index); i1++) {
1944 QModelIndex index2 = model.index(i1, 0, index);
1949 view.setModel(&model);
1951 // make sure the viewport height is smaller than the contents height.
1952 view.resize(200,200);
1955 QModelIndex index = model.index(0, 0, QModelIndex());
1956 view.setCurrentIndex(index);
1958 view.setExpanded(model.index(0,0, QModelIndex()), true);
1959 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
1960 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
1962 // Make sure all items are collapsed
1963 for (int i = 0; i < model.rowCount(QModelIndex()); i++) {
1964 view.setExpanded(model.index(i,0, QModelIndex()), false);
1967 int maximum = view.verticalScrollBar()->maximum();
1969 // Doubleclick in the bottom right corner, in the unused area between the vertical and horizontal scrollbar.
1970 int vsw = view.verticalScrollBar()->width();
1971 int hsh = view.horizontalScrollBar()->height();
1972 QTest::mouseDClick(&view, Qt::LeftButton, Qt::NoModifier, QPoint(view.width() - vsw + 1, view.height() - hsh + 1));
1973 // Should not have expanded, thus maximum() should have the same value.
1974 QCOMPARE(maximum, view.verticalScrollBar()->maximum());
1976 view.setExpandsOnDoubleClick(false);
1977 QTest::mouseDClick(&view, Qt::LeftButton, Qt::NoModifier, view.visualRect(index).center());
1978 QVERIFY(!view.isExpanded(index));
1981 void tst_QTreeView::rowsAboutToBeRemoved()
1983 QStandardItemModel model(3, 1);
1984 for (int i = 0; i < model.rowCount(); i++) {
1985 QModelIndex index = model.index(i, 0, QModelIndex());
1986 model.setData(index, QString("%1").arg(i));
1987 model.insertRows(0, 4, index);
1988 model.insertColumns(0,1,index);
1989 for (int i1 = 0; i1 < model.rowCount(index); i1++) {
1990 QModelIndex index2 = model.index(i1, 0, index);
1991 model.setData(index2, QString("%1%2").arg(i).arg(i1));
1996 view.setModel(&model);
1998 QModelIndex index = model.index(0,0, QModelIndex());
1999 view.setCurrentIndex(index);
2000 view.setExpanded(model.index(0,0, QModelIndex()), true);
2002 for (int i = 0; i < model.rowCount(QModelIndex()); i++) {
2003 view.setExpanded(model.index(i,0, QModelIndex()), true);
2006 QSignalSpy spy1(&model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
2008 model.removeRows(1,1);
2009 QCOMPARE(view.state(), 0);
2010 // Should not be 5 (or any other number for that sake :)
2011 QCOMPARE(spy1.count(), 1);
2015 void tst_QTreeView::headerSections_unhideSection()
2017 QtTestModel model(10, 7);
2021 view.setModel(&model);
2023 int size = view.header()->sectionSize(0);
2024 view.setColumnHidden(0, true);
2026 // should go back to old size
2027 view.setColumnHidden(0, false);
2028 QCOMPARE(size, view.header()->sectionSize(0));
2031 void tst_QTreeView::columnAt()
2034 model.rows = model.cols = 10;
2036 view.resize(500,500);
2037 view.setModel(&model);
2039 QCOMPARE(view.columnAt(0), 0);
2040 // really this is testing the header... so not much more should be needed if the header is working...
2043 void tst_QTreeView::scrollTo()
2045 #define CHECK_VISIBLE(ROW,COL) QVERIFY(QRect(QPoint(),view.viewport()->size()).contains(\
2046 view.visualRect(model.index((ROW),(COL),QModelIndex()))))
2049 model.rows = model.cols = 100;
2051 view.setUniformRowHeights(true);
2052 view.scrollTo(QModelIndex(), QTreeView::PositionAtTop);
2053 view.setModel(&model);
2055 // ### check the scrollbar values an make sure it actually scrolls to the item
2056 // ### check for bot item based and pixel based scrolling
2057 // ### create a data function for this test
2059 view.scrollTo(QModelIndex());
2060 view.scrollTo(model.index(0,0,QModelIndex()));
2061 view.scrollTo(model.index(0,0,QModelIndex()), QTreeView::PositionAtTop);
2062 view.scrollTo(model.index(0,0,QModelIndex()), QTreeView::PositionAtBottom);
2067 view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem); //some styles change that in Polish
2069 view.resize(300, 200);
2070 //view.verticalScrollBar()->setValue(0);
2072 view.scrollTo(model.index(0,0,QModelIndex()));
2074 QCOMPARE(view.verticalScrollBar()->value(), 0);
2076 view.header()->resizeSection(0, 5); // now we only see the branches
2077 view.scrollTo(model.index(5, 0, QModelIndex()), QTreeView::PositionAtTop);
2078 QCOMPARE(view.verticalScrollBar()->value(), 5);
2080 view.scrollTo(model.index(60, 60, QModelIndex()));
2082 CHECK_VISIBLE(60,60);
2083 view.scrollTo(model.index(60, 30, QModelIndex()));
2084 CHECK_VISIBLE(60,30);
2085 view.scrollTo(model.index(30, 30, QModelIndex()));
2086 CHECK_VISIBLE(30,30);
2088 // TODO force it to move to the left and then the right
2091 void tst_QTreeView::rowsAboutToBeRemoved_move()
2093 QStandardItemModel model(3,1);
2095 view.setModel(&model);
2096 QModelIndex indexThatWantsToLiveButWillDieDieITellYou;
2097 QModelIndex parent = model.index(2, 0 );
2098 view.expand(parent);
2099 for (int i = 0; i < 6; ++i) {
2100 model.insertRows(0, 1, parent);
2101 model.insertColumns(0, 1, parent);
2102 QModelIndex index = model.index(0, 0, parent);
2105 indexThatWantsToLiveButWillDieDieITellYou = index;
2106 model.setData(index, i);
2109 view.resize(600,800);
2111 view.doItemsLayout();
2112 static_cast<PublicView *>(&view)->executeDelayedItemsLayout();
2113 parent = indexThatWantsToLiveButWillDieDieITellYou.parent();
2114 QCOMPARE(view.isExpanded(indexThatWantsToLiveButWillDieDieITellYou), true);
2115 QCOMPARE(parent.isValid(), true);
2116 QCOMPARE(parent.parent().isValid(), true);
2117 view.expand(parent);
2118 QCOMPARE(view.isExpanded(parent), true);
2119 QCOMPARE(view.isExpanded(indexThatWantsToLiveButWillDieDieITellYou), true);
2120 model.removeRow(0, indexThatWantsToLiveButWillDieDieITellYou);
2121 QCOMPARE(view.isExpanded(parent), true);
2122 QCOMPARE(view.isExpanded(indexThatWantsToLiveButWillDieDieITellYou), true);
2125 void tst_QTreeView::resizeColumnToContents()
2127 QStandardItemModel model(50,2);
2128 for (int r = 0; r < model.rowCount(); ++r) {
2129 for (int c = 0; c < model.columnCount(); ++c) {
2130 QModelIndex idx = model.index(r, c);
2131 model.setData(idx, QString::fromLatin1("%1,%2").arg(r).arg(c) );
2132 model.insertColumns(0, 2, idx);
2133 model.insertRows(0, 6, idx);
2134 for (int i = 0; i < 6; ++i) {
2135 for (int j = 0; j < 2 ; ++j) {
2136 model.setData(model.index(i, j, idx), QString::fromLatin1("child%1%2").arg(i).arg(j));
2142 view.setModel(&model);
2144 qApp->processEvents(); //must have this, or else it will not scroll
2145 view.scrollToBottom();
2146 view.resizeColumnToContents(0);
2147 int oldColumnSize = view.header()->sectionSize(0);
2148 view.setRootIndex(model.index(0, 0));
2149 view.resizeColumnToContents(0); //Earlier, this gave an assert
2150 QVERIFY(view.header()->sectionSize(0) > oldColumnSize);
2153 void tst_QTreeView::insertAfterSelect()
2156 model.rows = model.cols = 10;
2158 view.setModel(&model);
2160 QModelIndex firstIndex = model.index(0, 0, QModelIndex());
2161 QVERIFY(firstIndex.isValid());
2162 int itemOffset = view.visualRect(firstIndex).width() / 2;
2163 QPoint p(itemOffset, 1);
2164 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
2165 QVERIFY(view.selectionModel()->isSelected(firstIndex));
2166 model.insertNewRow();
2167 QVERIFY(view.selectionModel()->isSelected(firstIndex)); // Should still be selected
2170 void tst_QTreeView::removeAfterSelect()
2173 model.rows = model.cols = 10;
2175 view.setModel(&model);
2177 QModelIndex firstIndex = model.index(0, 0, QModelIndex());
2178 QVERIFY(firstIndex.isValid());
2179 int itemOffset = view.visualRect(firstIndex).width() / 2;
2180 QPoint p(itemOffset, 1);
2181 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
2182 QVERIFY(view.selectionModel()->isSelected(firstIndex));
2183 model.removeLastRow();
2184 QVERIFY(view.selectionModel()->isSelected(firstIndex)); // Should still be selected
2187 void tst_QTreeView::hiddenItems()
2190 model.rows = model.cols = 10;
2192 view.setModel(&model);
2195 QModelIndex firstIndex = model.index(1, 0, QModelIndex());
2196 QVERIFY(firstIndex.isValid());
2197 if (model.canFetchMore(firstIndex))
2198 model.fetchMore(firstIndex);
2199 for (int i=0; i < model.rowCount(firstIndex); i++)
2200 view.setRowHidden(i , firstIndex, true );
2202 int itemOffset = view.visualRect(firstIndex).width() / 2;
2203 int itemHeight = view.visualRect(firstIndex).height();
2204 QPoint p(itemOffset, itemHeight + 1);
2205 view.setExpanded(firstIndex, false);
2206 QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
2207 QCOMPARE(view.isExpanded(firstIndex), false);
2210 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
2211 QCOMPARE(view.isExpanded(firstIndex), false);
2214 void tst_QTreeView::spanningItems()
2217 model.rows = model.cols = 10;
2219 view.setModel(&model);
2222 int itemWidth = view.header()->sectionSize(0);
2223 int itemHeight = view.visualRect(model.index(0, 0, QModelIndex())).height();
2225 // every second row is spanning
2226 for (int i = 1; i < model.rowCount(QModelIndex()); i += 2)
2227 view.setFirstColumnSpanned(i , QModelIndex(), true);
2229 // non-spanning item
2230 QPoint p(itemWidth / 2, itemHeight / 2); // column 0, row 0
2231 view.setCurrentIndex(QModelIndex());
2232 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
2233 QCOMPARE(view.currentIndex(), model.index(0, 0, QModelIndex()));
2234 QCOMPARE(view.header()->sectionSize(0) - view.indentation(),
2235 view.visualRect(model.index(0, 0, QModelIndex())).width());
2238 p.setX(itemWidth + (itemWidth / 2)); // column 1
2239 p.setY(itemHeight + (itemHeight / 2)); // row 1
2240 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
2241 QCOMPARE(view.currentIndex(), model.index(1, 0, QModelIndex()));
2242 QCOMPARE(view.header()->length() - view.indentation(),
2243 view.visualRect(model.index(1, 0, QModelIndex())).width());
2246 // every second row is un-spanned
2247 QStyleOptionViewItem option = view.viewOptions();
2248 int w = view.header()->sectionSizeHint(0);
2249 for (int i = 0; i < model.rowCount(QModelIndex()); ++i) {
2250 if (!view.isFirstColumnSpanned(i, QModelIndex())) {
2251 QModelIndex index = model.index(i, 0, QModelIndex());
2252 w = qMax(w, view.itemDelegate(index)->sizeHint(option, index).width() + view.indentation());
2255 QCOMPARE(view.sizeHintForColumn(0), w);
2258 void tst_QTreeView::selectionOrderTest()
2260 QVERIFY(((QItemSelectionModel*)sender())->currentIndex().row() != -1);
2263 void tst_QTreeView::selection()
2266 QStandardItemModel m(10, 2);
2267 for (int i = 0;i < 10; ++i)
2268 m.setData(m.index(i, 0), i);
2269 treeView.setModel(&m);
2271 treeView.setSelectionBehavior(QAbstractItemView::SelectRows);
2272 treeView.setSelectionMode(QAbstractItemView::ExtendedSelection);
2274 connect(treeView.selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
2275 this, SLOT(selectionOrderTest()));
2279 QTest::mousePress(treeView.viewport(), Qt::LeftButton, 0, treeView.visualRect(m.index(1, 0)).center());
2280 QTest::keyPress(treeView.viewport(), Qt::Key_Down);
2283 //From task 151686 QTreeView ExtendedSelection selects hidden rows
2284 void tst_QTreeView::selectionWithHiddenItems()
2286 QStandardItemModel model;
2287 for (int i = 0; i < model.rowCount(); ++i)
2288 model.setData(model.index(i,0), QString("row %1").arg(i));
2290 QStandardItem item0("row 0");
2291 QStandardItem item1("row 1");
2292 QStandardItem item2("row 2");
2293 QStandardItem item3("row 3");
2294 model.appendColumn( QList<QStandardItem*>() << &item0 << &item1 << &item2 << &item3);
2296 QStandardItem child("child");
2297 item1.appendRow( &child);
2300 view.setModel(&model);
2301 view.setSelectionMode(QAbstractItemView::ExtendedSelection);
2303 qApp->processEvents();
2305 //child should not be selected as it is hidden (its parent is not expanded)
2307 QCOMPARE(view.selectionModel()->selection().count(), 1); //one range
2308 QCOMPARE(view.selectionModel()->selectedRows().count(), 4);
2310 QVERIFY(view.isExpanded(item1.index()));
2311 QCOMPARE(view.selectionModel()->selection().count(), 1);
2312 QCOMPARE(view.selectionModel()->selectedRows().count(), 4);
2313 QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&child)));
2314 view.clearSelection();
2315 QVERIFY(view.isExpanded(item1.index()));
2317 //child should be selected as it is visible (its parent is expanded)
2319 QCOMPARE(view.selectionModel()->selection().count(), 2);
2320 QCOMPARE(view.selectionModel()->selectedRows().count(), 5); //everything is selected
2321 view.clearSelection();
2323 //we hide the node with a child (there should then be 3 items selected in 2 ranges)
2324 view.setRowHidden(1, QModelIndex(), true);
2325 QVERIFY(view.isExpanded(item1.index()));
2326 qApp->processEvents();
2328 QCOMPARE(view.selectionModel()->selection().count(), 2);
2329 QCOMPARE(view.selectionModel()->selectedRows().count(), 3);
2330 QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&item1)));
2331 QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&child)));
2333 view.setRowHidden(1, QModelIndex(), false);
2334 QVERIFY(view.isExpanded(item1.index()));
2335 view.clearSelection();
2337 //we hide a node without children (there should then be 4 items selected in 3 ranges)
2338 view.setRowHidden(2, QModelIndex(), true);
2339 qApp->processEvents();
2340 QVERIFY(view.isExpanded(item1.index()));
2342 QVERIFY(view.isExpanded(item1.index()));
2343 QCOMPARE(view.selectionModel()->selection().count(), 3);
2344 QCOMPARE(view.selectionModel()->selectedRows().count(), 4);
2345 QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&item2)));
2346 view.setRowHidden(2, QModelIndex(), false);
2347 QVERIFY(view.isExpanded(item1.index()));
2348 view.clearSelection();
2351 void tst_QTreeView::selectAll()
2353 QStandardItemModel model(4,4);
2355 view2.setModel(&model);
2356 view2.setSelectionMode(QAbstractItemView::ExtendedSelection);
2357 view2.selectAll(); // Should work with an empty model
2358 //everything should be selected since we are in ExtendedSelection mode
2359 QCOMPARE(view2.selectedIndexes().count(), model.rowCount() * model.columnCount());
2361 for (int i = 0; i < model.rowCount(); ++i)
2362 model.setData(model.index(i,0), QString("row %1").arg(i));
2364 view.setModel(&model);
2365 int selectedCount = view.selectedIndexes().count();
2367 QCOMPARE(view.selectedIndexes().count(), selectedCount);
2370 void tst_QTreeView::extendedSelection_data()
2372 QTest::addColumn<QPoint>("mousePressPos");
2373 QTest::addColumn<int>("selectedCount");
2375 QTest::newRow("select") << QPoint(10, 10) << 2;
2376 QTest::newRow("unselect") << QPoint(10, 150) << 0;
2379 void tst_QTreeView::extendedSelection()
2381 QFETCH(QPoint, mousePressPos);
2382 QFETCH(int, selectedCount);
2384 QStandardItemModel model(5, 2);
2386 QTreeView view(&topLevel);
2387 view.resize(qMax(mousePressPos.x() * 2, 200), qMax(mousePressPos.y() * 2, 200));
2388 view.setModel(&model);
2389 view.setSelectionMode(QAbstractItemView::ExtendedSelection);
2391 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, mousePressPos);
2392 QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedCount);
2395 void tst_QTreeView::rowSizeHint()
2397 //tests whether the correct visible columns are taken into account when
2398 //calculating the height of a line
2399 QStandardItemModel model(1,3);
2400 model.setData( model.index(0,0), QSize(20,40), Qt::SizeHintRole);
2401 model.setData( model.index(0,1), QSize(20,10), Qt::SizeHintRole);
2402 model.setData( model.index(0,2), QSize(20,10), Qt::SizeHintRole);
2404 view.setModel(&model);
2406 view.header()->moveSection(1, 0); //the 2nd column goes to the 1st place
2410 //it must be 40 since the tallest item that defines the height of a line
2411 QCOMPARE( view.visualRect(model.index(0,0)).height(), 40);
2412 QCOMPARE( view.visualRect(model.index(0,1)).height(), 40);
2413 QCOMPARE( view.visualRect(model.index(0,2)).height(), 40);
2417 //From task 155449 (QTreeWidget has a large width for the first section when sorting
2418 //is turned on before items are added)
2419 void tst_QTreeView::setSortingEnabled()
2421 //1st the treeview is a top-level
2424 QStandardItemModel model(1,1);
2425 view.setModel(&model);
2426 const int size = view.header()->sectionSize(0);
2427 view.setSortingEnabled(true);
2428 model.setColumnCount(3);
2429 //we test that changing the column count doesn't change the 1st column size
2430 QCOMPARE(view.header()->sectionSize(0), size);
2433 //then it is no more a top-level
2437 QStandardItemModel model(1,1);
2438 view.setModel(&model);
2439 win.setCentralWidget(&view);
2440 const int size = view.header()->sectionSize(0);
2441 view.setSortingEnabled(true);
2442 model.setColumnCount(3);
2443 //we test that changing the column count doesn't change the 1st column size
2444 QCOMPARE(view.header()->sectionSize(0), size);
2448 void tst_QTreeView::headerHidden()
2451 QStandardItemModel model;
2452 view.setModel(&model);
2453 QCOMPARE(view.isHeaderHidden(), false);
2454 QCOMPARE(view.header()->isHidden(), false);
2455 view.setHeaderHidden(true);
2456 QCOMPARE(view.isHeaderHidden(), true);
2457 QCOMPARE(view.header()->isHidden(), true);
2460 // From Task 145199 (crash when column 0 having at least one expanded item is removed and then
2461 // inserted). The test passes simply if it doesn't crash, hence there are no calls
2462 // to QCOMPARE() or QVERIFY().
2463 void tst_QTreeView::removeAndInsertExpandedCol0()
2466 QStandardItemModel model;
2467 view.setModel(&model);
2469 model.setColumnCount(1);
2471 QStandardItem *item0 = new QStandardItem(QString("item 0"));
2472 model.invisibleRootItem()->appendRow(item0);
2473 view.expand(item0->index());
2474 QStandardItem *item1 = new QStandardItem(QString("item 1"));
2475 item0->appendRow(item1);
2477 model.removeColumns(0, 1);
2478 model.insertColumns(0, 1);
2481 qApp->processEvents();
2484 void tst_QTreeView::disabledButCheckable()
2487 QStandardItemModel model;
2488 QStandardItem *item;
2489 item = new QStandardItem(QLatin1String("Row 1 Item"));
2490 model.insertRow(0, item);
2492 item = new QStandardItem(QLatin1String("Row 2 Item"));
2493 item->setCheckable(true);
2494 item->setEnabled(false);
2495 model.insertRow(1, item);
2497 view.setModel(&model);
2498 view.setCurrentIndex(model.index(1,0));
2499 QCOMPARE(item->checkState(), Qt::Unchecked);
2502 QTest::keyClick(&view, Qt::Key_Space);
2503 QCOMPARE(item->checkState(), Qt::Unchecked);
2506 void tst_QTreeView::sortByColumn_data()
2508 QTest::addColumn<bool>("sortingEnabled");
2509 QTest::newRow("sorting enabled") << true;
2510 QTest::newRow("sorting disabled") << false;
2513 // Checks sorting and that sortByColumn also sets the sortIndicator
2514 void tst_QTreeView::sortByColumn()
2516 QFETCH(bool, sortingEnabled);
2518 QStandardItemModel model(4,2);
2519 model.setItem(0,0,new QStandardItem("b"));
2520 model.setItem(1,0,new QStandardItem("d"));
2521 model.setItem(2,0,new QStandardItem("c"));
2522 model.setItem(3,0,new QStandardItem("a"));
2523 model.setItem(0,1,new QStandardItem("e"));
2524 model.setItem(1,1,new QStandardItem("g"));
2525 model.setItem(2,1,new QStandardItem("h"));
2526 model.setItem(3,1,new QStandardItem("f"));
2528 view.setSortingEnabled(sortingEnabled);
2529 view.setModel(&model);
2530 view.sortByColumn(1);
2531 QCOMPARE(view.header()->sortIndicatorSection(), 1);
2532 QCOMPARE(view.model()->data(view.model()->index(0,1)).toString(), QString::fromLatin1("h"));
2533 QCOMPARE(view.model()->data(view.model()->index(1,1)).toString(), QString::fromLatin1("g"));
2534 view.sortByColumn(0, Qt::AscendingOrder);
2535 QCOMPARE(view.header()->sortIndicatorSection(), 0);
2536 QCOMPARE(view.model()->data(view.model()->index(0,0)).toString(), QString::fromLatin1("a"));
2537 QCOMPARE(view.model()->data(view.model()->index(1,0)).toString(), QString::fromLatin1("b"));
2541 This is a model that every time kill() is called it will completely change
2542 all of its nodes for new nodes. It then qFatal's if you later use a dead node.
2544 class EvilModel: public QAbstractItemModel
2550 Node(Node *p = 0, int level = 0) : parent(p), isDead(false) {
2555 qDeleteAll(children.begin(), children.end());
2556 qDeleteAll(deadChildren.begin(), deadChildren.end());
2559 void populate(int level = 0) {
2561 for (int i = 0; i < 5; ++i)
2562 children.append(new Node(this, level + 1));
2565 for (int i = children.count() -1; i >= 0; --i) {
2566 children.at(i)->kill();
2568 deadChildren.append(children.at(i));
2569 children.removeAt(i);
2573 if (!children.isEmpty())
2574 qFatal("%s: children should be empty when parent is null", Q_FUNC_INFO);
2581 QList<Node*> children;
2582 QList<Node*> deadChildren;
2589 EvilModel(QObject *parent = 0): QAbstractItemModel(parent), root(new Node)
2599 emit layoutAboutToBeChanged();
2600 QModelIndexList oldList = persistentIndexList();
2601 QList<QStack<int> > oldListPath;
2602 for (int i = 0; i < oldList.count(); ++i) {
2603 QModelIndex idx = oldList.at(i);
2605 while (idx.isValid()) {
2606 path.push(idx.row());
2609 oldListPath.append(path);
2613 QModelIndexList newList;
2614 for (int i = 0; i < oldListPath.count(); ++i) {
2615 QStack<int> path = oldListPath[i];
2617 while(!path.isEmpty()) {
2618 idx = index(path.pop(), 0, idx);
2620 newList.append(idx);
2623 changePersistentIndexList(oldList, newList);
2624 emit layoutChanged();
2627 int rowCount(const QModelIndex& parent = QModelIndex()) const {
2628 Node *parentNode = root;
2629 if (parent.isValid()) {
2630 parentNode = static_cast<Node*>(parent.internalPointer());
2631 if (parentNode->isDead)
2632 qFatal("%s: parentNode is dead!", Q_FUNC_INFO);
2634 return parentNode->children.count();
2636 int columnCount(const QModelIndex& parent = QModelIndex()) const {
2637 if (parent.column() > 0)
2642 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
2644 Node *grandparentNode = static_cast<Node*>(parent.internalPointer());
2645 Node *parentNode = root;
2646 if (parent.isValid()) {
2647 if (grandparentNode->isDead)
2648 qFatal("%s: grandparentNode is dead!", Q_FUNC_INFO);
2649 parentNode = grandparentNode->children[parent.row()];
2650 if (parentNode->isDead)
2651 qFatal("%s: grandparentNode is dead!", Q_FUNC_INFO);
2653 return createIndex(row, column, parentNode);
2656 QModelIndex parent(const QModelIndex &index) const
2658 Node *parent = static_cast<Node*>(index.internalPointer());
2659 Node *grandparent = parent->parent;
2661 return QModelIndex();
2662 return createIndex(grandparent->children.indexOf(parent), 0, grandparent);
2665 QVariant data(const QModelIndex &idx, int role) const
2667 if (idx.isValid() && role == Qt::DisplayRole) {
2668 Node *parentNode = root;
2669 if (idx.isValid()) {
2670 parentNode = static_cast<Node*>(idx.internalPointer());
2671 if (parentNode->isDead)
2672 qFatal("%s: grandparentNode is dead!", Q_FUNC_INFO);
2674 return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column())
2675 .arg(parentNode->isDead ? "dead" : "alive");
2681 void tst_QTreeView::evilModel_data()
2683 QTest::addColumn<bool>("visible");
2684 QTest::newRow("visible") << false;
2687 void tst_QTreeView::evilModel()
2689 QFETCH(bool, visible);
2693 view.setModel(&model);
2694 view.setVisible(visible);
2695 QPersistentModelIndex firstLevel = model.index(0, 0);
2696 QPersistentModelIndex secondLevel = model.index(1, 0, firstLevel);
2697 QPersistentModelIndex thirdLevel = model.index(2, 0, secondLevel);
2698 view.setExpanded(firstLevel, true);
2699 view.setExpanded(secondLevel, true);
2700 view.setExpanded(thirdLevel, true);
2704 view.setRowHidden(0, firstLevel, true);
2708 view.setFirstColumnSpanned(1, QModelIndex(), true);
2711 view.expand(secondLevel);
2714 view.collapse(secondLevel);
2717 view.isExpanded(secondLevel);
2718 view.setCurrentIndex(firstLevel);
2721 view.keyboardSearch("foo");
2724 view.visualRect(secondLevel);
2727 view.scrollTo(thirdLevel);
2733 QTest::mouseDClick(view.viewport(), Qt::LeftButton);
2736 view.indexAt(QPoint(10, 10));
2739 view.indexAbove(model.index(2, 0));
2742 view.indexBelow(model.index(1, 0));
2745 QRect rect(0, 0, 10, 10);
2746 view.setSelection(rect, QItemSelectionModel::Select);
2749 view.moveCursor(PublicView::MoveDown, Qt::NoModifier);
2752 view.resizeColumnToContents(1);
2755 view.QAbstractItemView::sizeHintForColumn(1);
2758 view.rowHeight(secondLevel);
2761 view.setRootIsDecorated(true);
2764 view.setItemsExpandable(false);
2767 view.columnViewportPosition(0);
2770 view.columnWidth(0);
2773 view.setColumnWidth(0, 30);
2779 view.isColumnHidden(1);
2782 view.setColumnHidden(2, true);
2785 view.isHeaderHidden();
2788 view.setHeaderHidden(true);
2791 view.isRowHidden(2, secondLevel);
2794 view.setRowHidden(3, secondLevel, true);
2797 view.isFirstColumnSpanned(3, thirdLevel);
2800 view.setSortingEnabled(true);
2803 view.isSortingEnabled();
2806 view.setAnimated(true);
2812 view.setAllColumnsShowFocus(true);
2815 view.allColumnsShowFocus();
2818 view.doItemsLayout();
2824 view.sortByColumn(1, Qt::AscendingOrder);
2827 view.dataChanged(secondLevel, secondLevel);
2836 view.resizeColumnToContents(1);
2839 view.sortByColumn(1);
2851 view.expandToDepth(3);
2854 view.setRootIndex(secondLevel);
2857 void tst_QTreeView::indexRowSizeHint()
2859 QStandardItemModel model(10, 1);
2862 view.setModel(&model);
2864 QModelIndex index = model.index(5, 0);
2865 QPushButton *w = new QPushButton("Test");
2866 view.setIndexWidget(index, w);
2870 QCOMPARE(view.indexRowSizeHint(index), w->sizeHint().height());
2873 void tst_QTreeView::filterProxyModelCrash()
2875 QStandardItemModel model;
2876 QList<QStandardItem *> items;
2877 for (int i = 0; i < 100; i++)
2878 items << new QStandardItem(QString::fromLatin1("item %1").arg(i));
2879 model.appendColumn(items);
2881 QSortFilterProxyModel proxy;
2882 proxy.setSourceModel(&model);
2885 view.setModel(&proxy);
2889 view.verticalScrollBar()->setValue(15);
2893 view.repaint(); //used to crash
2896 void tst_QTreeView::renderToPixmap_data()
2898 QTest::addColumn<int>("row");
2899 QTest::newRow("row-0") << 0;
2900 QTest::newRow("row-1") << 1;
2903 void tst_QTreeView::renderToPixmap()
2907 QStandardItemModel model;
2909 model.appendRow(new QStandardItem("Spanning"));
2910 model.appendRow(QList<QStandardItem*>() << new QStandardItem("Not") << new QStandardItem("Spanning"));
2912 view.setModel(&model);
2913 view.setFirstColumnSpanned(0, QModelIndex(), true);
2915 #ifdef QT_BUILD_INTERNAL
2917 // We select the index at row=0 because it spans the
2918 // column (regression test for an assert)
2919 // We select the index at row=1 for coverage.
2920 QItemSelection sel(model.index(row,0), model.index(row,1));
2922 view.aiv_priv()->renderToPixmap(sel.indexes(), &rect);
2927 void tst_QTreeView::styleOptionViewItem()
2929 class MyDelegate : public QStyledItemDelegate
2931 static QString posToString(QStyleOptionViewItemV4::ViewItemPosition pos) {
2932 static const char* s_pos[] = { "Invalid", "Beginning", "Middle", "End", "OnlyOne" };
2936 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
2938 QVERIFY(qstyleoption_cast<const QStyleOptionViewItemV4 *>(&option));
2939 QStyleOptionViewItemV4 opt(option);
2940 initStyleOption(&opt, index);
2942 QVERIFY(!opt.text.isEmpty());
2943 QCOMPARE(opt.index, index);
2944 //qDebug() << index << opt.text;
2947 QCOMPARE(!(opt.features & QStyleOptionViewItemV2::Alternate), !(index.row() % 2));
2948 QCOMPARE(!(opt.features & QStyleOptionViewItemV2::HasCheckIndicator), !opt.text.contains("Checkable"));
2950 if (opt.text.contains("Beginning"))
2951 QCOMPARE(posToString(opt.viewItemPosition), posToString(QStyleOptionViewItemV4::Beginning));
2953 if (opt.text.contains("Middle"))
2954 QCOMPARE(posToString(opt.viewItemPosition), posToString(QStyleOptionViewItemV4::Middle));
2956 if (opt.text.contains("End"))
2957 QCOMPARE(posToString(opt.viewItemPosition), posToString(QStyleOptionViewItemV4::End));
2959 if (opt.text.contains("OnlyOne"))
2960 QCOMPARE(posToString(opt.viewItemPosition), posToString(QStyleOptionViewItemV4::OnlyOne));
2962 if (opt.text.contains("Checked"))
2963 QCOMPARE(opt.checkState, Qt::Checked);
2965 QCOMPARE(opt.checkState, Qt::Unchecked);
2967 QCOMPARE(!(opt.state & QStyle::State_Children) , !opt.text.contains("HasChildren"));
2968 QCOMPARE(!!(opt.state & QStyle::State_Sibling) , !opt.text.contains("Last"));
2970 QVERIFY(!opt.text.contains("Assert"));
2972 QStyledItemDelegate::paint(painter, option, index);
2980 QStandardItemModel model;
2981 view.setModel(&model);
2982 MyDelegate delegate;
2983 view.setItemDelegate(&delegate);
2984 model.appendRow(QList<QStandardItem*>()
2985 << new QStandardItem("Beginning") << new QStandardItem("Hidden") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") );
2986 QStandardItem *par1 = new QStandardItem("Beginning HasChildren");
2987 model.appendRow(QList<QStandardItem*>()
2988 << par1 << new QStandardItem("Hidden") << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") );
2989 model.appendRow(QList<QStandardItem*>()
2990 << new QStandardItem("OnlyOne") << new QStandardItem("Hidden") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Assert") );
2991 QStandardItem *checkable = new QStandardItem("Checkable");
2992 checkable->setCheckable(true);
2993 QStandardItem *checked = new QStandardItem("Checkable Checked");
2994 checked->setCheckable(true);
2995 checked->setCheckState(Qt::Checked);
2996 model.appendRow(QList<QStandardItem*>()
2997 << new QStandardItem("Beginning") << new QStandardItem("Hidden") << checkable << checked << new QStandardItem("End") );
2998 model.appendRow(QList<QStandardItem*>()
2999 << new QStandardItem("Beginning Last") << new QStandardItem("Hidden") << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") );
3001 par1->appendRow(QList<QStandardItem*>()
3002 << new QStandardItem("Beginning") << new QStandardItem("Hidden") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") );
3003 QStandardItem *par2 = new QStandardItem("Beginning HasChildren");
3004 par1->appendRow(QList<QStandardItem*>()
3005 << par2 << new QStandardItem("Hidden") << new QStandardItem("Middle HasChildren") << new QStandardItem("Middle HasChildren") << new QStandardItem("End HasChildren") );
3006 par2->appendRow(QList<QStandardItem*>()
3007 << new QStandardItem("Beginning Last") << new QStandardItem("Hidden") << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") );
3009 QStandardItem *par3 = new QStandardItem("Beginning Last");
3010 par1->appendRow(QList<QStandardItem*>()
3011 << par3 << new QStandardItem("Hidden") << new QStandardItem("Middle Last") << new QStandardItem("Middle Last") << new QStandardItem("End Last") );
3012 par3->appendRow(QList<QStandardItem*>()
3013 << new QStandardItem("Assert") << new QStandardItem("Hidden") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Asser") );
3014 view.setRowHidden(0, par3->index(), true);
3015 par1->appendRow(QList<QStandardItem*>()
3016 << new QStandardItem("Assert") << new QStandardItem("Hidden") << new QStandardItem("Assert") << new QStandardItem("Assert") << new QStandardItem("Asser") );
3017 view.setRowHidden(3, par1->index(), true);
3019 view.setColumnHidden(1, true);
3020 const int visibleColumns = 4;
3021 const int modelColumns = 5;
3023 view.header()->swapSections(2, 3);
3024 view.setFirstColumnSpanned(2, QModelIndex(), true);
3025 view.setAlternatingRowColors(true);
3027 #ifdef QT_BUILD_INTERNAL
3029 // Test the rendering to pixmap before painting the widget.
3030 // The rendering to pixmap should not depend on having been
3031 // painted already yet.
3033 QItemSelection sel(model.index(0,0), model.index(0,modelColumns-1));
3035 view.aiv_priv()->renderToPixmap(sel.indexes(), &rect);
3036 if (delegate.count != visibleColumns) {
3037 qDebug() << rect << view.rect() << view.isVisible();
3039 QTRY_COMPARE(delegate.count, visibleColumns);
3044 delegate.allCollapsed = true;
3045 view.showMaximized();
3046 QApplication::processEvents();
3047 QTRY_VERIFY(delegate.count >= 13);
3049 delegate.allCollapsed = false;
3051 QApplication::processEvents();
3052 QTRY_VERIFY(delegate.count >= 13);
3054 view.collapse(par2->index());
3055 QApplication::processEvents();
3056 QTRY_VERIFY(delegate.count >= 4);
3058 // test that the rendering of drag pixmap sets the correct options too (QTBUG-15834)
3059 #ifdef QT_BUILD_INTERNAL
3061 QItemSelection sel(model.index(0,0), model.index(0,modelColumns-1));
3063 view.aiv_priv()->renderToPixmap(sel.indexes(), &rect);
3064 if (delegate.count != visibleColumns) {
3065 qDebug() << rect << view.rect() << view.isVisible();
3067 QTRY_COMPARE(delegate.count, visibleColumns);
3070 //test dynamic models
3073 QStandardItemModel model2;
3074 QStandardItem *item0 = new QStandardItem("OnlyOne Last");
3075 model2.appendRow(QList<QStandardItem*>() << item0);
3076 view.setModel(&model2);
3077 QApplication::processEvents();
3078 QTRY_VERIFY(delegate.count >= 1);
3079 QApplication::processEvents();
3081 QStandardItem *item00 = new QStandardItem("OnlyOne Last");
3082 item0->appendRow(QList<QStandardItem*>() << item00);
3083 item0->setText("OnlyOne Last HasChildren");
3084 QApplication::processEvents();
3087 QApplication::processEvents();
3088 QTRY_VERIFY(delegate.count >= 2);
3089 QApplication::processEvents();
3091 QStandardItem *item1 = new QStandardItem("OnlyOne Last");
3093 item0->setText("OnlyOne HasChildren");
3094 model2.appendRow(QList<QStandardItem*>() << item1);
3095 QApplication::processEvents();
3096 QTRY_VERIFY(delegate.count >= 3);
3097 QApplication::processEvents();
3099 QStandardItem *item01 = new QStandardItem("OnlyOne Last");
3101 item00->setText("OnlyOne");
3102 item0->appendRow(QList<QStandardItem*>() << item01);
3103 QApplication::processEvents();
3104 QTRY_VERIFY(delegate.count >= 4);
3105 QApplication::processEvents();
3107 QStandardItem *item000 = new QStandardItem("OnlyOne Last");
3109 item00->setText("OnlyOne HasChildren");
3110 item00->appendRow(QList<QStandardItem*>() << item000);
3111 QApplication::processEvents();
3112 QTRY_VERIFY(delegate.count >= 5);
3113 QApplication::processEvents();
3116 item0->removeRow(0);
3117 QApplication::processEvents();
3118 QTRY_VERIFY(delegate.count >= 3);
3119 QApplication::processEvents();
3121 item00 = new QStandardItem("OnlyOne");
3122 item0->insertRow(0, QList<QStandardItem*>() << item00);
3123 QApplication::processEvents();
3126 QApplication::processEvents();
3127 QTRY_VERIFY(delegate.count >= 4);
3128 QApplication::processEvents();
3131 item0->removeRow(1);
3132 item00->setText("OnlyOne Last");
3133 QApplication::processEvents();
3134 QTRY_VERIFY(delegate.count >= 3);
3135 QApplication::processEvents();
3138 item0->removeRow(0);
3139 item0->setText("OnlyOne");
3140 QApplication::processEvents();
3141 QTRY_VERIFY(delegate.count >= 2);
3142 QApplication::processEvents();
3145 item0->setText("OnlyOne HasChildren");
3146 item00 = new QStandardItem("OnlyOne");
3147 item0->appendRow(QList<QStandardItem*>() << item00);
3148 item01 = new QStandardItem("Assert");
3149 item0->appendRow(QList<QStandardItem*>() << item01);
3150 view.setRowHidden(1, item0->index(), true);
3152 QStandardItem *item02 = new QStandardItem("OnlyOne Last");
3153 item0->appendRow(QList<QStandardItem*>() << item02);
3155 QApplication::processEvents();
3156 QTRY_VERIFY(delegate.count >= 4);
3157 QApplication::processEvents();
3159 item0->removeRow(2);
3160 item00->setText("OnlyOne Last");
3162 QApplication::processEvents();
3163 QTRY_VERIFY(delegate.count >= 3);
3164 QApplication::processEvents();
3166 item00->setText("OnlyOne");
3167 item0->insertRow(2, new QStandardItem("OnlyOne Last"));
3168 view.collapse(item0->index());
3169 item0->removeRow(0);
3171 QTRY_VERIFY(delegate.count >= 2);
3172 QApplication::processEvents();
3174 item0->removeRow(1);
3175 item0->setText("OnlyOne");
3177 QTRY_VERIFY(delegate.count >= 2);
3178 QApplication::processEvents();
3182 class task174627_TreeView : public QTreeView
3186 void currentChanged(const QModelIndex ¤t, const QModelIndex &)
3187 { emit currentChanged(current); }
3189 void currentChanged(const QModelIndex &);
3192 void tst_QTreeView::task174627_moveLeftToRoot()
3194 QStandardItemModel model;
3195 QStandardItem *item1 = new QStandardItem(QString("item 1"));
3196 model.invisibleRootItem()->appendRow(item1);
3197 QStandardItem *item2 = new QStandardItem(QString("item 2"));
3198 item1->appendRow(item2);
3200 task174627_TreeView view;
3201 view.setModel(&model);
3202 view.setRootIndex(item1->index());
3203 view.setCurrentIndex(item2->index());
3205 QSignalSpy spy(&view, SIGNAL(currentChanged(QModelIndex)));
3206 QTest::keyClick(&view, Qt::Key_Left);
3207 QCOMPARE(spy.count(), 0);
3210 void tst_QTreeView::task171902_expandWith1stColHidden()
3212 //the task was: if the first column of a treeview is hidden, the expanded state is not correctly restored
3213 QStandardItemModel model;
3214 QStandardItem root("root"), root2("root"),
3215 subitem("subitem"), subitem2("subitem"),
3216 subsubitem("subsubitem"), subsubitem2("subsubitem");
3218 model.appendRow( QList<QStandardItem *>() << &root << &root2);
3219 root.appendRow( QList<QStandardItem *>() << &subitem << &subitem2);
3220 subitem.appendRow( QList<QStandardItem *>() << &subsubitem << &subsubitem2);
3223 view.setModel(&model);
3225 view.setColumnHidden(0, true);
3227 view.collapse(root.index());
3228 view.expand(root.index());
3230 QCOMPARE(view.isExpanded(root.index()), true);
3231 QCOMPARE(view.isExpanded(subitem.index()), true);
3235 void tst_QTreeView::task203696_hidingColumnsAndRowsn()
3238 QStandardItemModel *model = new QStandardItemModel(0, 3, &view);
3239 for (int i = 0; i < 3; ++i)
3241 model->insertRow(model->rowCount());
3242 for (int j = 0; j < model->columnCount(); ++j)
3243 model->setData(model->index(i, j), QString("row %1 col %2").arg(i).arg(j));
3245 view.setModel(model);
3247 view.setColumnHidden(0, true);
3248 view.setRowHidden(0, QModelIndex(), true);
3249 QCOMPARE(view.indexAt(QPoint(0, 0)), model->index(1, 1));
3253 void tst_QTreeView::addRowsWhileSectionsAreHidden()
3256 for (int pass = 1; pass <= 2; ++pass) {
3257 QStandardItemModel *model = new QStandardItemModel(6, pass, &view);
3258 view.setModel(model);
3262 for (i = 0; i < 3; ++i)
3264 model->insertRow(model->rowCount());
3265 for (int j = 0; j < model->columnCount(); ++j) {
3266 model->setData(model->index(i, j), QString("row %1 col %2").arg(i).arg(j));
3270 for (col = 0; col < pass; ++col)
3271 view.setColumnHidden(col, true);
3272 for (i = 3; i < 6; ++i)
3274 model->insertRow(model->rowCount());
3275 for (int j = 0; j < model->columnCount(); ++j) {
3276 model->setData(model->index(i, j), QString("row %1 col %2").arg(i).arg(j));
3279 for (col = 0; col < pass; ++col)
3280 view.setColumnHidden(col, false);
3283 for (i = 0; i < 6; ++i) {
3284 QRect rect = view.visualRect(model->index(i, 0));
3285 QCOMPARE(rect.isValid(), true);
3292 void tst_QTreeView::task216717_updateChildren()
3294 class Tree : public QTreeWidget {
3296 void paintEvent(QPaintEvent *e)
3298 QTreeWidget::paintEvent(e);
3305 QVERIFY(QTest::qWaitForWindowExposed(&tree));
3306 tree.refreshed = false;
3307 QTreeWidgetItem *parent = new QTreeWidgetItem(QStringList() << "parent");
3308 tree.addTopLevelItem(parent);
3310 QTRY_VERIFY(tree.refreshed);
3311 tree.refreshed = false;
3312 parent->addChild(new QTreeWidgetItem(QStringList() << "child"));
3314 QTRY_VERIFY(tree.refreshed);
3318 void tst_QTreeView::task220298_selectColumns()
3320 //this is a very simple 3x3 model where the internalId of the index are different for each cell
3321 class Model : public QAbstractTableModel
3323 virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const
3324 { return parent.isValid() ? 0 : 3; }
3325 virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const
3326 { return parent.isValid() ? 0 : 3; }
3328 virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const
3330 if(role == Qt::DisplayRole)
3331 return QVariant(QString("%1-%2").arg(index.column()).arg(index.row()));
3335 virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const
3337 return hasIndex(row, column, parent) ? createIndex(row, column, column*10+row) : QModelIndex();
3341 class TreeView : public QTreeView { public: QModelIndexList selectedIndexes () const { return QTreeView::selectedIndexes(); } } view;
3343 view.setModel(&model);
3346 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
3347 view.visualRect(view.model()->index(1, 1)).center());
3349 QVERIFY(view.selectedIndexes().contains(view.model()->index(1, 2)));
3350 QVERIFY(view.selectedIndexes().contains(view.model()->index(1, 1)));
3351 QVERIFY(view.selectedIndexes().contains(view.model()->index(1, 0)));
3355 void tst_QTreeView::task224091_appendColumns()
3357 QStandardItemModel *model = new QStandardItemModel();
3358 QWidget* topLevel= new QWidget;
3359 QTreeView *treeView = new QTreeView(topLevel);
3360 treeView->setModel(model);
3362 treeView->resize(50,50);
3363 qApp->setActiveWindow(topLevel);
3364 QVERIFY(QTest::qWaitForWindowActive(topLevel));
3366 QList<QStandardItem *> projlist;
3367 for (int k = 0; k < 10; ++k)
3368 projlist.append(new QStandardItem(QString("Top Level %0").arg(k)));
3369 model->appendColumn(projlist);
3370 model->invisibleRootItem()->appendRow(new QStandardItem("end"));
3373 qApp->processEvents();
3375 QTRY_VERIFY(treeView->verticalScrollBar()->isVisible());
3381 void tst_QTreeView::task211293_removeRootIndex()
3384 QStandardItemModel model;
3385 QStandardItem *A1 = new QStandardItem("A1");
3386 QStandardItem *B11 = new QStandardItem("B1.1");
3387 QStandardItem *C111 = new QStandardItem("C1.1.1");
3388 QStandardItem *C112 = new QStandardItem("C1.1.2");
3389 QStandardItem *C113 = new QStandardItem("C1.1.3");
3390 QStandardItem *D1131 = new QStandardItem("D1.1.3.1");
3391 QStandardItem *E11311 = new QStandardItem("E1.1.3.1.1");
3392 QStandardItem *E11312 = new QStandardItem("E1.1.3.1.2");
3393 QStandardItem *E11313 = new QStandardItem("E1.1.3.1.3");
3394 QStandardItem *E11314 = new QStandardItem("E1.1.3.1.4");
3395 QStandardItem *D1132 = new QStandardItem("D1.1.3.2");
3396 QStandardItem *E11321 = new QStandardItem("E1.1.3.2.1");
3397 D1132->appendRow(E11321);
3398 D1131->appendRow(E11311);
3399 D1131->appendRow(E11312);
3400 D1131->appendRow(E11313);
3401 D1131->appendRow(E11314);
3402 C113->appendRow(D1131);
3403 C113->appendRow(D1132);
3404 B11->appendRow(C111);
3405 B11->appendRow(C112);
3406 B11->appendRow(C113);
3408 model.appendRow(A1);
3409 view.setModel(&model);
3410 view.setRootIndex(model.indexFromItem(B11));
3411 view.setExpanded(model.indexFromItem(B11), true);
3412 view.setCurrentIndex(model.indexFromItem(E11314));
3413 view.setExpanded(model.indexFromItem(E11314), true);
3415 qApp->processEvents();
3416 model.removeRows(0, 1);
3417 qApp->processEvents();
3420 void tst_QTreeView::task225539_deleteModel()
3424 QStandardItemModel *model = new QStandardItemModel(&treeView);
3426 QStandardItem* parentItem = model->invisibleRootItem();
3427 QStandardItem* item = new QStandardItem(QString("item"));
3428 parentItem->appendRow(item);
3430 treeView.setModel(model);
3432 QCOMPARE(item->index(), treeView.indexAt(QPoint()));
3436 QVERIFY(!treeView.indexAt(QPoint()).isValid());
3439 void tst_QTreeView::task230123_setItemsExpandable()
3441 //let's check that we prevent the expansion inside a treeview
3442 //when the property is set.
3445 QTreeWidgetItem root;
3446 QTreeWidgetItem child;
3447 root.addChild(&child);
3448 tree.addTopLevelItem(&root);
3450 tree.setCurrentItem(&root);
3452 tree.setItemsExpandable(false);
3454 QTest::keyClick(&tree, Qt::Key_Plus);
3455 QVERIFY(!root.isExpanded());
3457 QTest::keyClick(&tree, Qt::Key_Right);
3458 QVERIFY(!root.isExpanded());
3460 tree.setItemsExpandable(true);
3462 QTest::keyClick(&tree, Qt::Key_Plus);
3463 QVERIFY(root.isExpanded());
3465 QTest::keyClick(&tree, Qt::Key_Minus);
3466 QVERIFY(!root.isExpanded());
3468 QTest::keyClick(&tree, Qt::Key_Right);
3469 QVERIFY(root.isExpanded());
3471 QTest::keyClick(&tree, Qt::Key_Left);
3472 QVERIFY(!root.isExpanded());
3474 QTest::keyClick(&tree, Qt::Key_Right);
3475 QVERIFY(root.isExpanded());
3477 const bool navToChild = tree.style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, &tree);
3478 QTest::keyClick(&tree, Qt::Key_Right);
3479 QCOMPARE(tree.currentItem(), navToChild ? &child : &root);
3481 QTest::keyClick(&tree, Qt::Key_Right);
3482 //it should not be expanded: it has no leaf
3483 QCOMPARE(child.isExpanded(), false);
3485 QTest::keyClick(&tree, Qt::Key_Left);
3486 QCOMPARE(tree.currentItem(), &root);
3488 QTest::keyClick(&tree, Qt::Key_Left);
3489 QVERIFY(!root.isExpanded());
3494 void tst_QTreeView::task202039_closePersistentEditor()
3496 QStandardItemModel model(1,1);
3498 view.setModel(&model);
3500 QModelIndex current = model.index(0,0);
3501 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
3502 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
3503 QCOMPARE(view.currentIndex(), current);
3504 QVERIFY(view.indexWidget(current));
3506 view.closePersistentEditor(current);
3507 QVERIFY(view.indexWidget(current) == 0);
3509 //here was the bug: closing the persistent editor would not reset the state
3510 //and it was impossible to go into editinon again
3511 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
3512 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(current).center());
3513 QCOMPARE(view.currentIndex(), current);
3514 QVERIFY(view.indexWidget(current));
3517 void tst_QTreeView::task238873_avoidAutoReopening()
3519 QStandardItemModel model;
3521 QStandardItem item0("row 0");
3522 QStandardItem item1("row 1");
3523 QStandardItem item2("row 2");
3524 QStandardItem item3("row 3");
3525 model.appendColumn( QList<QStandardItem*>() << &item0 << &item1 << &item2 << &item3);
3527 QStandardItem child("child");
3528 item1.appendRow( &child);
3531 view.setModel(&model);
3536 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(child.index()).center());
3538 QCOMPARE(view.currentIndex(), child.index());
3540 view.setExpanded(item1.index(), false);
3542 QTest::qWait(500); //enough to trigger the delayedAutoScroll timer
3543 QVERIFY(!view.isExpanded(item1.index()));
3546 void tst_QTreeView::task244304_clickOnDecoration()
3549 QStandardItemModel model;
3550 QStandardItem item0("row 0");
3551 QStandardItem item00("row 0");
3552 item0.appendRow(&item00);
3553 QStandardItem item1("row 1");
3554 model.appendColumn(QList<QStandardItem*>() << &item0 << &item1);
3555 view.setModel(&model);
3557 QVERIFY(!view.currentIndex().isValid());
3558 QRect rect = view.visualRect(item0.index());
3559 //we click on the decoration
3560 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, rect.topLeft()+QPoint(-rect.left()/2,rect.height()/2));
3561 QVERIFY(!view.currentIndex().isValid());
3562 QVERIFY(view.isExpanded(item0.index()));
3564 rect = view.visualRect(item1.index());
3565 //the item has no decoration, it should get selected
3566 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, rect.topLeft()+QPoint(-rect.left()/2,rect.height()/2));
3567 QCOMPARE(view.currentIndex(), item1.index());
3570 void tst_QTreeView::task246536_scrollbarsNotWorking()
3572 struct MyObject : public QObject
3574 MyObject() : count(0)
3578 bool eventFilter(QObject*, QEvent *e)
3580 if (e->type() == QEvent::Paint)
3590 tree.viewport()->installEventFilter(&o);
3591 QStandardItemModel model;
3592 tree.setModel(&model);
3594 QVERIFY(QTest::qWaitForWindowExposed(&tree));
3595 QList<QStandardItem *> items;
3596 for(int i=0; i<100; ++i){
3597 items << new QStandardItem(QString::fromLatin1("item %1").arg(i));
3599 model.invisibleRootItem()->appendColumn(items);
3602 tree.verticalScrollBar()->setValue(50);
3604 QTRY_VERIFY(o.count > 0);
3607 void tst_QTreeView::task250683_wrongSectionSize()
3611 treeView.header()->setSectionResizeMode(QHeaderView::ResizeToContents);
3612 treeView.setModel(&model);
3613 treeView.setColumnHidden(2, true);
3614 treeView.setColumnHidden(3, true);
3619 QCOMPARE(treeView.header()->sectionSize(0) + treeView.header()->sectionSize(1), treeView.viewport()->width());
3622 void tst_QTreeView::task239271_addRowsWithFirstColumnHidden()
3624 class MyDelegate : public QStyledItemDelegate
3627 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
3629 paintedIndexes << index;
3630 QStyledItemDelegate::paint(painter, option, index);
3633 mutable QSet<QModelIndex> paintedIndexes;
3637 QStandardItemModel model;
3638 view.setModel(&model);
3639 MyDelegate delegate;
3640 view.setItemDelegate(&delegate);
3641 QStandardItem root0("root0"), root1("root1");
3642 model.invisibleRootItem()->appendRow(QList<QStandardItem*>() << &root0 << &root1);
3643 QStandardItem sub0("sub0"), sub00("sub00");
3644 root0.appendRow(QList<QStandardItem*>() << &sub0 << &sub00);
3645 view.expand(root0.index());
3649 QVERIFY(QTest::qWaitForWindowExposed(&view));
3650 delegate.paintedIndexes.clear();
3651 QStandardItem sub1("sub1"), sub11("sub11");
3652 root0.appendRow(QList<QStandardItem*>() << &sub1 << &sub11);
3655 //items in the 2nd column should have been painted
3656 QTRY_VERIFY(!delegate.paintedIndexes.isEmpty());
3657 QVERIFY(delegate.paintedIndexes.contains(sub00.index()));
3658 QVERIFY(delegate.paintedIndexes.contains(sub11.index()));
3661 void tst_QTreeView::task254234_proxySort()
3663 //based on tst_QTreeView::sortByColumn
3664 // it used not to work when setting the source of a proxy after enabling sorting
3666 QStandardItemModel model(4,2);
3667 model.setItem(0,0,new QStandardItem("b"));
3668 model.setItem(1,0,new QStandardItem("d"));
3669 model.setItem(2,0,new QStandardItem("c"));
3670 model.setItem(3,0,new QStandardItem("a"));
3671 model.setItem(0,1,new QStandardItem("e"));
3672 model.setItem(1,1,new QStandardItem("g"));
3673 model.setItem(2,1,new QStandardItem("h"));
3674 model.setItem(3,1,new QStandardItem("f"));
3676 view.sortByColumn(1);
3677 view.setSortingEnabled(true);
3679 QSortFilterProxyModel proxy;
3680 proxy.setDynamicSortFilter(true);
3681 view.setModel(&proxy);
3682 proxy.setSourceModel(&model);
3683 QCOMPARE(view.header()->sortIndicatorSection(), 1);
3684 QCOMPARE(view.model()->data(view.model()->index(0,1)).toString(), QString::fromLatin1("h"));
3685 QCOMPARE(view.model()->data(view.model()->index(1,1)).toString(), QString::fromLatin1("g"));
3688 class TreeView : public QTreeView
3692 void handleSelectionChanged()
3694 //let's select the last item
3695 QModelIndex idx = model()->index(0, 0);
3696 selectionModel()->select(QItemSelection(idx, idx), QItemSelectionModel::Select);
3697 disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(handleSelectionChanged()));
3701 void tst_QTreeView::task248022_changeSelection()
3703 //we check that changing the selection between the mouse press and the mouse release
3706 QStringList list = QStringList() << "1" << "2";
3707 QStringListModel model(list);
3708 view.setSelectionMode(QAbstractItemView::ExtendedSelection);
3709 view.setModel(&model);
3710 view.connect(view.selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(handleSelectionChanged()));
3711 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(model.index(1)).center());
3712 QCOMPARE(view.selectionModel()->selectedIndexes().count(), list.count());
3715 void tst_QTreeView::task245654_changeModelAndExpandAll()
3718 QStandardItemModel *model = new QStandardItemModel;
3719 QStandardItem *top = new QStandardItem("top");
3720 QStandardItem *sub = new QStandardItem("sub");
3721 top->appendRow(sub);
3722 model->appendRow(top);
3723 view.setModel(model);
3725 QApplication::processEvents();
3726 QVERIFY(view.isExpanded(top->index()));
3728 //now let's try to delete the model
3729 //then repopulate and expand again
3731 model = new QStandardItemModel;
3732 top = new QStandardItem("top");
3733 sub = new QStandardItem("sub");
3734 top->appendRow(sub);
3735 model->appendRow(top);
3736 view.setModel(model);
3738 QApplication::processEvents();
3739 QVERIFY(view.isExpanded(top->index()));
3743 void tst_QTreeView::doubleClickedWithSpans()
3746 QStandardItemModel model(1, 2);
3747 view.setModel(&model);
3748 view.setFirstColumnSpanned(0, QModelIndex(), true);
3750 QApplication::setActiveWindow(&view);
3751 QVERIFY(QTest::qWaitForWindowActive(&view));
3752 QVERIFY(view.isActiveWindow());
3755 QCOMPARE(view.indexAt(p), model.index(0, 0));
3756 QSignalSpy spy(&view, SIGNAL(doubleClicked(QModelIndex)));
3757 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, p);
3758 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, p);
3759 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, p);
3760 QCOMPARE(spy.count(), 1);
3762 //let's click on the 2nd column
3763 p.setX(p.x() + view.header()->sectionSize(0));
3764 QCOMPARE(view.indexAt(p), model.index(0, 0));
3766 //end the previous edition
3767 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
3769 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, p);
3770 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, p);
3771 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, p);
3772 QTRY_COMPARE(spy.count(), 2);
3775 void tst_QTreeView::taskQTBUG_6450_selectAllWith1stColumnHidden()
3778 tree.setSelectionMode(QAbstractItemView::MultiSelection);
3779 tree.setColumnCount(2);
3780 QList<QTreeWidgetItem *> items;
3781 const int nrRows = 10;
3782 for (int i = 0; i < nrRows; ++i) {
3783 items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item: %1").arg(i))));
3784 items.last()->setText(1, QString("is an item"));
3786 tree.insertTopLevelItems(0, items);
3791 QVERIFY(tree.selectionModel()->hasSelection());
3792 for (int i = 0; i < nrRows; ++i)
3793 QVERIFY(tree.selectionModel()->isRowSelected(i, QModelIndex()));
3796 class TreeViewQTBUG_9216 : public QTreeView
3800 void paintEvent(QPaintEvent *event)
3803 QCOMPARE(event->rect(), viewport()->rect());
3804 QTreeView::paintEvent(event);
3811 void tst_QTreeView::taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint()
3813 QStandardItemModel model(10, 10, this);
3814 for (int row = 0; row < 10; row++)
3815 for (int col = 0; col < 10; col++)
3816 model.setItem(row, col, new QStandardItem(QString("row %0, col %1").arg(row).arg(col)));
3817 TreeViewQTBUG_9216 view;
3818 view.setUniformRowHeights(true);
3819 view.setModel(&model);
3821 view.doCompare = false;
3823 QVERIFY(QTest::qWaitForWindowExposed(&view));
3824 QTRY_VERIFY(view.painted > 0);
3826 QTest::qWait(100); // This one is needed to make the test fail before the patch.
3828 view.doCompare = true;
3829 model.setData(model.index(0, 0), QVariant(QSize(50, 50)), Qt::SizeHintRole);
3831 QTRY_VERIFY(view.painted > 0);
3834 void tst_QTreeView::keyboardNavigationWithDisabled()
3837 QTreeView view(&topLevel);
3838 QStandardItemModel model(90, 0);
3839 for (int i = 0; i < 90; i ++) {
3840 model.setItem(i, new QStandardItem(QString::number(i)));
3841 model.item(i)->setEnabled(i%6 == 0);
3843 view.setModel(&model);
3845 view.resize(200, view.visualRect(model.index(0,0)).height()*10);
3847 QApplication::setActiveWindow(&topLevel);
3848 QVERIFY(QTest::qWaitForWindowActive(&topLevel));
3849 QVERIFY(topLevel.isActiveWindow());
3851 view.setCurrentIndex(model.index(1, 0));
3852 QTest::keyClick(view.viewport(), Qt::Key_Up);
3853 QCOMPARE(view.currentIndex(), model.index(0, 0));
3854 QTest::keyClick(view.viewport(), Qt::Key_Down);
3855 QCOMPARE(view.currentIndex(), model.index(6, 0));
3856 QTest::keyClick(view.viewport(), Qt::Key_PageDown);
3857 QCOMPARE(view.currentIndex(), model.index(18, 0));
3858 QTest::keyClick(view.viewport(), Qt::Key_Down);
3859 QCOMPARE(view.currentIndex(), model.index(24, 0));
3860 QTest::keyClick(view.viewport(), Qt::Key_PageUp);
3861 QCOMPARE(view.currentIndex(), model.index(12, 0));
3862 QTest::keyClick(view.viewport(), Qt::Key_Up);
3863 QCOMPARE(view.currentIndex(), model.index(6, 0));
3866 class Model_11466 : public QAbstractItemModel
3870 Model_11466(QObject * /* parent */) :
3873 // set up the model to have two top level items and a few others
3874 m_selectionModel = new QItemSelectionModel(this, this); // owned by this
3876 connect(m_selectionModel, SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)),
3877 this, SLOT(slotCurrentChanged(const QModelIndex &,const QModelIndex &)));
3880 int rowCount(const QModelIndex &parent) const
3882 if (parent.isValid())
3883 return (parent.internalId() == 0) ? 4 : 0;
3884 return 2; // two top level items
3887 int columnCount(const QModelIndex & /* parent */) const
3892 QVariant data(const QModelIndex &index, int role) const
3894 if (role == Qt::DisplayRole && index.isValid()) {
3895 qint64 parentRowPlusOne = index.internalId();
3897 QTextStream stream(&str);
3898 if (parentRowPlusOne > 0)
3899 stream << parentRowPlusOne << " -> " << index.row() << " : " << index.column();
3901 stream << index.row() << " : " << index.column();
3902 return QVariant(str);
3907 QModelIndex parent(const QModelIndex &index) const
3909 if (index.isValid()) {
3910 qint64 parentRowPlusOne = index.internalId();
3911 if (parentRowPlusOne > 0) {
3912 int row = static_cast<int>(parentRowPlusOne - 1);
3913 return createIndex(row, 0, (quint32)0);
3916 return QModelIndex();
3919 void bindView(QTreeView *view)
3921 // sets the view to this model with a shared selection model
3922 QItemSelectionModel *oldModel = view->selectionModel();
3923 if (oldModel != m_selectionModel)
3925 view->setModel(this); // this creates a new selection model for the view, but we don't want it either ...
3926 oldModel = view->selectionModel();
3927 view->setSelectionModel(m_selectionModel);
3931 QModelIndex index(int row, int column, const QModelIndex &parent) const
3933 return createIndex(row, column, parent.isValid() ? (quint32)(parent.row() + 1) : (quint32)0);
3937 void slotCurrentChanged(const QModelIndex ¤t,const QModelIndex &)
3942 if (current.isValid()) {
3943 int selectedRow = current.row();
3944 quint32 parentRowPlusOne = static_cast<quint32>(current.internalId());
3946 for (int i = 0; i < 2; ++i) {
3947 // announce the removal of all non top level items
3948 beginRemoveRows(createIndex(i, 0, 0), 0, 3);
3949 // nothing to actually do for the removal
3952 // put them back in again
3953 beginInsertRows(createIndex(i, 0, 0), 0, 3);
3954 // nothing to actually do for the insertion
3957 // reselect the current item ...
3958 QModelIndex selectedIndex = createIndex(selectedRow, 0, parentRowPlusOne);
3960 m_block = true; // recursion block
3961 m_selectionModel->select(selectedIndex, QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Current|QItemSelectionModel::Rows);
3962 m_selectionModel->setCurrentIndex(selectedIndex, QItemSelectionModel::NoUpdate);
3965 m_selectionModel->clear();
3971 QItemSelectionModel *m_selectionModel;
3974 void tst_QTreeView::taskQTBUG_11466_keyboardNavigationRegression()
3977 treeView.setSelectionBehavior(QAbstractItemView::SelectRows);
3978 treeView.setSelectionMode(QAbstractItemView::SingleSelection);
3979 Model_11466 model(&treeView);
3980 model.bindView(&treeView);
3981 treeView.expandAll();
3983 QVERIFY(QTest::qWaitForWindowExposed(&treeView));
3985 QTest::keyPress(treeView.viewport(), Qt::Key_Down);
3987 QTRY_COMPARE(treeView.currentIndex(), treeView.selectionModel()->selection().indexes().first());
3990 void tst_QTreeView::taskQTBUG_13567_removeLastItemRegression()
3992 QtTestModel model(200, 1);
3995 view.setSelectionMode(QAbstractItemView::ExtendedSelection);
3996 view.setModel(&model);
3998 QVERIFY(QTest::qWaitForWindowExposed(&view));
4000 view.scrollToBottom();
4002 CHECK_VISIBLE(199, 0);
4004 view.setCurrentIndex(model.index(199, 0));
4005 model.removeLastRow();
4007 QCOMPARE(view.currentIndex(), model.index(198, 0));
4008 CHECK_VISIBLE(198, 0);
4011 // From QTBUG-25333 (QTreeWidget drag crashes when there was a hidden item in tree)
4012 // The test passes simply if it doesn't crash, hence there are no calls
4013 // to QCOMPARE() or QVERIFY().
4014 // Note: define QT_BUILD_INTERNAL to run this test
4015 void tst_QTreeView::taskQTBUG_25333_adjustViewOptionsForIndex()
4018 QStandardItemModel model;
4019 QStandardItem *item1 = new QStandardItem("Item1");
4020 QStandardItem *item2 = new QStandardItem("Item2");
4021 QStandardItem *item3 = new QStandardItem("Item3");
4022 QStandardItem *data1 = new QStandardItem("Data1");
4023 QStandardItem *data2 = new QStandardItem("Data2");
4024 QStandardItem *data3 = new QStandardItem("Data3");
4026 // Create a treeview
4027 model.appendRow(QList<QStandardItem*>() << item1 << data1 );
4028 model.appendRow(QList<QStandardItem*>() << item2 << data2 );
4029 model.appendRow(QList<QStandardItem*>() << item3 << data3 );
4031 view.setModel(&model);
4034 view.setRowHidden(1, QModelIndex(), true);
4039 #ifdef QT_BUILD_INTERNAL
4041 QStyleOptionViewItemV4 option;
4043 view.aiv_priv()->adjustViewOptionsForIndex(&option, model.indexFromItem(item1));
4045 view.aiv_priv()->adjustViewOptionsForIndex(&option, model.indexFromItem(item3));
4052 QTEST_MAIN(tst_QTreeView)
4053 #include "tst_qtreeview.moc"