1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the test suite of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
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
static inline void setFrameless(QWidget *w)
75
Qt::WindowFlags flags = w->windowFlags();
76
flags |= Qt::FramelessWindowHint;
77
flags &= ~(Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
78
w->setWindowFlags(flags);
81
class TestView : public QAbstractItemView
85
inline void tst_dataChanged(const QModelIndex &tl, const QModelIndex &br)
86
{ dataChanged(tl, br); }
87
inline void tst_setHorizontalStepsPerItem(int steps)
88
{ setHorizontalStepsPerItem(steps); }
89
inline int tst_horizontalStepsPerItem() const
90
{ return horizontalStepsPerItem(); }
91
inline void tst_setVerticalStepsPerItem(int steps)
92
{ setVerticalStepsPerItem(steps); }
93
inline int tst_verticalStepsPerItem() const
94
{ return verticalStepsPerItem(); }
96
inline void tst_rowsInserted(const QModelIndex &parent, int start, int end)
97
{ rowsInserted(parent, start, end); }
98
inline void tst_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
99
{ rowsAboutToBeRemoved(parent, start, end); }
100
inline void tst_selectionChanged(const QItemSelection &selected,
101
const QItemSelection &deselected)
102
{ selectionChanged(selected, deselected); }
103
inline void tst_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
104
{ currentChanged(current, previous); }
105
inline void tst_updateEditorData()
106
{ updateEditorData(); }
107
inline void tst_updateEditorGeometries()
108
{ updateEditorGeometries(); }
109
inline void tst_updateGeometries()
110
{ updateGeometries(); }
111
inline void tst_verticalScrollbarAction(int action)
112
{ verticalScrollbarAction(action); }
113
inline void tst_horizontalScrollbarAction(int action)
114
{ horizontalScrollbarAction(action); }
115
inline void tst_verticalScrollbarValueChanged(int value)
116
{ verticalScrollbarValueChanged(value); }
117
inline void tst_horizontalScrollbarValueChanged(int value)
118
{ horizontalScrollbarValueChanged(value); }
119
inline void tst_closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
120
{ closeEditor(editor, hint); }
121
inline void tst_commitData(QWidget *editor)
122
{ commitData(editor); }
123
inline void tst_editorDestroyed(QObject *editor)
124
{ editorDestroyed(editor); }
125
enum tst_CursorAction {
126
MoveUp = QAbstractItemView::MoveUp,
127
MoveDown = QAbstractItemView::MoveDown,
128
MoveLeft = QAbstractItemView::MoveLeft,
129
MoveRight = QAbstractItemView::MoveRight,
130
MoveHome = QAbstractItemView::MoveHome,
131
MoveEnd = QAbstractItemView::MoveEnd,
132
MovePageUp = QAbstractItemView::MovePageUp,
133
MovePageDown = QAbstractItemView::MovePageDown,
134
MoveNext = QAbstractItemView::MoveNext,
135
MovePrevious = QAbstractItemView::MovePrevious
137
inline QModelIndex tst_moveCursor(tst_CursorAction cursorAction,
138
Qt::KeyboardModifiers modifiers)
139
{ return moveCursor(QAbstractItemView::CursorAction(cursorAction), modifiers); }
140
inline int tst_horizontalOffset() const
141
{ return horizontalOffset(); }
142
inline int tst_verticalOffset() const
143
{ return verticalOffset(); }
144
inline bool tst_isIndexHidden(const QModelIndex &index) const
145
{ return isIndexHidden(index); }
146
inline void tst_setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
147
{ setSelection(rect, command); }
148
inline QRegion tst_visualRegionForSelection(const QItemSelection &selection) const
149
{ return visualRegionForSelection(selection); }
150
inline QModelIndexList tst_selectedIndexes() const
151
{ return selectedIndexes(); }
152
inline bool tst_edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
153
{ return edit(index, trigger, event); }
154
inline QItemSelectionModel::SelectionFlags tst_selectionCommand(const QModelIndex &index,
155
const QEvent *event = 0) const
156
{ return selectionCommand(index, event); }
157
#ifndef QT_NO_DRAGANDDROP
158
inline void tst_startDrag(Qt::DropActions supportedActions)
159
{ startDrag(supportedActions); }
161
inline QStyleOptionViewItem tst_viewOptions() const
162
{ return viewOptions(); }
164
NoState = QAbstractItemView::NoState,
165
DraggingState = QAbstractItemView::DraggingState,
166
DragSelectingState = QAbstractItemView::DragSelectingState,
167
EditingState = QAbstractItemView::EditingState,
168
ExpandingState = QAbstractItemView::ExpandingState,
169
CollapsingState = QAbstractItemView::CollapsingState
171
inline tst_State tst_state() const
172
{ return (tst_State)state(); }
173
inline void tst_setState(tst_State state)
174
{ setState(QAbstractItemView::State(state)); }
175
inline void tst_startAutoScroll()
176
{ startAutoScroll(); }
177
inline void tst_stopAutoScroll()
178
{ stopAutoScroll(); }
179
inline void tst_doAutoScroll()
183
class tst_QAbstractItemView : public QObject
189
tst_QAbstractItemView();
190
virtual ~tst_QAbstractItemView();
191
void basic_tests(TestView *view);
195
void cleanupTestCase();
199
void emptyModels_data();
201
void setModel_data();
206
void columnDelegate();
209
void persistentEditorFocus();
210
void setItemDelegate();
211
void setItemDelegate_data();
212
// The dragAndDrop() test doesn't work, and is thus disabled on Mac and Windows
213
// for the following reasons:
214
// Mac: use of GetCurrentEventButtonState() in QDragManager::drag()
215
// Win: unknown reason
216
#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
219
void dragAndDropOnChild();
222
void noFallbackToRoot();
223
void setCurrentIndex_data();
224
void setCurrentIndex();
226
void task221955_selectedEditor();
227
void task250754_fontChange();
228
void task200665_itemEntered();
229
void task257481_emptyEditor();
230
void shiftArrowSelectionAfterScrolling();
231
void shiftSelectionAfterRubberbandSelection();
232
void ctrlRubberbandSelection();
233
void QTBUG6407_extendedSelection();
234
void QTBUG6753_selectOnSelection();
235
void testDelegateDestroyEditor();
236
void testClickedSignal();
237
void testChangeEditorState();
240
class MyAbstractItemDelegate : public QAbstractItemDelegate
243
MyAbstractItemDelegate() : QAbstractItemDelegate() { calledVirtualDtor = false; }
244
void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
245
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
246
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
248
openedEditor = new QWidget(parent);
251
void destroyEditor(QWidget *editor, const QModelIndex &) const
253
calledVirtualDtor = true;
254
editor->deleteLater();
257
mutable bool calledVirtualDtor;
258
mutable QWidget *openedEditor;
261
// Testing get/set functions
262
void tst_QAbstractItemView::getSetCheck()
265
TestView *obj1 = reinterpret_cast<TestView*>(&view);
266
// QAbstractItemDelegate * QAbstractItemView::itemDelegate()
267
// void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *)
268
MyAbstractItemDelegate *var1 = new MyAbstractItemDelegate;
269
obj1->setItemDelegate(var1);
270
QCOMPARE((QAbstractItemDelegate*)var1, obj1->itemDelegate());
271
obj1->setItemDelegate((QAbstractItemDelegate *)0);
272
QCOMPARE((QAbstractItemDelegate *)0, obj1->itemDelegate());
275
// EditTriggers QAbstractItemView::editTriggers()
276
// void QAbstractItemView::setEditTriggers(EditTriggers)
277
obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers));
278
QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers), obj1->editTriggers());
279
obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged));
280
QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged), obj1->editTriggers());
281
obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked));
282
QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked), obj1->editTriggers());
283
obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked));
284
QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked), obj1->editTriggers());
285
obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed));
286
QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed), obj1->editTriggers());
287
obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed));
288
QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed), obj1->editTriggers());
289
obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers));
290
QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers), obj1->editTriggers());
292
// bool QAbstractItemView::tabKeyNavigation()
293
// void QAbstractItemView::setTabKeyNavigation(bool)
294
obj1->setTabKeyNavigation(false);
295
QCOMPARE(false, obj1->tabKeyNavigation());
296
obj1->setTabKeyNavigation(true);
297
QCOMPARE(true, obj1->tabKeyNavigation());
299
// bool QAbstractItemView::dragEnabled()
300
// void QAbstractItemView::setDragEnabled(bool)
301
#ifndef QT_NO_DRAGANDDROP
302
obj1->setDragEnabled(false);
303
QCOMPARE(false, obj1->dragEnabled());
304
obj1->setDragEnabled(true);
305
QCOMPARE(true, obj1->dragEnabled());
307
// bool QAbstractItemView::alternatingRowColors()
308
// void QAbstractItemView::setAlternatingRowColors(bool)
309
obj1->setAlternatingRowColors(false);
310
QCOMPARE(false, obj1->alternatingRowColors());
311
obj1->setAlternatingRowColors(true);
312
QCOMPARE(true, obj1->alternatingRowColors());
314
// State QAbstractItemView::state()
315
// void QAbstractItemView::setState(State)
316
obj1->tst_setState(TestView::tst_State(TestView::NoState));
317
QCOMPARE(TestView::tst_State(TestView::NoState), obj1->tst_state());
318
obj1->tst_setState(TestView::tst_State(TestView::DraggingState));
319
QCOMPARE(TestView::tst_State(TestView::DraggingState), obj1->tst_state());
320
obj1->tst_setState(TestView::tst_State(TestView::DragSelectingState));
321
QCOMPARE(TestView::tst_State(TestView::DragSelectingState), obj1->tst_state());
322
obj1->tst_setState(TestView::tst_State(TestView::EditingState));
323
QCOMPARE(TestView::tst_State(TestView::EditingState), obj1->tst_state());
324
obj1->tst_setState(TestView::tst_State(TestView::ExpandingState));
325
QCOMPARE(TestView::tst_State(TestView::ExpandingState), obj1->tst_state());
326
obj1->tst_setState(TestView::tst_State(TestView::CollapsingState));
327
QCOMPARE(TestView::tst_State(TestView::CollapsingState), obj1->tst_state());
329
// QWidget QAbstractScrollArea::viewport()
330
// void setViewport(QWidget*)
331
QWidget *vp = new QWidget;
332
obj1->setViewport(vp);
333
QCOMPARE(vp, obj1->viewport());
335
QCOMPARE(16, obj1->autoScrollMargin());
336
obj1->setAutoScrollMargin(20);
337
QCOMPARE(20, obj1->autoScrollMargin());
338
obj1->setAutoScrollMargin(16);
339
QCOMPARE(16, obj1->autoScrollMargin());
342
tst_QAbstractItemView::tst_QAbstractItemView()
346
tst_QAbstractItemView::~tst_QAbstractItemView()
350
void tst_QAbstractItemView::initTestCase()
353
qApp->setAutoMaximizeThreshold(-1);
357
void tst_QAbstractItemView::cleanupTestCase()
361
void tst_QAbstractItemView::emptyModels_data()
363
QTest::addColumn<QString>("viewType");
365
QTest::newRow("QListView") << "QListView";
366
QTest::newRow("QTableView") << "QTableView";
367
QTest::newRow("QTreeView") << "QTreeView";
368
QTest::newRow("QHeaderView") << "QHeaderView";
371
void tst_QAbstractItemView::emptyModels()
373
QFETCH(QString, viewType);
376
if (viewType == "QListView")
377
view = reinterpret_cast<TestView*>(new QListView());
378
else if (viewType == "QTableView")
379
view = reinterpret_cast<TestView*>(new QTableView());
380
else if (viewType == "QTreeView")
381
view = reinterpret_cast<TestView*>(new QTreeView());
382
else if (viewType == "QHeaderView")
383
view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
388
QVERIFY(!view->model());
389
QVERIFY(!view->selectionModel());
390
//QVERIFY(view->itemDelegate() != 0);
396
void tst_QAbstractItemView::setModel_data()
398
QTest::addColumn<QString>("viewType");
400
QTest::newRow("QListView") << "QListView";
401
QTest::newRow("QTableView") << "QTableView";
402
QTest::newRow("QTreeView") << "QTreeView";
403
QTest::newRow("QHeaderView") << "QHeaderView";
406
void tst_QAbstractItemView::setModel()
408
QFETCH(QString, viewType);
410
if (viewType == "QListView")
411
view = reinterpret_cast<TestView*>(new QListView());
412
else if (viewType == "QTableView")
413
view = reinterpret_cast<TestView*>(new QTableView());
414
else if (viewType == "QTreeView")
415
view = reinterpret_cast<TestView*>(new QTreeView());
416
else if (viewType == "QHeaderView")
417
view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
422
QStandardItemModel model(20,20);
424
view->setModel(&model);
429
void tst_QAbstractItemView::basic_tests(TestView *view)
432
// Will assert as it should
433
//view->setSelectionModel(0);
435
//view->setItemDelegate(0);
436
// Will asswert as it should
439
view->setSelectionMode(QAbstractItemView::SingleSelection);
440
QCOMPARE(view->selectionMode(), QAbstractItemView::SingleSelection);
441
view->setSelectionMode(QAbstractItemView::ContiguousSelection);
442
QCOMPARE(view->selectionMode(), QAbstractItemView::ContiguousSelection);
443
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
444
QCOMPARE(view->selectionMode(), QAbstractItemView::ExtendedSelection);
445
view->setSelectionMode(QAbstractItemView::MultiSelection);
446
QCOMPARE(view->selectionMode(), QAbstractItemView::MultiSelection);
447
view->setSelectionMode(QAbstractItemView::NoSelection);
448
QCOMPARE(view->selectionMode(), QAbstractItemView::NoSelection);
450
// setSelectionBehavior
451
view->setSelectionBehavior(QAbstractItemView::SelectItems);
452
QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectItems);
453
view->setSelectionBehavior(QAbstractItemView::SelectRows);
454
QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectRows);
455
view->setSelectionBehavior(QAbstractItemView::SelectColumns);
456
QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectColumns);
459
view->setEditTriggers(QAbstractItemView::EditKeyPressed);
460
QCOMPARE(view->editTriggers(), QAbstractItemView::EditKeyPressed);
461
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
462
QCOMPARE(view->editTriggers(), QAbstractItemView::NoEditTriggers);
463
view->setEditTriggers(QAbstractItemView::CurrentChanged);
464
QCOMPARE(view->editTriggers(), QAbstractItemView::CurrentChanged);
465
view->setEditTriggers(QAbstractItemView::DoubleClicked);
466
QCOMPARE(view->editTriggers(), QAbstractItemView::DoubleClicked);
467
view->setEditTriggers(QAbstractItemView::SelectedClicked);
468
QCOMPARE(view->editTriggers(), QAbstractItemView::SelectedClicked);
469
view->setEditTriggers(QAbstractItemView::AnyKeyPressed);
470
QCOMPARE(view->editTriggers(), QAbstractItemView::AnyKeyPressed);
471
view->setEditTriggers(QAbstractItemView::AllEditTriggers);
472
QCOMPARE(view->editTriggers(), QAbstractItemView::AllEditTriggers);
475
view->setAutoScroll(false);
476
QCOMPARE(view->hasAutoScroll(), false);
477
view->setAutoScroll(true);
478
QCOMPARE(view->hasAutoScroll(), true);
480
// setTabKeyNavigation
481
view->setTabKeyNavigation(false);
482
QCOMPARE(view->tabKeyNavigation(), false);
483
view->setTabKeyNavigation(true);
484
QCOMPARE(view->tabKeyNavigation(), true);
486
#ifndef QT_NO_DRAGANDDROP
487
// setDropIndicatorShown
488
view->setDropIndicatorShown(false);
489
QCOMPARE(view->showDropIndicator(), false);
490
view->setDropIndicatorShown(true);
491
QCOMPARE(view->showDropIndicator(), true);
494
view->setDragEnabled(false);
495
QCOMPARE(view->dragEnabled(), false);
496
view->setDragEnabled(true);
497
QCOMPARE(view->dragEnabled(), true);
500
// setAlternatingRowColors
501
view->setAlternatingRowColors(false);
502
QCOMPARE(view->alternatingRowColors(), false);
503
view->setAlternatingRowColors(true);
504
QCOMPARE(view->alternatingRowColors(), true);
507
view->setIconSize(QSize(16, 16));
508
QCOMPARE(view->iconSize(), QSize(16, 16));
509
view->setIconSize(QSize(32, 32));
510
QCOMPARE(view->iconSize(), QSize(32, 32));
511
// Should this happen?
512
view->setIconSize(QSize(-1, -1));
513
QCOMPARE(view->iconSize(), QSize(-1, -1));
515
QCOMPARE(view->currentIndex(), QModelIndex());
516
QCOMPARE(view->rootIndex(), QModelIndex());
518
view->keyboardSearch("");
519
view->keyboardSearch("foo");
520
view->keyboardSearch("1");
522
QCOMPARE(view->visualRect(QModelIndex()), QRect());
524
view->scrollTo(QModelIndex());
526
QCOMPARE(view->sizeHintForIndex(QModelIndex()), QSize());
527
QCOMPARE(view->indexAt(QPoint(-1, -1)), QModelIndex());
530
QCOMPARE(view->indexAt(QPoint(10, 10)), QModelIndex());
531
QCOMPARE(view->sizeHintForRow(0), -1);
532
QCOMPARE(view->sizeHintForColumn(0), -1);
533
}else if (view->itemDelegate()){
534
view->sizeHintForRow(0);
535
view->sizeHintForColumn(0);
537
view->openPersistentEditor(QModelIndex());
538
view->closePersistentEditor(QModelIndex());
541
view->setRootIndex(QModelIndex());
542
view->doItemsLayout();
544
view->edit(QModelIndex());
545
view->clearSelection();
546
view->setCurrentIndex(QModelIndex());
549
view->tst_dataChanged(QModelIndex(), QModelIndex());
550
view->tst_rowsInserted(QModelIndex(), -1, -1);
551
view->tst_rowsAboutToBeRemoved(QModelIndex(), -1, -1);
552
view->tst_selectionChanged(QItemSelection(), QItemSelection());
554
view->tst_currentChanged(QModelIndex(), QModelIndex());
555
view->tst_currentChanged(QModelIndex(), view->model()->index(0,0));
557
view->tst_updateEditorData();
558
view->tst_updateEditorGeometries();
559
view->tst_updateGeometries();
560
view->tst_verticalScrollbarAction(QAbstractSlider::SliderSingleStepAdd);
561
view->tst_horizontalScrollbarAction(QAbstractSlider::SliderSingleStepAdd);
562
view->tst_verticalScrollbarValueChanged(10);
563
view->tst_horizontalScrollbarValueChanged(10);
564
view->tst_closeEditor(0, QAbstractItemDelegate::NoHint);
565
view->tst_commitData(0);
566
view->tst_editorDestroyed(0);
568
view->tst_setHorizontalStepsPerItem(2);
569
view->tst_horizontalStepsPerItem();
570
view->tst_setVerticalStepsPerItem(2);
571
view->tst_verticalStepsPerItem();
573
// Will assert as it should
574
// view->setIndexWidget(QModelIndex(), 0);
576
view->tst_moveCursor(TestView::MoveUp, Qt::NoModifier);
577
view->tst_horizontalOffset();
578
view->tst_verticalOffset();
580
// view->tst_isIndexHidden(QModelIndex()); // will (correctly) assert
582
view->tst_isIndexHidden(view->model()->index(0,0));
584
view->tst_setSelection(QRect(0, 0, 10, 10), QItemSelectionModel::ClearAndSelect);
585
view->tst_setSelection(QRect(-1, -1, -1, -1), QItemSelectionModel::ClearAndSelect);
586
view->tst_visualRegionForSelection(QItemSelection());
587
view->tst_selectedIndexes();
589
view->tst_edit(QModelIndex(), QAbstractItemView::NoEditTriggers, 0);
591
view->tst_selectionCommand(QModelIndex(), 0);
593
#ifndef QT_NO_DRAGANDDROP
595
view->tst_startDrag(Qt::CopyAction);
597
view->tst_viewOptions();
599
view->tst_setState(TestView::NoState);
600
QVERIFY(view->tst_state()==TestView::NoState);
601
view->tst_setState(TestView::DraggingState);
602
QVERIFY(view->tst_state()==TestView::DraggingState);
603
view->tst_setState(TestView::DragSelectingState);
604
QVERIFY(view->tst_state()==TestView::DragSelectingState);
605
view->tst_setState(TestView::EditingState);
606
QVERIFY(view->tst_state()==TestView::EditingState);
607
view->tst_setState(TestView::ExpandingState);
608
QVERIFY(view->tst_state()==TestView::ExpandingState);
609
view->tst_setState(TestView::CollapsingState);
610
QVERIFY(view->tst_state()==TestView::CollapsingState);
613
view->tst_startAutoScroll();
614
view->tst_stopAutoScroll();
615
view->tst_doAutoScroll();
617
// testing mouseFoo and key functions
618
// QTest::mousePress(view, Qt::LeftButton, Qt::NoModifier, QPoint(0,0));
619
// mouseMove(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
620
// QTest::mouseRelease(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
621
// QTest::mouseClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
622
// mouseDClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
623
// QTest::keyClick(view, Qt::Key_A);
626
void tst_QAbstractItemView::noModel()
630
QStandardItemModel model(20,20);
634
view.setModel(&model);
635
// Make the viewport smaller than the contents, so that we can scroll
636
view.resize(100,100);
639
// make sure that the scrollbars are not at value 0
640
view.scrollTo(view.model()->index(10,10));
641
QApplication::processEvents();
644
// Due to the model is removed, this will generate a valueChanged signal on both scrollbars. (value to 0)
645
QApplication::processEvents();
646
QCOMPARE(view.model(), (QAbstractItemModel*)0);
649
void tst_QAbstractItemView::dragSelect()
653
QStandardItemModel model(64,64);
656
view.setModel(&model);
657
view.setVisible(true);
660
for (int i = 0; i < 2; ++i) {
661
bool tracking = (i == 1);
662
view.setMouseTracking(false);
663
QTest::mouseMove(&view, QPoint(0, 0), delay);
664
view.setMouseTracking(tracking);
665
QTest::mouseMove(&view, QPoint(50, 50), delay);
666
QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
670
void tst_QAbstractItemView::rowDelegate()
672
QStandardItemModel model(4,4);
673
MyAbstractItemDelegate delegate;
676
view.setModel(&model);
677
view.setItemDelegateForRow(3, &delegate);
680
QModelIndex index = model.index(3, 0);
681
view.openPersistentEditor(index);
682
QWidget *w = view.indexWidget(index);
684
QCOMPARE(w->metaObject()->className(), "QWidget");
687
void tst_QAbstractItemView::columnDelegate()
689
QStandardItemModel model(4,4);
690
MyAbstractItemDelegate delegate;
693
view.setModel(&model);
694
view.setItemDelegateForColumn(3, &delegate);
697
QModelIndex index = model.index(0, 3);
698
view.openPersistentEditor(index);
699
QWidget *w = view.indexWidget(index);
701
QCOMPARE(w->metaObject()->className(), "QWidget");
704
void tst_QAbstractItemView::selectAll()
706
QStandardItemModel model(4,4);
708
view.setModel(&model);
710
TestView *tst_view = (TestView*)&view;
712
QCOMPARE(tst_view->tst_selectedIndexes().count(), 0);
714
QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4);
717
void tst_QAbstractItemView::ctrlA()
719
QStandardItemModel model(4,4);
721
view.setModel(&model);
723
TestView *tst_view = (TestView*)&view;
725
QCOMPARE(tst_view->tst_selectedIndexes().count(), 0);
726
QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
727
QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4);
730
void tst_QAbstractItemView::persistentEditorFocus()
732
// one row, three columns
733
QStandardItemModel model(1, 3);
734
for(int i = 0; i < model.columnCount(); ++i)
735
model.setData(model.index(0, i), i);
737
view.setModel(&model);
739
view.openPersistentEditor(model.index(0, 1));
740
view.openPersistentEditor(model.index(0, 2));
742
//these are spinboxes because we put numbers inside
743
QList<QSpinBox*> list = qFindChildren<QSpinBox*>(view.viewport());
744
QCOMPARE(list.count(), 2); //these should be the 2 editors
746
view.setCurrentIndex(model.index(0, 0));
747
QCOMPARE(view.currentIndex(), model.index(0, 0));
749
QTRY_VERIFY(view.isVisible());
751
for (int i = 0; i < list.count(); ++i) {
752
TRY_COMPARE(list.at(i)->isVisible(), true);
753
QPoint p = QPoint(5, 5);
754
QMouseEvent mouseEvent(QEvent::MouseButtonPress, p, Qt::LeftButton,
755
Qt::LeftButton, Qt::NoModifier);
756
qApp->sendEvent(list.at(i), &mouseEvent);
757
if (!qApp->focusWidget())
758
QSKIP("Some window managers don't handle focus that well");
759
QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget *>(list.at(i)));
764
#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
768
static void sendMouseMove(QWidget *widget, QPoint pos = QPoint())
771
pos = widget->rect().center();
772
QMouseEvent event(QEvent::MouseMove, pos, widget->mapToGlobal(pos), Qt::NoButton, 0, 0);
773
QCursor::setPos(widget->mapToGlobal(pos));
774
qApp->processEvents();
775
QVERIFY(QTest::qWaitForWindowExposed(widget));
776
QApplication::sendEvent(widget, &event);
779
static void sendMousePress(
780
QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton)
783
pos = widget->rect().center();
784
QMouseEvent event(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, 0, 0);
785
QApplication::sendEvent(widget, &event);
788
static void sendMouseRelease(
789
QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton)
792
pos = widget->rect().center();
793
QMouseEvent event(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, 0, 0);
794
QApplication::sendEvent(widget, &event);
797
class DnDTestModel : public QStandardItemModel
800
bool dropMimeData(const QMimeData *md, Qt::DropAction action, int r, int c, const QModelIndex &p)
802
dropAction_result = action;
803
QStandardItemModel::dropMimeData(md, action, r, c, p);
806
Qt::DropActions supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; }
808
Qt::DropAction dropAction_result;
810
DnDTestModel() : QStandardItemModel(20, 20), dropAction_result(Qt::IgnoreAction) {
811
for (int i = 0; i < rowCount(); ++i)
812
setData(index(i, 0), QString("%1").arg(i));
814
Qt::DropAction dropAction() const { return dropAction_result; }
817
class DnDTestView : public QTreeView
822
Qt::DropAction dropAction;
824
void dragEnterEvent(QDragEnterEvent *event)
826
QAbstractItemView::dragEnterEvent(event);
829
void dropEvent(QDropEvent *event)
831
event->setDropAction(dropAction);
832
QTreeView::dropEvent(event);
835
void timerEvent(QTimerEvent *event)
837
killTimer(event->timerId());
838
sendMouseMove(this, dropPoint);
839
sendMouseRelease(this);
842
void mousePressEvent(QMouseEvent *e)
844
QTreeView::mousePressEvent(e);
847
setState(DraggingState);
848
startDrag(dropAction);
852
DnDTestView(Qt::DropAction dropAction, QAbstractItemModel *model)
853
: dropAction(dropAction)
857
setDragDropMode(QAbstractItemView::DragDrop);
858
setAcceptDrops(true);
859
setDragEnabled(true);
862
void dragAndDrop(QPoint drag, QPoint drop)
865
setCurrentIndex(indexAt(drag));
866
sendMousePress(viewport(), drag);
870
class DnDTestWidget : public QWidget
874
Qt::DropAction dropAction_request;
875
Qt::DropAction dropAction_result;
878
void timerEvent(QTimerEvent *event)
880
killTimer(event->timerId());
881
sendMouseMove(dropTarget);
882
sendMouseRelease(dropTarget);
885
void mousePressEvent(QMouseEvent *)
887
QDrag *drag = new QDrag(this);
888
QMimeData *mimeData = new QMimeData;
889
mimeData->setData("application/x-qabstractitemmodeldatalist", QByteArray(""));
890
drag->setMimeData(mimeData);
892
dropAction_result = drag->start(dropAction_request);
896
Qt::DropAction dropAction() const { return dropAction_result; }
898
void dragAndDrop(QWidget *dropTarget, Qt::DropAction dropAction)
900
this->dropTarget = dropTarget;
901
dropAction_request = dropAction;
902
sendMousePress(this);
906
void tst_QAbstractItemView::dragAndDrop()
911
const int attempts = 10;
913
for (int i = 0; i < attempts; ++i) {
914
Qt::DropAction dropAction = Qt::MoveAction;
917
DnDTestView view(dropAction, &model);
918
DnDTestWidget widget;
920
const int size = 200;
921
widget.setFixedSize(size, size);
922
view.setFixedSize(size, size);
925
view.move(int(size * 1.5), int(size * 1.5));
929
QVERIFY(QTest::qWaitForWindowExposed(&widget));
930
QVERIFY(QTest::qWaitForWindowExposed(&view));
932
widget.dragAndDrop(&view, dropAction);
933
if (model.dropAction() == dropAction
934
&& widget.dropAction() == dropAction)
938
if (successes < attempts) {
939
QString msg = QString("# successes (%1) < # attempts (%2)").arg(successes).arg(attempts);
940
QWARN(msg.toLatin1());
942
QVERIFY(successes > 0); // allow for some "event unstability" (i.e. unless
943
// successes == 0, QAbstractItemView is probably ok!)
946
void tst_QAbstractItemView::dragAndDropOnChild()
949
const int attempts = 10;
951
for (int i = 0; i < attempts; ++i) {
952
Qt::DropAction dropAction = Qt::MoveAction;
955
QModelIndex parent = model.index(0, 0);
956
model.insertRow(0, parent);
957
model.insertColumn(0, parent);
958
QModelIndex child = model.index(0, 0, parent);
959
model.setData(child, "child");
960
QCOMPARE(model.rowCount(parent), 1);
961
DnDTestView view(dropAction, &model);
962
view.setExpanded(parent, true);
963
view.setDragDropMode(QAbstractItemView::InternalMove);
965
const int size = 200;
966
view.setFixedSize(size, size);
967
view.move(int(size * 1.5), int(size * 1.5));
969
QVERIFY(QTest::qWaitForWindowExposed(&view));
971
view.dragAndDrop(view.visualRect(parent).center(),
972
view.visualRect(child).center());
973
if (model.dropAction() == dropAction)
977
QVERIFY(successes == 0);
981
#endif // !Q_OS_MAC && !Q_OS_WIN
983
class TestModel : public QStandardItemModel
986
TestModel(int rows, int columns) : QStandardItemModel(rows, columns)
991
virtual bool setData(const QModelIndex &/*index*/, const QVariant &/*value*/, int /*role = Qt::EditRole*/)
1000
typedef QList<int> IntList;
1002
void tst_QAbstractItemView::setItemDelegate_data()
1004
// default is rows, a -1 will switch to columns
1005
QTest::addColumn<IntList>("rowsOrColumnsWithDelegate");
1006
QTest::addColumn<QPoint>("cellToEdit");
1007
QTest::newRow("4 columndelegates")
1008
<< (IntList() << -1 << 0 << 1 << 2 << 3)
1010
QTest::newRow("2 identical rowdelegates on the same row")
1011
<< (IntList() << 0 << 0)
1013
QTest::newRow("2 identical columndelegates on the same column")
1014
<< (IntList() << -1 << 2 << 2)
1016
QTest::newRow("2 duplicate delegates, 1 row and 1 column")
1017
<< (IntList() << 0 << -1 << 2)
1019
QTest::newRow("4 duplicate delegates, 2 row and 2 column")
1020
<< (IntList() << 0 << 0 << -1 << 2 << 2)
1025
void tst_QAbstractItemView::setItemDelegate()
1027
QFETCH(IntList, rowsOrColumnsWithDelegate);
1028
QFETCH(QPoint, cellToEdit);
1030
QItemDelegate *delegate = new QItemDelegate(&v);
1031
TestModel model(5, 5);
1035
foreach (int rc, rowsOrColumnsWithDelegate) {
1040
v.setItemDelegateForRow(rc, delegate);
1042
v.setItemDelegateForColumn(rc, delegate);
1048
QCursor::setPos(v.geometry().center());
1049
QApplication::syncX();
1051
QApplication::setActiveWindow(&v);
1052
QVERIFY(QTest::qWaitForWindowActive(&v));
1054
QModelIndex index = model.index(cellToEdit.y(), cellToEdit.x());
1057
// This will close the editor
1058
TRY_COMPARE(QApplication::focusWidget() == 0, false);
1059
QWidget *editor = QApplication::focusWidget();
1063
QCOMPARE(model.setData_count, 1);
1067
void tst_QAbstractItemView::noFallbackToRoot()
1069
QStandardItemModel model(0, 1);
1070
for (int i = 0; i < 5; ++i)
1071
model.appendRow(new QStandardItem("top" + QString::number(i)));
1072
QStandardItem *par1 = model.item(1);
1073
for (int j = 0; j < 15; ++j)
1074
par1->appendRow(new QStandardItem("sub" + QString::number(j)));
1075
QStandardItem *par2 = par1->child(2);
1076
for (int k = 0; k < 10; ++k)
1077
par2->appendRow(new QStandardItem("bot" + QString::number(k)));
1078
QStandardItem *it1 = par2->child(5);
1080
QModelIndex parent1 = model.indexFromItem(par1);
1081
QModelIndex parent2 = model.indexFromItem(par2);
1082
QModelIndex item1 = model.indexFromItem(it1);
1086
v.setRootIndex(parent1);
1087
v.setCurrentIndex(item1);
1088
QCOMPARE(v.currentIndex(), item1);
1089
QVERIFY(model.removeRows(0, 10, parent2));
1090
QCOMPARE(v.currentIndex(), parent2);
1091
QVERIFY(model.removeRows(0, 15, parent1));
1092
QCOMPARE(v.currentIndex(), QModelIndex());
1095
void tst_QAbstractItemView::setCurrentIndex_data()
1097
QTest::addColumn<QString>("viewType");
1098
QTest::addColumn<int>("itemFlags");
1099
QTest::addColumn<bool>("result");
1101
QStringList widgets;
1102
widgets << "QListView" << "QTreeView" << "QHeaderView" << "QTableView";
1104
foreach(QString widget, widgets) {
1105
QTest::newRow((widget+QLatin1String(": no flags")).toLocal8Bit().constData())
1106
<< widget << (int)0 << false;
1107
QTest::newRow((widget+QLatin1String(": checkable")).toLocal8Bit().constData())
1108
<< widget << (int)Qt::ItemIsUserCheckable << false;
1109
QTest::newRow((widget+QLatin1String(": selectable")).toLocal8Bit().constData())
1110
<< widget << (int)Qt::ItemIsSelectable << false;
1111
QTest::newRow((widget+QLatin1String(": enabled")).toLocal8Bit().constData())
1112
<< widget << (int)Qt::ItemIsEnabled << true;
1113
QTest::newRow((widget+QLatin1String(": enabled|selectable")).toLocal8Bit().constData())
1114
<< widget << (int)(Qt::ItemIsSelectable|Qt::ItemIsEnabled) << true;
1118
void tst_QAbstractItemView::setCurrentIndex()
1120
QFETCH(QString, viewType);
1121
QFETCH(int, itemFlags);
1122
QFETCH(bool, result);
1125
if (viewType == "QListView")
1126
view = reinterpret_cast<TestView*>(new QListView());
1127
else if (viewType == "QTableView")
1128
view = reinterpret_cast<TestView*>(new QTableView());
1129
else if (viewType == "QTreeView")
1130
view = reinterpret_cast<TestView*>(new QTreeView());
1131
else if (viewType == "QHeaderView")
1132
view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical));
1137
QStandardItemModel *model = new QStandardItemModel(view);
1138
QStandardItem *item = new QStandardItem("first item");
1139
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
1140
model->appendRow(item);
1142
item = new QStandardItem("test item");
1143
item->setFlags(Qt::ItemFlags(itemFlags));
1144
model->appendRow(item);
1146
view->setModel(model);
1148
view->setCurrentIndex(model->index(0,0));
1149
QVERIFY(view->currentIndex() == model->index(0,0));
1150
view->setCurrentIndex(model->index(1,0));
1151
QVERIFY(view->currentIndex() == model->index(result ? 1 : 0,0));
1156
void tst_QAbstractItemView::task221955_selectedEditor()
1158
QPushButton *button;
1161
tree.setColumnCount(2);
1163
tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Foo" <<"1"));
1164
tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Bar" <<"2"));
1165
tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Baz" <<"3"));
1167
QTreeWidgetItem *dummy = new QTreeWidgetItem();
1168
tree.addTopLevelItem(dummy);
1169
tree.setItemWidget(dummy, 0, button = new QPushButton("More..."));
1170
button->setAutoFillBackground(true); // as recommended in doc
1174
tree.setCurrentIndex(tree.model()->index(1,0));
1176
QApplication::setActiveWindow(&tree);
1178
QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
1180
//We set the focus to the button, the index need to be selected
1183
QVERIFY(tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
1185
tree.setCurrentIndex(tree.model()->index(1,0));
1186
QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0)));
1188
//Same thing but with the flag NoSelection, nothing can be selected.
1190
tree.setSelectionMode(QAbstractItemView::NoSelection);
1191
tree.clearSelection();
1192
QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty());
1196
QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty());
1199
void tst_QAbstractItemView::task250754_fontChange()
1201
QString app_css = qApp->styleSheet();
1202
qApp->setStyleSheet("/* */");
1206
QVBoxLayout *vLayout = new QVBoxLayout(&w);
1207
vLayout->addWidget(&tree);
1209
QStandardItemModel *m = new QStandardItemModel(this);
1210
for (int i=0; i<5; ++i) {
1211
QStandardItem *item = new QStandardItem(QString("Item number %1").arg(i));
1212
for (int j=0; j<5; ++j) {
1213
QStandardItem *child = new QStandardItem(QString("Child Item number %1").arg(j));
1214
item->setChild(j, 0, child);
1216
m->setItem(i, 0, item);
1223
QFont font = tree.font();
1224
font.setPixelSize(10);
1226
QTRY_VERIFY(!tree.verticalScrollBar()->isVisible());
1228
font.setPixelSize(60);
1230
//now with the huge items, the scrollbar must be visible
1231
QTRY_VERIFY(tree.verticalScrollBar()->isVisible());
1233
qApp->setStyleSheet(app_css);
1236
void tst_QAbstractItemView::task200665_itemEntered()
1238
#ifdef Q_OS_WINCE_WM
1239
QSKIP("On Windows Mobile the mouse tracking is unavailable at the moment");
1241
//we test that view will emit entered
1242
//when the scrollbar move but not the mouse itself
1243
QStandardItemModel model(1000,1);
1245
view.setModel(&model);
1248
QRect rect = view.visualRect(model.index(0,0));
1249
QCursor::setPos( view.viewport()->mapToGlobal(rect.center()) );
1250
QSignalSpy spy(&view, SIGNAL(entered(QModelIndex)));
1251
view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
1253
QCOMPARE(spy.count(), 1);
1256
void tst_QAbstractItemView::task257481_emptyEditor()
1258
QIcon icon = qApp->style()->standardIcon(QStyle::SP_ComputerIcon);
1260
QStandardItemModel model;
1262
model.appendRow( new QStandardItem(icon, QString()) );
1263
model.appendRow( new QStandardItem(icon, "Editor works") );
1264
model.appendRow( new QStandardItem( QString() ) );
1267
treeView.setRootIsDecorated(false);
1268
treeView.setModel(&model);
1271
treeView.edit(model.index(0,0));
1272
QList<QLineEdit *> lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
1273
QCOMPARE(lineEditors.count(), 1);
1274
QVERIFY(!lineEditors.first()->size().isEmpty());
1278
treeView.edit(model.index(1,0));
1279
lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
1280
QCOMPARE(lineEditors.count(), 1);
1281
QVERIFY(!lineEditors.first()->size().isEmpty());
1285
treeView.edit(model.index(2,0));
1286
lineEditors = qFindChildren<QLineEdit *>(treeView.viewport());
1287
QCOMPARE(lineEditors.count(), 1);
1288
QVERIFY(!lineEditors.first()->size().isEmpty());
1291
void tst_QAbstractItemView::shiftArrowSelectionAfterScrolling()
1293
QStandardItemModel model;
1294
for (int i=0; i<10; ++i) {
1295
QStandardItem *item = new QStandardItem(QString("%1").arg(i));
1296
model.setItem(i, 0, item);
1300
view.setFixedSize(150, 250);
1301
view.setFlow(QListView::LeftToRight);
1302
view.setGridSize(QSize(100, 100));
1303
view.setSelectionMode(QListView::ExtendedSelection);
1304
view.setViewMode(QListView::IconMode);
1305
view.setModel(&model);
1309
QModelIndex index0 = model.index(0, 0);
1310
QModelIndex index1 = model.index(1, 0);
1311
QModelIndex index9 = model.index(9, 0);
1313
view.selectionModel()->setCurrentIndex(index0, QItemSelectionModel::NoUpdate);
1314
QCOMPARE(view.currentIndex(), index0);
1316
view.scrollTo(index9);
1317
QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
1319
QCOMPARE(view.currentIndex(), index1);
1320
QModelIndexList selected = view.selectionModel()->selectedIndexes();
1321
QCOMPARE(selected.count(), 2);
1322
QVERIFY(selected.contains(index0));
1323
QVERIFY(selected.contains(index1));
1326
void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection()
1328
QStandardItemModel model;
1329
for (int i=0; i<3; ++i) {
1330
QStandardItem *item = new QStandardItem(QString("%1").arg(i));
1331
model.setItem(i, 0, item);
1335
view.setFixedSize(150, 450);
1336
view.setFlow(QListView::LeftToRight);
1337
view.setGridSize(QSize(100, 100));
1338
view.setSelectionMode(QListView::ExtendedSelection);
1339
view.setViewMode(QListView::IconMode);
1340
view.setModel(&model);
1344
QModelIndex index0 = model.index(0, 0);
1345
QModelIndex index1 = model.index(1, 0);
1346
QModelIndex index2 = model.index(2, 0);
1348
view.setCurrentIndex(index0);
1349
QCOMPARE(view.currentIndex(), index0);
1351
// Determine the points where the rubberband selection starts and ends
1352
QPoint pressPos = view.visualRect(index1).bottomRight() + QPoint(1, 1);
1353
QPoint releasePos = view.visualRect(index1).center();
1354
QVERIFY(!view.indexAt(pressPos).isValid());
1355
QCOMPARE(view.indexAt(releasePos), index1);
1357
// Select item 1 using a rubberband selection
1358
// The mouse move event has to be created manually because the QTest framework does not
1359
// contain a function for mouse moves with buttons pressed
1360
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos);
1361
QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
1362
bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
1363
QVERIFY(moveEventReceived);
1364
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos);
1365
QCOMPARE(view.currentIndex(), index1);
1367
// Shift-click item 2
1368
QPoint item2Pos = view.visualRect(index2).center();
1369
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, item2Pos);
1370
QCOMPARE(view.currentIndex(), index2);
1372
// Verify that the selection worked OK
1373
QModelIndexList selected = view.selectionModel()->selectedIndexes();
1374
QCOMPARE(selected.count(), 2);
1375
QVERIFY(selected.contains(index1));
1376
QVERIFY(selected.contains(index2));
1378
// Select item 0 to revert the selection
1379
view.setCurrentIndex(index0);
1380
QCOMPARE(view.currentIndex(), index0);
1382
// Repeat the same steps as above, but with a Shift-Arrow selection
1383
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos);
1384
QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
1385
moveEventReceived = qApp->notify(view.viewport(), &moveEvent2);
1386
QVERIFY(moveEventReceived);
1387
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos);
1388
QCOMPARE(view.currentIndex(), index1);
1391
QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier);
1392
QCOMPARE(view.currentIndex(), index2);
1394
// Verify that the selection worked OK
1395
selected = view.selectionModel()->selectedIndexes();
1396
QCOMPARE(selected.count(), 2);
1397
QVERIFY(selected.contains(index1));
1398
QVERIFY(selected.contains(index2));
1401
void tst_QAbstractItemView::ctrlRubberbandSelection()
1403
QStandardItemModel model;
1404
for (int i=0; i<3; ++i) {
1405
QStandardItem *item = new QStandardItem(QString("%1").arg(i));
1406
model.setItem(i, 0, item);
1410
view.setFixedSize(150, 450);
1411
view.setFlow(QListView::LeftToRight);
1412
view.setGridSize(QSize(100, 100));
1413
view.setSelectionMode(QListView::ExtendedSelection);
1414
view.setViewMode(QListView::IconMode);
1415
view.setModel(&model);
1419
QModelIndex index1 = model.index(1, 0);
1420
QModelIndex index2 = model.index(2, 0);
1423
view.setCurrentIndex(index1);
1424
QModelIndexList selected = view.selectionModel()->selectedIndexes();
1425
QCOMPARE(selected.count(), 1);
1426
QVERIFY(selected.contains(index1));
1428
// Now press control and draw a rubberband around items 1 and 2.
1429
// The mouse move event has to be created manually because the QTest framework does not
1430
// contain a function for mouse moves with buttons pressed.
1431
QPoint pressPos = view.visualRect(index1).topLeft() - QPoint(1, 1);
1432
QPoint releasePos = view.visualRect(index2).bottomRight() + QPoint(1, 1);
1433
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pressPos);
1434
QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
1435
bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
1436
QVERIFY(moveEventReceived);
1437
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, releasePos);
1439
// Verify that item 2 is selected now
1440
selected = view.selectionModel()->selectedIndexes();
1441
QCOMPARE(selected.count(), 1);
1442
QVERIFY(selected.contains(index2));
1445
void tst_QAbstractItemView::QTBUG6407_extendedSelection()
1448
view.setSelectionMode(QAbstractItemView::ExtendedSelection);
1449
for(int i = 0; i < 50; ++i)
1450
view.addItem(QString::number(i));
1452
QFont font = view.font();
1453
font.setPixelSize(10);
1455
view.resize(200,240);
1458
QApplication::setActiveWindow(&view);
1459
QVERIFY(QTest::qWaitForWindowActive(&view));
1460
QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow());
1462
view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
1465
QModelIndex index49 = view.model()->index(49,0);
1466
QPoint p = view.visualRect(index49).center();
1467
QVERIFY(view.viewport()->rect().contains(p));
1468
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
1469
QCOMPARE(view.currentIndex(), index49);
1470
QCOMPARE(view.selectedItems().count(), 1);
1472
QModelIndex index47 = view.model()->index(47,0);
1473
p = view.visualRect(index47).center();
1474
QVERIFY(view.viewport()->rect().contains(p));
1475
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p);
1476
QCOMPARE(view.currentIndex(), index47);
1477
QCOMPARE(view.selectedItems().count(), 3); //49, 48, 47;
1479
QModelIndex index44 = view.model()->index(44,0);
1480
p = view.visualRect(index44).center();
1481
QVERIFY(view.viewport()->rect().contains(p));
1482
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p);
1483
QCOMPARE(view.currentIndex(), index44);
1484
QCOMPARE(view.selectedItems().count(), 6); //49 .. 44;
1488
void tst_QAbstractItemView::QTBUG6753_selectOnSelection()
1490
QTableWidget table(5, 5);
1491
for (int i = 0; i < table.rowCount(); ++i)
1492
for (int j = 0; j < table.columnCount(); ++j)
1493
table.setItem(i, j, new QTableWidgetItem("choo-be-doo-wah"));
1496
table.setSelectionMode(QAbstractItemView::ExtendedSelection);
1498
QVERIFY(QTest::qWaitForWindowExposed(&table));
1499
QModelIndex item = table.model()->index(1,1);
1500
QRect itemRect = table.visualRect(item);
1501
QTest::mouseMove(table.viewport(), itemRect.center());
1502
QTest::mouseClick(table.viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center());
1505
QCOMPARE(table.selectedItems().count(), 1);
1506
QCOMPARE(table.selectedItems().first(), table.item(item.row(), item.column()));
1509
void tst_QAbstractItemView::testDelegateDestroyEditor()
1511
QTableWidget table(5, 5);
1512
MyAbstractItemDelegate delegate;
1513
table.setItemDelegate(&delegate);
1514
table.edit(table.model()->index(1, 1));
1515
TestView *tv = reinterpret_cast<TestView*>(&table);
1516
QVERIFY(!delegate.calledVirtualDtor);
1517
tv->tst_closeEditor(delegate.openedEditor, QAbstractItemDelegate::NoHint);
1518
QVERIFY(delegate.calledVirtualDtor);
1521
void tst_QAbstractItemView::testClickedSignal()
1523
QTableWidget view(5, 5);
1526
QApplication::setActiveWindow(&view);
1527
QVERIFY(QTest::qWaitForWindowActive(&view));
1528
QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow());
1530
QModelIndex index49 = view.model()->index(49,0);
1531
QPoint p = view.visualRect(index49).center();
1532
QVERIFY(view.viewport()->rect().contains(p));
1534
QSignalSpy clickedSpy(&view, SIGNAL(clicked(QModelIndex)));
1536
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
1537
QCOMPARE(clickedSpy.count(), 1);
1539
QTest::mouseClick(view.viewport(), Qt::RightButton, 0, p);
1540
// We expect that right-clicks do not cause the clicked() signal to
1542
QCOMPARE(clickedSpy.count(), 1);
1546
class StateChangeDelegate : public QItemDelegate {
1550
explicit StateChangeDelegate(QObject* parent = 0) :
1551
QItemDelegate(parent)
1554
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE {
1556
static bool w = true;
1557
editor->setEnabled(w);
1562
class StateChangeModel : public QStandardItemModel {
1566
explicit StateChangeModel(QObject *parent = 0) :
1567
QStandardItemModel(parent)
1570
void emitDataChanged() {
1571
emit dataChanged(index(0, 0), index(0, 1));
1576
void tst_QAbstractItemView::testChangeEditorState()
1578
// Test for QTBUG-25370
1579
StateChangeModel model;
1581
QStandardItem* item = new QStandardItem("a");
1582
model.setItem(0, 0, item);
1585
QStandardItem* item = new QStandardItem("b");
1586
model.setItem(0, 1, item);
1590
view.setEditTriggers(QAbstractItemView::CurrentChanged);
1591
view.setItemDelegate(new StateChangeDelegate);
1592
view.setModel(&model);
1594
QApplication::setActiveWindow(&view);
1595
QVERIFY(QTest::qWaitForWindowActive(&view));
1596
QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow());
1598
model.emitDataChanged();
1599
// No segfault - the test passes.
1602
QTEST_MAIN(tst_QAbstractItemView)
1603
#include "tst_qabstractitemview.moc"