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 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <qabstractitemview.h>
46 #include <qstandarditemmodel.h>
47 #include <qapplication.h>
48 #include <qlistview.h>
49 #include <qlistwidget.h>
50 #include <qtableview.h>
51 #include <qtablewidget.h>
52 #include <qtreeview.h>
53 #include <qtreewidget.h>
54 #include <qheaderview.h>
56 #include <qitemdelegate.h>
57 #include <qpushbutton.h>
58 #include <qscrollbar.h>
59 #include <qboxlayout.h>
60 #include <qlineedit.h>
62 // Will try to wait for the condition while allowing event processing
63 // for a maximum of 5 seconds.
64 #define TRY_COMPARE(expr, expected) \
66 const int step = 50; \
67 for (int q = 0; q < 5000 && ((expr) != (expected)); q+=step) { \
70 QCOMPARE(expr, expected); \
73 class TestView : public QAbstractItemView
77 inline void tst_dataChanged(const QModelIndex &tl, const QModelIndex &br)
78 { dataChanged(tl, br); }
79 inline void tst_setHorizontalStepsPerItem(int steps)
80 { setHorizontalStepsPerItem(steps); }
81 inline int tst_horizontalStepsPerItem() const
82 { return horizontalStepsPerItem(); }
83 inline void tst_setVerticalStepsPerItem(int steps)
84 { setVerticalStepsPerItem(steps); }
85 inline int tst_verticalStepsPerItem() const
86 { return verticalStepsPerItem(); }
88 inline void tst_rowsInserted(const QModelIndex &parent, int start, int end)
89 { rowsInserted(parent, start, end); }
90 inline void tst_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
91 { rowsAboutToBeRemoved(parent, start, end); }
92 inline void tst_selectionChanged(const QItemSelection &selected,
93 const QItemSelection &deselected)
94 { selectionChanged(selected, deselected); }
95 inline void tst_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
96 { currentChanged(current, previous); }
97 inline void tst_updateEditorData()
98 { updateEditorData(); }
99 inline void tst_updateEditorGeometries()
100 { updateEditorGeometries(); }
101 inline void tst_updateGeometries()
102 { updateGeometries(); }
103 inline void tst_verticalScrollbarAction(int action)
104 { verticalScrollbarAction(action); }
105 inline void tst_horizontalScrollbarAction(int action)
106 { horizontalScrollbarAction(action); }
107 inline void tst_verticalScrollbarValueChanged(int value)
108 { verticalScrollbarValueChanged(value); }
109 inline void tst_horizontalScrollbarValueChanged(int value)
110 { horizontalScrollbarValueChanged(value); }
111 inline void tst_closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
112 { closeEditor(editor, hint); }
113 inline void tst_commitData(QWidget *editor)
114 { commitData(editor); }
115 inline void tst_editorDestroyed(QObject *editor)
116 { editorDestroyed(editor); }
117 enum tst_CursorAction {
118 MoveUp = QAbstractItemView::MoveUp,
119 MoveDown = QAbstractItemView::MoveDown,
120 MoveLeft = QAbstractItemView::MoveLeft,
121 MoveRight = QAbstractItemView::MoveRight,
122 MoveHome = QAbstractItemView::MoveHome,
123 MoveEnd = QAbstractItemView::MoveEnd,
124 MovePageUp = QAbstractItemView::MovePageUp,
125 MovePageDown = QAbstractItemView::MovePageDown,
126 MoveNext = QAbstractItemView::MoveNext,
127 MovePrevious = QAbstractItemView::MovePrevious
129 inline QModelIndex tst_moveCursor(tst_CursorAction cursorAction,
130 Qt::KeyboardModifiers modifiers)
131 { return moveCursor(QAbstractItemView::CursorAction(cursorAction), modifiers); }
132 inline int tst_horizontalOffset() const
133 { return horizontalOffset(); }
134 inline int tst_verticalOffset() const
135 { return verticalOffset(); }
136 inline bool tst_isIndexHidden(const QModelIndex &index) const
137 { return isIndexHidden(index); }
138 inline void tst_setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
139 { setSelection(rect, command); }
140 inline QRegion tst_visualRegionForSelection(const QItemSelection &selection) const
141 { return visualRegionForSelection(selection); }
142 inline QModelIndexList tst_selectedIndexes() const
143 { return selectedIndexes(); }
144 inline bool tst_edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
145 { return edit(index, trigger, event); }
146 inline QItemSelectionModel::SelectionFlags tst_selectionCommand(const QModelIndex &index,
147 const QEvent *event = 0) const
148 { return selectionCommand(index, event); }
149 #ifndef QT_NO_DRAGANDDROP
150 inline void tst_startDrag(Qt::DropActions supportedActions)
151 { startDrag(supportedActions); }
153 inline QStyleOptionViewItem tst_viewOptions() const
154 { return viewOptions(); }
156 NoState = QAbstractItemView::NoState,
157 DraggingState = QAbstractItemView::DraggingState,
158 DragSelectingState = QAbstractItemView::DragSelectingState,
159 EditingState = QAbstractItemView::EditingState,
160 ExpandingState = QAbstractItemView::ExpandingState,
161 CollapsingState = QAbstractItemView::CollapsingState
163 inline tst_State tst_state() const
164 { return (tst_State)state(); }
165 inline void tst_setState(tst_State state)
166 { setState(QAbstractItemView::State(state)); }
167 inline void tst_startAutoScroll()
168 { startAutoScroll(); }
169 inline void tst_stopAutoScroll()
170 { stopAutoScroll(); }
171 inline void tst_doAutoScroll()
175 class tst_QAbstractItemView : public QObject
181 tst_QAbstractItemView();
182 virtual ~tst_QAbstractItemView();
183 void basic_tests(TestView *view);
187 void cleanupTestCase();
191 void emptyModels_data();
193 void setModel_data();
198 void columnDelegate();
201 void persistentEditorFocus();
202 void setItemDelegate();
203 void setItemDelegate_data();
204 // The dragAndDrop() test doesn't work, and is thus disabled on Mac and Windows
205 // for the following reasons:
206 // Mac: use of GetCurrentEventButtonState() in QDragManager::drag()
207 // Win: unknown reason
208 #if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
211 void dragAndDropOnChild();
214 void noFallbackToRoot();
215 void setCurrentIndex_data();
216 void setCurrentIndex();
218 void task221955_selectedEditor();
219 void task250754_fontChange();
220 void task200665_itemEntered();
221 void task257481_emptyEditor();
222 void shiftArrowSelectionAfterScrolling();
223 void shiftSelectionAfterRubberbandSelection();
224 void ctrlRubberbandSelection();
225 void QTBUG6407_extendedSelection();
226 void QTBUG6753_selectOnSelection();
227 void testDelegateDestroyEditor();
230 class MyAbstractItemDelegate : public QAbstractItemDelegate
233 MyAbstractItemDelegate() : QAbstractItemDelegate() { calledVirtualDtor = false; }
234 void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
235 QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
236 QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
238 openedEditor = new QWidget(parent);
241 void destroyEditor(QWidget *editor, const QModelIndex &) const
243 calledVirtualDtor = true;
244 editor->deleteLater();
247 mutable bool calledVirtualDtor;
248 mutable QWidget *openedEditor;
251 // Testing get/set functions
252 void tst_QAbstractItemView::getSetCheck()
255 TestView *obj1 = reinterpret_cast<TestView*>(&view);
256 // QAbstractItemDelegate * QAbstractItemView::itemDelegate()
257 // void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *)
258 MyAbstractItemDelegate *var1 = new MyAbstractItemDelegate;
259 obj1->setItemDelegate(var1);
260 QCOMPARE((QAbstractItemDelegate*)var1, obj1->itemDelegate());
261 obj1->setItemDelegate((QAbstractItemDelegate *)0);
262 QCOMPARE((QAbstractItemDelegate *)0, obj1->itemDelegate());
265 // EditTriggers QAbstractItemView::editTriggers()
266 // void QAbstractItemView::setEditTriggers(EditTriggers)
267 obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers));
268 QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers), obj1->editTriggers());
269 obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged));
270 QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged), obj1->editTriggers());
271 obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked));
272 QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked), obj1->editTriggers());
273 obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked));
274 QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked), obj1->editTriggers());
275 obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed));
276 QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed), obj1->editTriggers());
277 obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed));
278 QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed), obj1->editTriggers());
279 obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers));
280 QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers), obj1->editTriggers());
282 // bool QAbstractItemView::tabKeyNavigation()
283 // void QAbstractItemView::setTabKeyNavigation(bool)
284 obj1->setTabKeyNavigation(false);
285 QCOMPARE(false, obj1->tabKeyNavigation());
286 obj1->setTabKeyNavigation(true);
287 QCOMPARE(true, obj1->tabKeyNavigation());
289 // bool QAbstractItemView::dragEnabled()
290 // void QAbstractItemView::setDragEnabled(bool)
291 #ifndef QT_NO_DRAGANDDROP
292 obj1->setDragEnabled(false);
293 QCOMPARE(false, obj1->dragEnabled());
294 obj1->setDragEnabled(true);
295 QCOMPARE(true, obj1->dragEnabled());
297 // bool QAbstractItemView::alternatingRowColors()
298 // void QAbstractItemView::setAlternatingRowColors(bool)
299 obj1->setAlternatingRowColors(false);
300 QCOMPARE(false, obj1->alternatingRowColors());
301 obj1->setAlternatingRowColors(true);
302 QCOMPARE(true, obj1->alternatingRowColors());
304 // State QAbstractItemView::state()
305 // void QAbstractItemView::setState(State)
306 obj1->tst_setState(TestView::tst_State(TestView::NoState));
307 QCOMPARE(TestView::tst_State(TestView::NoState), obj1->tst_state());
308 obj1->tst_setState(TestView::tst_State(TestView::DraggingState));
309 QCOMPARE(TestView::tst_State(TestView::DraggingState), obj1->tst_state());
310 obj1->tst_setState(TestView::tst_State(TestView::DragSelectingState));
311 QCOMPARE(TestView::tst_State(TestView::DragSelectingState), obj1->tst_state());
312 obj1->tst_setState(TestView::tst_State(TestView::EditingState));
313 QCOMPARE(TestView::tst_State(TestView::EditingState), obj1->tst_state());
314 obj1->tst_setState(TestView::tst_State(TestView::ExpandingState));
315 QCOMPARE(TestView::tst_State(TestView::ExpandingState), obj1->tst_state());
316 obj1->tst_setState(TestView::tst_State(TestView::CollapsingState));
317 QCOMPARE(TestView::tst_State(TestView::CollapsingState), obj1->tst_state());
319 // QWidget QAbstractScrollArea::viewport()
320 // void setViewport(QWidget*)
321 QWidget *vp = new QWidget;
322 obj1->setViewport(vp);
323 QCOMPARE(vp, obj1->viewport());
325 QCOMPARE(16, obj1->autoScrollMargin());
326 obj1->setAutoScrollMargin(20);
327 QCOMPARE(20, obj1->autoScrollMargin());
328 obj1->setAutoScrollMargin(16);
329 QCOMPARE(16, obj1->autoScrollMargin());
332 tst_QAbstractItemView::tst_QAbstractItemView()
336 tst_QAbstractItemView::~tst_QAbstractItemView()
340 void tst_QAbstractItemView::initTestCase()
343 qApp->setAutoMaximizeThreshold(-1);
347 void tst_QAbstractItemView::cleanupTestCase()
351 void tst_QAbstractItemView::emptyModels_data()
353 QTest::addColumn<QString>("viewType");
355 QTest::newRow("QListView") << "QListView";
356 QTest::newRow("QTableView") << "QTableView";
357 QTest::newRow("QTreeView") << "QTreeView";
358 QTest::newRow("QHeaderView") << "QHeaderView";
361 void tst_QAbstractItemView::emptyModels()
363 QFETCH(QString, viewType);
366 if (viewType == "QListView")
367 view = reinterpret_cast<TestView*>(new QListView());
368 else if (viewType == "QTableView")
369 view = reinterpret_cast<TestView*>(new QTableView());
370 else if (viewType == "QTreeView")
371 view = reinterpret_cast<TestView*>(new QTreeView());
372 else if (viewType == "QHeaderView")
373 view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
378 QVERIFY(!view->model());
379 QVERIFY(!view->selectionModel());
380 //QVERIFY(view->itemDelegate() != 0);
386 void tst_QAbstractItemView::setModel_data()
388 QTest::addColumn<QString>("viewType");
390 QTest::newRow("QListView") << "QListView";
391 QTest::newRow("QTableView") << "QTableView";
392 QTest::newRow("QTreeView") << "QTreeView";
393 QTest::newRow("QHeaderView") << "QHeaderView";
396 void tst_QAbstractItemView::setModel()
398 QFETCH(QString, viewType);
400 if (viewType == "QListView")
401 view = reinterpret_cast<TestView*>(new QListView());
402 else if (viewType == "QTableView")
403 view = reinterpret_cast<TestView*>(new QTableView());
404 else if (viewType == "QTreeView")
405 view = reinterpret_cast<TestView*>(new QTreeView());
406 else if (viewType == "QHeaderView")
407 view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
412 QStandardItemModel model(20,20);
414 view->setModel(&model);
419 void tst_QAbstractItemView::basic_tests(TestView *view)
422 // Will assert as it should
423 //view->setSelectionModel(0);
425 //view->setItemDelegate(0);
426 // Will asswert as it should
429 view->setSelectionMode(QAbstractItemView::SingleSelection);
430 QCOMPARE(view->selectionMode(), QAbstractItemView::SingleSelection);
431 view->setSelectionMode(QAbstractItemView::ContiguousSelection);
432 QCOMPARE(view->selectionMode(), QAbstractItemView::ContiguousSelection);
433 view->setSelectionMode(QAbstractItemView::ExtendedSelection);
434 QCOMPARE(view->selectionMode(), QAbstractItemView::ExtendedSelection);
435 view->setSelectionMode(QAbstractItemView::MultiSelection);
436 QCOMPARE(view->selectionMode(), QAbstractItemView::MultiSelection);
437 view->setSelectionMode(QAbstractItemView::NoSelection);
438 QCOMPARE(view->selectionMode(), QAbstractItemView::NoSelection);
440 // setSelectionBehavior
441 view->setSelectionBehavior(QAbstractItemView::SelectItems);
442 QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectItems);
443 view->setSelectionBehavior(QAbstractItemView::SelectRows);
444 QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectRows);
445 view->setSelectionBehavior(QAbstractItemView::SelectColumns);
446 QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectColumns);
449 view->setEditTriggers(QAbstractItemView::EditKeyPressed);
450 QCOMPARE(view->editTriggers(), QAbstractItemView::EditKeyPressed);
451 view->setEditTriggers(QAbstractItemView::NoEditTriggers);
452 QCOMPARE(view->editTriggers(), QAbstractItemView::NoEditTriggers);
453 view->setEditTriggers(QAbstractItemView::CurrentChanged);
454 QCOMPARE(view->editTriggers(), QAbstractItemView::CurrentChanged);
455 view->setEditTriggers(QAbstractItemView::DoubleClicked);
456 QCOMPARE(view->editTriggers(), QAbstractItemView::DoubleClicked);
457 view->setEditTriggers(QAbstractItemView::SelectedClicked);
458 QCOMPARE(view->editTriggers(), QAbstractItemView::SelectedClicked);
459 view->setEditTriggers(QAbstractItemView::AnyKeyPressed);
460 QCOMPARE(view->editTriggers(), QAbstractItemView::AnyKeyPressed);
461 view->setEditTriggers(QAbstractItemView::AllEditTriggers);
462 QCOMPARE(view->editTriggers(), QAbstractItemView::AllEditTriggers);
465 view->setAutoScroll(false);
466 QCOMPARE(view->hasAutoScroll(), false);
467 view->setAutoScroll(true);
468 QCOMPARE(view->hasAutoScroll(), true);
470 // setTabKeyNavigation
471 view->setTabKeyNavigation(false);
472 QCOMPARE(view->tabKeyNavigation(), false);
473 view->setTabKeyNavigation(true);
474 QCOMPARE(view->tabKeyNavigation(), true);
476 #ifndef QT_NO_DRAGANDDROP
477 // setDropIndicatorShown
478 view->setDropIndicatorShown(false);
479 QCOMPARE(view->showDropIndicator(), false);
480 view->setDropIndicatorShown(true);
481 QCOMPARE(view->showDropIndicator(), true);
484 view->setDragEnabled(false);
485 QCOMPARE(view->dragEnabled(), false);
486 view->setDragEnabled(true);
487 QCOMPARE(view->dragEnabled(), true);
490 // setAlternatingRowColors
491 view->setAlternatingRowColors(false);
492 QCOMPARE(view->alternatingRowColors(), false);
493 view->setAlternatingRowColors(true);
494 QCOMPARE(view->alternatingRowColors(), true);
497 view->setIconSize(QSize(16, 16));
498 QCOMPARE(view->iconSize(), QSize(16, 16));
499 view->setIconSize(QSize(32, 32));
500 QCOMPARE(view->iconSize(), QSize(32, 32));
501 // Should this happen?
502 view->setIconSize(QSize(-1, -1));
503 QCOMPARE(view->iconSize(), QSize(-1, -1));
505 QCOMPARE(view->currentIndex(), QModelIndex());
506 QCOMPARE(view->rootIndex(), QModelIndex());
508 view->keyboardSearch("");
509 view->keyboardSearch("foo");
510 view->keyboardSearch("1");
512 QCOMPARE(view->visualRect(QModelIndex()), QRect());
514 view->scrollTo(QModelIndex());
516 QCOMPARE(view->sizeHintForIndex(QModelIndex()), QSize());
517 QCOMPARE(view->indexAt(QPoint(-1, -1)), QModelIndex());
520 QCOMPARE(view->indexAt(QPoint(10, 10)), QModelIndex());
521 QCOMPARE(view->sizeHintForRow(0), -1);
522 QCOMPARE(view->sizeHintForColumn(0), -1);
523 }else if (view->itemDelegate()){
524 view->sizeHintForRow(0);
525 view->sizeHintForColumn(0);
527 view->openPersistentEditor(QModelIndex());
528 view->closePersistentEditor(QModelIndex());
531 view->setRootIndex(QModelIndex());
532 view->doItemsLayout();
534 view->edit(QModelIndex());
535 view->clearSelection();
536 view->setCurrentIndex(QModelIndex());
539 view->tst_dataChanged(QModelIndex(), QModelIndex());
540 view->tst_rowsInserted(QModelIndex(), -1, -1);
541 view->tst_rowsAboutToBeRemoved(QModelIndex(), -1, -1);
542 view->tst_selectionChanged(QItemSelection(), QItemSelection());
544 view->tst_currentChanged(QModelIndex(), QModelIndex());
545 view->tst_currentChanged(QModelIndex(), view->model()->index(0,0));
547 view->tst_updateEditorData();
548 view->tst_updateEditorGeometries();
549 view->tst_updateGeometries();
550 view->tst_verticalScrollbarAction(QAbstractSlider::SliderSingleStepAdd);
551 view->tst_horizontalScrollbarAction(QAbstractSlider::SliderSingleStepAdd);
552 view->tst_verticalScrollbarValueChanged(10);
553 view->tst_horizontalScrollbarValueChanged(10);
554 view->tst_closeEditor(0, QAbstractItemDelegate::NoHint);
555 view->tst_commitData(0);
556 view->tst_editorDestroyed(0);
558 view->tst_setHorizontalStepsPerItem(2);
559 view->tst_horizontalStepsPerItem();
560 view->tst_setVerticalStepsPerItem(2);
561 view->tst_verticalStepsPerItem();
563 // Will assert as it should
564 // view->setIndexWidget(QModelIndex(), 0);
566 view->tst_moveCursor(TestView::MoveUp, Qt::NoModifier);
567 view->tst_horizontalOffset();
568 view->tst_verticalOffset();
570 // view->tst_isIndexHidden(QModelIndex()); // will (correctly) assert
572 view->tst_isIndexHidden(view->model()->index(0,0));
574 view->tst_setSelection(QRect(0, 0, 10, 10), QItemSelectionModel::ClearAndSelect);
575 view->tst_setSelection(QRect(-1, -1, -1, -1), QItemSelectionModel::ClearAndSelect);
576 view->tst_visualRegionForSelection(QItemSelection());
577 view->tst_selectedIndexes();
579 view->tst_edit(QModelIndex(), QAbstractItemView::NoEditTriggers, 0);
581 view->tst_selectionCommand(QModelIndex(), 0);
583 #ifndef QT_NO_DRAGANDDROP
585 view->tst_startDrag(Qt::CopyAction);
587 view->tst_viewOptions();
589 view->tst_setState(TestView::NoState);
590 QVERIFY(view->tst_state()==TestView::NoState);
591 view->tst_setState(TestView::DraggingState);
592 QVERIFY(view->tst_state()==TestView::DraggingState);
593 view->tst_setState(TestView::DragSelectingState);
594 QVERIFY(view->tst_state()==TestView::DragSelectingState);
595 view->tst_setState(TestView::EditingState);
596 QVERIFY(view->tst_state()==TestView::EditingState);
597 view->tst_setState(TestView::ExpandingState);
598 QVERIFY(view->tst_state()==TestView::ExpandingState);
599 view->tst_setState(TestView::CollapsingState);
600 QVERIFY(view->tst_state()==TestView::CollapsingState);
603 view->tst_startAutoScroll();
604 view->tst_stopAutoScroll();
605 view->tst_doAutoScroll();
607 // testing mouseFoo and key functions
608 // QTest::mousePress(view, Qt::LeftButton, Qt::NoModifier, QPoint(0,0));
609 // mouseMove(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
610 // QTest::mouseRelease(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
611 // QTest::mouseClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
612 // mouseDClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
613 // QTest::keyClick(view, Qt::Key_A);
616 void tst_QAbstractItemView::noModel()
620 QStandardItemModel model(20,20);
623 view.setModel(&model);
624 // Make the viewport smaller than the contents, so that we can scroll
625 view.resize(100,100);
628 // make sure that the scrollbars are not at value 0
629 view.scrollTo(view.model()->index(10,10));
630 QApplication::processEvents();
633 // Due to the model is removed, this will generate a valueChanged signal on both scrollbars. (value to 0)
634 QApplication::processEvents();
635 QCOMPARE(view.model(), (QAbstractItemModel*)0);
638 void tst_QAbstractItemView::dragSelect()
642 QStandardItemModel model(64,64);
645 view.setModel(&model);
646 view.setVisible(true);
649 for (int i = 0; i < 2; ++i) {
650 bool tracking = (i == 1);
651 view.setMouseTracking(false);
652 QTest::mouseMove(&view, QPoint(0, 0), delay);
653 view.setMouseTracking(tracking);
654 QTest::mouseMove(&view, QPoint(50, 50), delay);
655 QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
659 void tst_QAbstractItemView::rowDelegate()
661 QStandardItemModel model(4,4);
662 MyAbstractItemDelegate delegate;
665 view.setModel(&model);
666 view.setItemDelegateForRow(3, &delegate);
669 QModelIndex index = model.index(3, 0);
670 view.openPersistentEditor(index);
671 QWidget *w = view.indexWidget(index);
673 QCOMPARE(w->metaObject()->className(), "QWidget");
676 void tst_QAbstractItemView::columnDelegate()
678 QStandardItemModel model(4,4);
679 MyAbstractItemDelegate delegate;
682 view.setModel(&model);
683 view.setItemDelegateForColumn(3, &delegate);
686 QModelIndex index = model.index(0, 3);
687 view.openPersistentEditor(index);
688 QWidget *w = view.indexWidget(index);
690 QCOMPARE(w->metaObject()->className(), "QWidget");
693 void tst_QAbstractItemView::selectAll()
695 QStandardItemModel model(4,4);
697 view.setModel(&model);
699 TestView *tst_view = (TestView*)&view;
701 QCOMPARE(tst_view->tst_selectedIndexes().count(), 0);
703 QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4);
706 void tst_QAbstractItemView::ctrlA()
708 QStandardItemModel model(4,4);
710 view.setModel(&model);
712 TestView *tst_view = (TestView*)&view;
714 QCOMPARE(tst_view->tst_selectedIndexes().count(), 0);
715 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
716 QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4);
719 void tst_QAbstractItemView::persistentEditorFocus()
721 // one row, three columns
722 QStandardItemModel model(1, 3);
723 for(int i = 0; i < model.columnCount(); ++i)
724 model.setData(model.index(0, i), i);
726 view.setModel(&model);
728 view.openPersistentEditor(model.index(0, 1));
729 view.openPersistentEditor(model.index(0, 2));
731 //these are spinboxes because we put numbers inside
732 QList<QSpinBox*> list = qFindChildren<QSpinBox*>(view.viewport());
733 QCOMPARE(list.count(), 2); //these should be the 2 editors
735 view.setCurrentIndex(model.index(0, 0));
736 QCOMPARE(view.currentIndex(), model.index(0, 0));
738 QTRY_VERIFY(view.isVisible());
740 for (int i = 0; i < list.count(); ++i) {
741 TRY_COMPARE(list.at(i)->isVisible(), true);
742 QPoint p = QPoint(5, 5);
743 QMouseEvent mouseEvent(QEvent::MouseButtonPress, p, Qt::LeftButton,
744 Qt::LeftButton, Qt::NoModifier);
745 qApp->sendEvent(list.at(i), &mouseEvent);
746 if (!qApp->focusWidget())
747 QSKIP("Some window managers don't handle focus that well");
748 QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget *>(list.at(i)));
753 #if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
757 static void sendMouseMove(QWidget *widget, QPoint pos = QPoint())
760 pos = widget->rect().center();
761 QMouseEvent event(QEvent::MouseMove, pos, widget->mapToGlobal(pos), Qt::NoButton, 0, 0);
762 QCursor::setPos(widget->mapToGlobal(pos));
763 qApp->processEvents();
764 QVERIFY(QTest::qWaitForWindowExposed(widget));
765 QApplication::sendEvent(widget, &event);
768 static void sendMousePress(
769 QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton)
772 pos = widget->rect().center();
773 QMouseEvent event(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, 0, 0);
774 QApplication::sendEvent(widget, &event);
777 static void sendMouseRelease(
778 QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton)
781 pos = widget->rect().center();
782 QMouseEvent event(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, 0, 0);
783 QApplication::sendEvent(widget, &event);
786 class DnDTestModel : public QStandardItemModel
789 bool dropMimeData(const QMimeData *md, Qt::DropAction action, int r, int c, const QModelIndex &p)
791 dropAction_result = action;
792 QStandardItemModel::dropMimeData(md, action, r, c, p);
795 Qt::DropActions supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; }
797 Qt::DropAction dropAction_result;
799 DnDTestModel() : QStandardItemModel(20, 20), dropAction_result(Qt::IgnoreAction) {
800 for (int i = 0; i < rowCount(); ++i)
801 setData(index(i, 0), QString("%1").arg(i));
803 Qt::DropAction dropAction() const { return dropAction_result; }
806 class DnDTestView : public QTreeView
811 Qt::DropAction dropAction;
813 void dragEnterEvent(QDragEnterEvent *event)
815 QAbstractItemView::dragEnterEvent(event);
818 void dropEvent(QDropEvent *event)
820 event->setDropAction(dropAction);
821 QTreeView::dropEvent(event);
824 void timerEvent(QTimerEvent *event)
826 killTimer(event->timerId());
827 sendMouseMove(this, dropPoint);
828 sendMouseRelease(this);
831 void mousePressEvent(QMouseEvent *e)
833 QTreeView::mousePressEvent(e);
836 setState(DraggingState);
837 startDrag(dropAction);
841 DnDTestView(Qt::DropAction dropAction, QAbstractItemModel *model)
842 : dropAction(dropAction)
846 setDragDropMode(QAbstractItemView::DragDrop);
847 setAcceptDrops(true);
848 setDragEnabled(true);
851 void dragAndDrop(QPoint drag, QPoint drop)
854 setCurrentIndex(indexAt(drag));
855 sendMousePress(viewport(), drag);
859 class DnDTestWidget : public QWidget
863 Qt::DropAction dropAction_request;
864 Qt::DropAction dropAction_result;
867 void timerEvent(QTimerEvent *event)
869 killTimer(event->timerId());
870 sendMouseMove(dropTarget);
871 sendMouseRelease(dropTarget);
874 void mousePressEvent(QMouseEvent *)
876 QDrag *drag = new QDrag(this);
877 QMimeData *mimeData = new QMimeData;
878 mimeData->setData("application/x-qabstractitemmodeldatalist", QByteArray(""));
879 drag->setMimeData(mimeData);
881 dropAction_result = drag->start(dropAction_request);
885 Qt::DropAction dropAction() const { return dropAction_result; }
887 void dragAndDrop(QWidget *dropTarget, Qt::DropAction dropAction)
889 this->dropTarget = dropTarget;
890 dropAction_request = dropAction;
891 sendMousePress(this);
895 void tst_QAbstractItemView::dragAndDrop()
900 QSKIP("Embedded drag-and-drop not good enough yet...");
903 const int attempts = 10;
905 for (int i = 0; i < attempts; ++i) {
906 Qt::DropAction dropAction = Qt::MoveAction;
909 DnDTestView view(dropAction, &model);
910 DnDTestWidget widget;
912 const int size = 200;
913 widget.setFixedSize(size, size);
914 view.setFixedSize(size, size);
917 view.move(int(size * 1.5), int(size * 1.5));
921 QVERIFY(QTest::qWaitForWindowExposed(&widget));
922 QVERIFY(QTest::qWaitForWindowExposed(&view));
924 widget.dragAndDrop(&view, dropAction);
925 if (model.dropAction() == dropAction
926 && widget.dropAction() == dropAction)
930 if (successes < attempts) {
931 QString msg = QString("# successes (%1) < # attempts (%2)").arg(successes).arg(attempts);
932 QWARN(msg.toLatin1());
934 QVERIFY(successes > 0); // allow for some "event unstability" (i.e. unless
935 // successes == 0, QAbstractItemView is probably ok!)
938 void tst_QAbstractItemView::dragAndDropOnChild()
941 QSKIP("Embedded drag-and-drop not good enough yet...");
944 const int attempts = 10;
946 for (int i = 0; i < attempts; ++i) {
947 Qt::DropAction dropAction = Qt::MoveAction;
950 QModelIndex parent = model.index(0, 0);
951 model.insertRow(0, parent);
952 model.insertColumn(0, parent);
953 QModelIndex child = model.index(0, 0, parent);
954 model.setData(child, "child");
955 QCOMPARE(model.rowCount(parent), 1);
956 DnDTestView view(dropAction, &model);
957 view.setExpanded(parent, true);
958 view.setDragDropMode(QAbstractItemView::InternalMove);
960 const int size = 200;
961 view.setFixedSize(size, size);
962 view.move(int(size * 1.5), int(size * 1.5));
964 QVERIFY(QTest::qWaitForWindowExposed(&view));
966 view.dragAndDrop(view.visualRect(parent).center(),
967 view.visualRect(child).center());
968 if (model.dropAction() == dropAction)
972 QVERIFY(successes == 0);
976 #endif // !Q_OS_MAC && !Q_OS_WIN
978 class TestModel : public QStandardItemModel
981 TestModel(int rows, int columns) : QStandardItemModel(rows, columns)
986 virtual bool setData(const QModelIndex &/*index*/, const QVariant &/*value*/, int /*role = Qt::EditRole*/)
995 typedef QList<int> IntList;
996 Q_DECLARE_METATYPE(IntList)
998 void tst_QAbstractItemView::setItemDelegate_data()
1000 // default is rows, a -1 will switch to columns
1001 QTest::addColumn<IntList>("rowsOrColumnsWithDelegate");
1002 QTest::addColumn<QPoint>("cellToEdit");
1003 QTest::newRow("4 columndelegates")
1004 << (IntList() << -1 << 0 << 1 << 2 << 3)
1006 QTest::newRow("2 identical rowdelegates on the same row")
1007 << (IntList() << 0 << 0)
1009 QTest::newRow("2 identical columndelegates on the same column")
1010 << (IntList() << -1 << 2 << 2)
1012 QTest::newRow("2 duplicate delegates, 1 row and 1 column")
1013 << (IntList() << 0 << -1 << 2)
1015 QTest::newRow("4 duplicate delegates, 2 row and 2 column")
1016 << (IntList() << 0 << 0 << -1 << 2 << 2)
1021 void tst_QAbstractItemView::setItemDelegate()
1023 QFETCH(IntList, rowsOrColumnsWithDelegate);
1024 QFETCH(QPoint, cellToEdit);
1026 QItemDelegate *delegate = new QItemDelegate(&v);
1027 TestModel model(5, 5);
1031 foreach (int rc, rowsOrColumnsWithDelegate) {
1036 v.setItemDelegateForRow(rc, delegate);
1038 v.setItemDelegateForColumn(rc, delegate);
1044 QCursor::setPos(v.geometry().center());
1045 QApplication::syncX();
1047 QApplication::setActiveWindow(&v);
1048 QVERIFY(QTest::qWaitForWindowActive(&v));
1050 QModelIndex index = model.index(cellToEdit.y(), cellToEdit.x());
1053 // This will close the editor
1054 TRY_COMPARE(QApplication::focusWidget() == 0, false);
1055 QWidget *editor = QApplication::focusWidget();
1059 QCOMPARE(model.setData_count, 1);
1063 void tst_QAbstractItemView::noFallbackToRoot()
1065 QStandardItemModel model(0, 1);
1066 for (int i = 0; i < 5; ++i)
1067 model.appendRow(new QStandardItem("top" + QString::number(i)));
1068 QStandardItem *par1 = model.item(1);
1069 for (int j = 0; j < 15; ++j)
1070 par1->appendRow(new QStandardItem("sub" + QString::number(j)));
1071 QStandardItem *par2 = par1->child(2);
1072 for (int k = 0; k < 10; ++k)
1073 par2->appendRow(new QStandardItem("bot" + QString::number(k)));
1074 QStandardItem *it1 = par2->child(5);
1076 QModelIndex parent1 = model.indexFromItem(par1);
1077 QModelIndex parent2 = model.indexFromItem(par2);
1078 QModelIndex item1 = model.indexFromItem(it1);
1082 v.setRootIndex(parent1);
1083 v.setCurrentIndex(item1);
1084 QCOMPARE(v.currentIndex(), item1);
1085 QVERIFY(model.removeRows(0, 10, parent2));
1086 QCOMPARE(v.currentIndex(), parent2);
1087 QVERIFY(model.removeRows(0, 15, parent1));
1088 QCOMPARE(v.currentIndex(), QModelIndex());
1091 void tst_QAbstractItemView::setCurrentIndex_data()
1093 QTest::addColumn<QString>("viewType");
1094 QTest::addColumn<int>("itemFlags");
1095 QTest::addColumn<bool>("result");
1097 QStringList widgets;
1098 widgets << "QListView" << "QTreeView" << "QHeaderView" << "QTableView";
1100 foreach(QString widget, widgets) {
1101 QTest::newRow((widget+QLatin1String(": no flags")).toLocal8Bit().constData())
1102 << widget << (int)0 << false;
1103 QTest::newRow((widget+QLatin1String(": checkable")).toLocal8Bit().constData())
1104 << widget << (int)Qt::ItemIsUserCheckable << false;
1105 QTest::newRow((widget+QLatin1String(": selectable")).toLocal8Bit().constData())
1106 << widget << (int)Qt::ItemIsSelectable << false;
1107 QTest::newRow((widget+QLatin1String(": enabled")).toLocal8Bit().constData())
1108 << widget << (int)Qt::ItemIsEnabled << true;
1109 QTest::newRow((widget+QLatin1String(": enabled|selectable")).toLocal8Bit().constData())
1110 << widget << (int)(Qt::ItemIsSelectable|Qt::ItemIsEnabled) << true;
1114 void tst_QAbstractItemView::setCurrentIndex()
1116 QFETCH(QString, viewType);
1117 QFETCH(int, itemFlags);
1118 QFETCH(bool, result);
1121 if (viewType == "QListView")
1122 view = reinterpret_cast<TestView*>(new QListView());
1123 else if (viewType == "QTableView")
1124 view = reinterpret_cast<TestView*>(new QTableView());
1125 else if (viewType == "QTreeView")
1126 view = reinterpret_cast<TestView*>(new QTreeView());
1127 else if (viewType == "QHeaderView")
1128 view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
1133 QStandardItemModel *model = new QStandardItemModel(view);
1134 QStandardItem *item = new QStandardItem("first item");
1135 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
1136 model->appendRow(item);
1138 item = new QStandardItem("test item");
1139 item->setFlags(Qt::ItemFlags(itemFlags));
1140 model->appendRow(item);
1142 view->setModel(model);
1144 view->setCurrentIndex(model->index(0,0));
1145 QVERIFY(view->currentIndex() == model->index(0,0));
1146 view->setCurrentIndex(model->index(1,0));
1147 QVERIFY(view->currentIndex() == model->index(result ? 1 : 0,0));
1152 void tst_QAbstractItemView::task221955_selectedEditor()
1154 QPushButton *button;
1157 tree.setColumnCount(2);
1159 tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Foo" <<"1"));
1160 tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Bar" <<"2"));
1161 tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Baz" <<"3"));
1163 QTreeWidgetItem *dummy = new QTreeWidgetItem();
1164 tree.addTopLevelItem(dummy);
1165 tree.setItemWidget(dummy, 0, button = new QPushButton("More..."));
1166 button->setAutoFillBackground(true); // as recommended in doc
1170 tree.setCurrentIndex(tree.model()->index(1,0));
1172 QApplication::setActiveWindow(&tree);
1174 QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
1176 //We set the focus to the button, the index need to be selected
1179 QVERIFY(tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
1181 tree.setCurrentIndex(tree.model()->index(1,0));
1182 QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
1184 //Same thing but with the flag NoSelection, nothing can be selected.
1186 tree.setSelectionMode(QAbstractItemView::NoSelection);
1187 tree.clearSelection();
1188 QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty());
1192 QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty());
1195 void tst_QAbstractItemView::task250754_fontChange()
1197 QString app_css = qApp->styleSheet();
1198 qApp->setStyleSheet("/* */");
1202 QVBoxLayout *vLayout = new QVBoxLayout(&w);
1203 vLayout->addWidget(&tree);
1205 QStandardItemModel *m = new QStandardItemModel(this);
1206 for (int i=0; i<5; ++i) {
1207 QStandardItem *item = new QStandardItem(QString("Item number %1").arg(i));
1208 for (int j=0; j<5; ++j) {
1209 QStandardItem *child = new QStandardItem(QString("Child Item number %1").arg(j));
1210 item->setChild(j, 0, child);
1212 m->setItem(i, 0, item);
1219 QFont font = tree.font();
1220 font.setPixelSize(10);
1222 QTRY_VERIFY(!tree.verticalScrollBar()->isVisible());
1224 font.setPixelSize(60);
1226 //now with the huge items, the scrollbar must be visible
1227 QTRY_VERIFY(tree.verticalScrollBar()->isVisible());
1229 qApp->setStyleSheet(app_css);
1232 void tst_QAbstractItemView::task200665_itemEntered()
1234 #ifdef Q_OS_WINCE_WM
1235 QSKIP("On Windows Mobile the mouse tracking is unavailable at the moment");
1237 //we test that view will emit entered
1238 //when the scrollbar move but not the mouse itself
1239 QStandardItemModel model(1000,1);
1241 view.setModel(&model);
1244 QRect rect = view.visualRect(model.index(0,0));
1245 QCursor::setPos( view.viewport()->mapToGlobal(rect.center()) );
1246 QSignalSpy spy(&view, SIGNAL(entered(QModelIndex)));
1247 view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
1249 QCOMPARE(spy.count(), 1);
1252 void tst_QAbstractItemView::task257481_emptyEditor()
1254 QIcon icon = qApp->style()->standardIcon(QStyle::SP_ComputerIcon);
1256 QStandardItemModel model;
1258 model.appendRow( new QStandardItem(icon, QString()) );
1259 model.appendRow( new QStandardItem(icon, "Editor works") );
1260 model.appendRow( new QStandardItem( QString() ) );
1263 treeView.setRootIsDecorated(false);
1264 treeView.setModel(&model);
1267 treeView.edit(model.index(0,0));
1268 QList<QLineEdit *> lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
1269 QCOMPARE(lineEditors.count(), 1);
1270 QVERIFY(!lineEditors.first()->size().isEmpty());
1274 treeView.edit(model.index(1,0));
1275 lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
1276 QCOMPARE(lineEditors.count(), 1);
1277 QVERIFY(!lineEditors.first()->size().isEmpty());
1281 treeView.edit(model.index(2,0));
1282 lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
1283 QCOMPARE(lineEditors.count(), 1);
1284 QVERIFY(!lineEditors.first()->size().isEmpty());
1287 void tst_QAbstractItemView::shiftArrowSelectionAfterScrolling()
1289 QStandardItemModel model;
1290 for (int i=0; i<10; ++i) {
1291 QStandardItem *item = new QStandardItem(QString("%1").arg(i));
1292 model.setItem(i, 0, item);
1296 view.setFixedSize(150, 250);
1297 view.setFlow(QListView::LeftToRight);
1298 view.setGridSize(QSize(100, 100));
1299 view.setSelectionMode(QListView::ExtendedSelection);
1300 view.setViewMode(QListView::IconMode);
1301 view.setModel(&model);
1305 QModelIndex index0 = model.index(0, 0);
1306 QModelIndex index1 = model.index(1, 0);
1307 QModelIndex index9 = model.index(9, 0);
1309 view.selectionModel()->setCurrentIndex(index0, QItemSelectionModel::NoUpdate);
1310 QCOMPARE(view.currentIndex(), index0);
1312 view.scrollTo(index9);
1313 QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
1315 QCOMPARE(view.currentIndex(), index1);
1316 QModelIndexList selected = view.selectionModel()->selectedIndexes();
1317 QCOMPARE(selected.count(), 2);
1318 QVERIFY(selected.contains(index0));
1319 QVERIFY(selected.contains(index1));
1322 void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection()
1324 QStandardItemModel model;
1325 for (int i=0; i<3; ++i) {
1326 QStandardItem *item = new QStandardItem(QString("%1").arg(i));
1327 model.setItem(i, 0, item);
1331 view.setFixedSize(150, 450);
1332 view.setFlow(QListView::LeftToRight);
1333 view.setGridSize(QSize(100, 100));
1334 view.setSelectionMode(QListView::ExtendedSelection);
1335 view.setViewMode(QListView::IconMode);
1336 view.setModel(&model);
1340 QModelIndex index0 = model.index(0, 0);
1341 QModelIndex index1 = model.index(1, 0);
1342 QModelIndex index2 = model.index(2, 0);
1344 view.setCurrentIndex(index0);
1345 QCOMPARE(view.currentIndex(), index0);
1347 // Determine the points where the rubberband selection starts and ends
1348 QPoint pressPos = view.visualRect(index1).bottomRight() + QPoint(1, 1);
1349 QPoint releasePos = view.visualRect(index1).center();
1350 QVERIFY(!view.indexAt(pressPos).isValid());
1351 QCOMPARE(view.indexAt(releasePos), index1);
1353 // Select item 1 using a rubberband selection
1354 // The mouse move event has to be created manually because the QTest framework does not
1355 // contain a function for mouse moves with buttons pressed
1356 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos);
1357 QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
1358 bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
1359 QVERIFY(moveEventReceived);
1360 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos);
1361 QCOMPARE(view.currentIndex(), index1);
1363 // Shift-click item 2
1364 QPoint item2Pos = view.visualRect(index2).center();
1365 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, item2Pos);
1366 QCOMPARE(view.currentIndex(), index2);
1368 // Verify that the selection worked OK
1369 QModelIndexList selected = view.selectionModel()->selectedIndexes();
1370 QCOMPARE(selected.count(), 2);
1371 QVERIFY(selected.contains(index1));
1372 QVERIFY(selected.contains(index2));
1374 // Select item 0 to revert the selection
1375 view.setCurrentIndex(index0);
1376 QCOMPARE(view.currentIndex(), index0);
1378 // Repeat the same steps as above, but with a Shift-Arrow selection
1379 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos);
1380 QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
1381 moveEventReceived = qApp->notify(view.viewport(), &moveEvent2);
1382 QVERIFY(moveEventReceived);
1383 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos);
1384 QCOMPARE(view.currentIndex(), index1);
1387 QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
1388 QCOMPARE(view.currentIndex(), index2);
1390 // Verify that the selection worked OK
1391 selected = view.selectionModel()->selectedIndexes();
1392 QCOMPARE(selected.count(), 2);
1393 QVERIFY(selected.contains(index1));
1394 QVERIFY(selected.contains(index2));
1397 void tst_QAbstractItemView::ctrlRubberbandSelection()
1399 QStandardItemModel model;
1400 for (int i=0; i<3; ++i) {
1401 QStandardItem *item = new QStandardItem(QString("%1").arg(i));
1402 model.setItem(i, 0, item);
1406 view.setFixedSize(150, 450);
1407 view.setFlow(QListView::LeftToRight);
1408 view.setGridSize(QSize(100, 100));
1409 view.setSelectionMode(QListView::ExtendedSelection);
1410 view.setViewMode(QListView::IconMode);
1411 view.setModel(&model);
1415 QModelIndex index1 = model.index(1, 0);
1416 QModelIndex index2 = model.index(2, 0);
1419 view.setCurrentIndex(index1);
1420 QModelIndexList selected = view.selectionModel()->selectedIndexes();
1421 QCOMPARE(selected.count(), 1);
1422 QVERIFY(selected.contains(index1));
1424 // Now press control and draw a rubberband around items 1 and 2.
1425 // The mouse move event has to be created manually because the QTest framework does not
1426 // contain a function for mouse moves with buttons pressed.
1427 QPoint pressPos = view.visualRect(index1).topLeft() - QPoint(1, 1);
1428 QPoint releasePos = view.visualRect(index2).bottomRight() + QPoint(1, 1);
1429 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pressPos);
1430 QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
1431 bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
1432 QVERIFY(moveEventReceived);
1433 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, releasePos);
1435 // Verify that item 2 is selected now
1436 selected = view.selectionModel()->selectedIndexes();
1437 QCOMPARE(selected.count(), 1);
1438 QVERIFY(selected.contains(index2));
1441 void tst_QAbstractItemView::QTBUG6407_extendedSelection()
1444 view.setSelectionMode(QAbstractItemView::ExtendedSelection);
1445 for(int i = 0; i < 50; ++i)
1446 view.addItem(QString::number(i));
1448 QFont font = view.font();
1449 font.setPixelSize(10);
1451 view.resize(200,240);
1454 QApplication::setActiveWindow(&view);
1455 QVERIFY(QTest::qWaitForWindowActive(&view));
1456 QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow());
1458 view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
1461 QModelIndex index49 = view.model()->index(49,0);
1462 QPoint p = view.visualRect(index49).center();
1463 QVERIFY(view.viewport()->rect().contains(p));
1464 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
1465 QCOMPARE(view.currentIndex(), index49);
1466 QCOMPARE(view.selectedItems().count(), 1);
1468 QModelIndex index47 = view.model()->index(47,0);
1469 p = view.visualRect(index47).center();
1470 QVERIFY(view.viewport()->rect().contains(p));
1471 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p);
1472 QCOMPARE(view.currentIndex(), index47);
1473 QCOMPARE(view.selectedItems().count(), 3); //49, 48, 47;
1475 QModelIndex index44 = view.model()->index(44,0);
1476 p = view.visualRect(index44).center();
1477 QVERIFY(view.viewport()->rect().contains(p));
1478 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p);
1479 QCOMPARE(view.currentIndex(), index44);
1480 QCOMPARE(view.selectedItems().count(), 6); //49 .. 44;
1484 void tst_QAbstractItemView::QTBUG6753_selectOnSelection()
1486 QTableWidget table(5, 5);
1487 for (int i = 0; i < table.rowCount(); ++i)
1488 for (int j = 0; j < table.columnCount(); ++j)
1489 table.setItem(i, j, new QTableWidgetItem("choo-be-doo-wah"));
1492 table.setSelectionMode(QAbstractItemView::ExtendedSelection);
1494 QVERIFY(QTest::qWaitForWindowExposed(&table));
1495 QModelIndex item = table.model()->index(1,1);
1496 QRect itemRect = table.visualRect(item);
1497 QTest::mouseMove(table.viewport(), itemRect.center());
1498 QTest::mouseClick(table.viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center());
1501 QCOMPARE(table.selectedItems().count(), 1);
1502 QCOMPARE(table.selectedItems().first(), table.item(item.row(), item.column()));
1505 void tst_QAbstractItemView::testDelegateDestroyEditor()
1507 QTableWidget table(5, 5);
1508 MyAbstractItemDelegate delegate;
1509 table.setItemDelegate(&delegate);
1510 table.edit(table.model()->index(1, 1));
1511 TestView *tv = reinterpret_cast<TestView*>(&table);
1512 QVERIFY(!delegate.calledVirtualDtor);
1513 tv->tst_closeEditor(delegate.openedEditor, QAbstractItemDelegate::NoHint);
1514 QVERIFY(delegate.calledVirtualDtor);
1518 QTEST_MAIN(tst_QAbstractItemView)
1519 #include "tst_qabstractitemview.moc"