From 9f1aa866bda7678261f2f441d4cfd5bb524c2411 Mon Sep 17 00:00:00 2001 From: Jo Asplin Date: Thu, 20 Oct 2011 13:17:26 +0200 Subject: Moved tests into integrationtests/ and widgets/ Task-number: QTBUG-19013 Change-Id: Ibb776f5967c0645ce6d22ef7afdc40657c575461 Reviewed-by: Holger Ihrig --- .../widgets/itemviews/qabstractitemview/.gitignore | 1 + .../qabstractitemview/qabstractitemview.pro | 3 + .../qabstractitemview/tst_qabstractitemview.cpp | 1504 ++++++++++++++++++++ 3 files changed, 1508 insertions(+) create mode 100644 tests/auto/widgets/itemviews/qabstractitemview/.gitignore create mode 100644 tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro create mode 100644 tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp (limited to 'tests/auto/widgets/itemviews/qabstractitemview') diff --git a/tests/auto/widgets/itemviews/qabstractitemview/.gitignore b/tests/auto/widgets/itemviews/qabstractitemview/.gitignore new file mode 100644 index 0000000000..2f9f90e27e --- /dev/null +++ b/tests/auto/widgets/itemviews/qabstractitemview/.gitignore @@ -0,0 +1 @@ +tst_qabstractitemview diff --git a/tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro b/tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro new file mode 100644 index 0000000000..7f6c2cb65c --- /dev/null +++ b/tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_qabstractitemview.cpp diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp new file mode 100644 index 0000000000..b9c652f1d3 --- /dev/null +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -0,0 +1,1504 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +// Will try to wait for the condition while allowing event processing +// for a maximum of 5 seconds. +#define TRY_COMPARE(expr, expected) \ + do { \ + const int step = 50; \ + for (int q = 0; q < 5000 && ((expr) != (expected)); q+=step) { \ + QTest::qWait(step); \ + } \ + QCOMPARE(expr, expected); \ + } while(0) + +class TestView : public QAbstractItemView +{ + Q_OBJECT +public: + inline void tst_dataChanged(const QModelIndex &tl, const QModelIndex &br) + { dataChanged(tl, br); } + inline void tst_setHorizontalStepsPerItem(int steps) + { setHorizontalStepsPerItem(steps); } + inline int tst_horizontalStepsPerItem() const + { return horizontalStepsPerItem(); } + inline void tst_setVerticalStepsPerItem(int steps) + { setVerticalStepsPerItem(steps); } + inline int tst_verticalStepsPerItem() const + { return verticalStepsPerItem(); } + + inline void tst_rowsInserted(const QModelIndex &parent, int start, int end) + { rowsInserted(parent, start, end); } + inline void tst_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) + { rowsAboutToBeRemoved(parent, start, end); } + inline void tst_selectionChanged(const QItemSelection &selected, + const QItemSelection &deselected) + { selectionChanged(selected, deselected); } + inline void tst_currentChanged(const QModelIndex ¤t, const QModelIndex &previous) + { currentChanged(current, previous); } + inline void tst_updateEditorData() + { updateEditorData(); } + inline void tst_updateEditorGeometries() + { updateEditorGeometries(); } + inline void tst_updateGeometries() + { updateGeometries(); } + inline void tst_verticalScrollbarAction(int action) + { verticalScrollbarAction(action); } + inline void tst_horizontalScrollbarAction(int action) + { horizontalScrollbarAction(action); } + inline void tst_verticalScrollbarValueChanged(int value) + { verticalScrollbarValueChanged(value); } + inline void tst_horizontalScrollbarValueChanged(int value) + { horizontalScrollbarValueChanged(value); } + inline void tst_closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint) + { closeEditor(editor, hint); } + inline void tst_commitData(QWidget *editor) + { commitData(editor); } + inline void tst_editorDestroyed(QObject *editor) + { editorDestroyed(editor); } + enum tst_CursorAction { + MoveUp = QAbstractItemView::MoveUp, + MoveDown = QAbstractItemView::MoveDown, + MoveLeft = QAbstractItemView::MoveLeft, + MoveRight = QAbstractItemView::MoveRight, + MoveHome = QAbstractItemView::MoveHome, + MoveEnd = QAbstractItemView::MoveEnd, + MovePageUp = QAbstractItemView::MovePageUp, + MovePageDown = QAbstractItemView::MovePageDown, + MoveNext = QAbstractItemView::MoveNext, + MovePrevious = QAbstractItemView::MovePrevious + }; + inline QModelIndex tst_moveCursor(tst_CursorAction cursorAction, + Qt::KeyboardModifiers modifiers) + { return moveCursor(QAbstractItemView::CursorAction(cursorAction), modifiers); } + inline int tst_horizontalOffset() const + { return horizontalOffset(); } + inline int tst_verticalOffset() const + { return verticalOffset(); } + inline bool tst_isIndexHidden(const QModelIndex &index) const + { return isIndexHidden(index); } + inline void tst_setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) + { setSelection(rect, command); } + inline QRegion tst_visualRegionForSelection(const QItemSelection &selection) const + { return visualRegionForSelection(selection); } + inline QModelIndexList tst_selectedIndexes() const + { return selectedIndexes(); } + inline bool tst_edit(const QModelIndex &index, EditTrigger trigger, QEvent *event) + { return edit(index, trigger, event); } + inline QItemSelectionModel::SelectionFlags tst_selectionCommand(const QModelIndex &index, + const QEvent *event = 0) const + { return selectionCommand(index, event); } +#ifndef QT_NO_DRAGANDDROP + inline void tst_startDrag(Qt::DropActions supportedActions) + { startDrag(supportedActions); } +#endif + inline QStyleOptionViewItem tst_viewOptions() const + { return viewOptions(); } + enum tst_State { + NoState = QAbstractItemView::NoState, + DraggingState = QAbstractItemView::DraggingState, + DragSelectingState = QAbstractItemView::DragSelectingState, + EditingState = QAbstractItemView::EditingState, + ExpandingState = QAbstractItemView::ExpandingState, + CollapsingState = QAbstractItemView::CollapsingState + }; + inline tst_State tst_state() const + { return (tst_State)state(); } + inline void tst_setState(tst_State state) + { setState(QAbstractItemView::State(state)); } + inline void tst_startAutoScroll() + { startAutoScroll(); } + inline void tst_stopAutoScroll() + { stopAutoScroll(); } + inline void tst_doAutoScroll() + { doAutoScroll(); } +}; + +class tst_QAbstractItemView : public QObject +{ + Q_OBJECT + +public: + + tst_QAbstractItemView(); + virtual ~tst_QAbstractItemView(); + void basic_tests(TestView *view); + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void getSetCheck(); + void emptyModels_data(); + void emptyModels(); + void setModel_data(); + void setModel(); + void noModel(); + void dragSelect(); + void rowDelegate(); + void columnDelegate(); + void selectAll(); + void ctrlA(); + void persistentEditorFocus(); + void setItemDelegate(); + void setItemDelegate_data(); + // The dragAndDrop() test doesn't work, and is thus disabled on Mac and Windows + // for the following reasons: + // Mac: use of GetCurrentEventButtonState() in QDragManager::drag() + // Win: unknown reason +#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) +#if 0 + void dragAndDrop(); + void dragAndDropOnChild(); +#endif +#endif + void noFallbackToRoot(); + void setCurrentIndex_data(); + void setCurrentIndex(); + + void task221955_selectedEditor(); + void task250754_fontChange(); + void task200665_itemEntered(); + void task257481_emptyEditor(); + void shiftArrowSelectionAfterScrolling(); + void shiftSelectionAfterRubberbandSelection(); + void ctrlRubberbandSelection(); + void QTBUG6407_extendedSelection(); + void QTBUG6753_selectOnSelection(); +}; + +class MyAbstractItemDelegate : public QAbstractItemDelegate +{ +public: + MyAbstractItemDelegate() : QAbstractItemDelegate() {}; + void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {} + QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); } + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &) const { return new QWidget(parent); } +}; + +// Testing get/set functions +void tst_QAbstractItemView::getSetCheck() +{ + QListView view; + TestView *obj1 = reinterpret_cast(&view); + // QAbstractItemDelegate * QAbstractItemView::itemDelegate() + // void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *) + MyAbstractItemDelegate *var1 = new MyAbstractItemDelegate; + obj1->setItemDelegate(var1); + QCOMPARE((QAbstractItemDelegate*)var1, obj1->itemDelegate()); + obj1->setItemDelegate((QAbstractItemDelegate *)0); + QCOMPARE((QAbstractItemDelegate *)0, obj1->itemDelegate()); + delete var1; + + // EditTriggers QAbstractItemView::editTriggers() + // void QAbstractItemView::setEditTriggers(EditTriggers) + obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers)); + QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::NoEditTriggers), obj1->editTriggers()); + obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged)); + QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::CurrentChanged), obj1->editTriggers()); + obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked)); + QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::DoubleClicked), obj1->editTriggers()); + obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked)); + QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::SelectedClicked), obj1->editTriggers()); + obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed)); + QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::EditKeyPressed), obj1->editTriggers()); + obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed)); + QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AnyKeyPressed), obj1->editTriggers()); + obj1->setEditTriggers(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers)); + QCOMPARE(QAbstractItemView::EditTriggers(QAbstractItemView::AllEditTriggers), obj1->editTriggers()); + + // bool QAbstractItemView::tabKeyNavigation() + // void QAbstractItemView::setTabKeyNavigation(bool) + obj1->setTabKeyNavigation(false); + QCOMPARE(false, obj1->tabKeyNavigation()); + obj1->setTabKeyNavigation(true); + QCOMPARE(true, obj1->tabKeyNavigation()); + + // bool QAbstractItemView::dragEnabled() + // void QAbstractItemView::setDragEnabled(bool) +#ifndef QT_NO_DRAGANDDROP + obj1->setDragEnabled(false); + QCOMPARE(false, obj1->dragEnabled()); + obj1->setDragEnabled(true); + QCOMPARE(true, obj1->dragEnabled()); +#endif + // bool QAbstractItemView::alternatingRowColors() + // void QAbstractItemView::setAlternatingRowColors(bool) + obj1->setAlternatingRowColors(false); + QCOMPARE(false, obj1->alternatingRowColors()); + obj1->setAlternatingRowColors(true); + QCOMPARE(true, obj1->alternatingRowColors()); + + // State QAbstractItemView::state() + // void QAbstractItemView::setState(State) + obj1->tst_setState(TestView::tst_State(TestView::NoState)); + QCOMPARE(TestView::tst_State(TestView::NoState), obj1->tst_state()); + obj1->tst_setState(TestView::tst_State(TestView::DraggingState)); + QCOMPARE(TestView::tst_State(TestView::DraggingState), obj1->tst_state()); + obj1->tst_setState(TestView::tst_State(TestView::DragSelectingState)); + QCOMPARE(TestView::tst_State(TestView::DragSelectingState), obj1->tst_state()); + obj1->tst_setState(TestView::tst_State(TestView::EditingState)); + QCOMPARE(TestView::tst_State(TestView::EditingState), obj1->tst_state()); + obj1->tst_setState(TestView::tst_State(TestView::ExpandingState)); + QCOMPARE(TestView::tst_State(TestView::ExpandingState), obj1->tst_state()); + obj1->tst_setState(TestView::tst_State(TestView::CollapsingState)); + QCOMPARE(TestView::tst_State(TestView::CollapsingState), obj1->tst_state()); + + // QWidget QAbstractScrollArea::viewport() + // void setViewport(QWidget*) + QWidget *vp = new QWidget; + obj1->setViewport(vp); + QCOMPARE(vp, obj1->viewport()); + + QCOMPARE(16, obj1->autoScrollMargin()); + obj1->setAutoScrollMargin(20); + QCOMPARE(20, obj1->autoScrollMargin()); + obj1->setAutoScrollMargin(16); + QCOMPARE(16, obj1->autoScrollMargin()); +} + +tst_QAbstractItemView::tst_QAbstractItemView() +{ +} + +tst_QAbstractItemView::~tst_QAbstractItemView() +{ +} + +void tst_QAbstractItemView::initTestCase() +{ +#ifdef Q_OS_WINCE_WM + qApp->setAutoMaximizeThreshold(-1); +#endif +} + +void tst_QAbstractItemView::cleanupTestCase() +{ +} + +void tst_QAbstractItemView::emptyModels_data() +{ + QTest::addColumn("viewType"); + + QTest::newRow("QListView") << "QListView"; + QTest::newRow("QTableView") << "QTableView"; + QTest::newRow("QTreeView") << "QTreeView"; + QTest::newRow("QHeaderView") << "QHeaderView"; +} + +void tst_QAbstractItemView::emptyModels() +{ + QFETCH(QString, viewType); + + TestView *view = 0; + if (viewType == "QListView") + view = reinterpret_cast(new QListView()); + else if (viewType == "QTableView") + view = reinterpret_cast(new QTableView()); + else if (viewType == "QTreeView") + view = reinterpret_cast(new QTreeView()); + else if (viewType == "QHeaderView") + view = reinterpret_cast(new QHeaderView(Qt::Vertical)); + else + QVERIFY(0); + view->show(); + + QVERIFY(!view->model()); + QVERIFY(!view->selectionModel()); + //QVERIFY(view->itemDelegate() != 0); + + basic_tests(view); + delete view; +} + +void tst_QAbstractItemView::setModel_data() +{ + QTest::addColumn("viewType"); + + QTest::newRow("QListView") << "QListView"; + QTest::newRow("QTableView") << "QTableView"; + QTest::newRow("QTreeView") << "QTreeView"; + QTest::newRow("QHeaderView") << "QHeaderView"; +} + +void tst_QAbstractItemView::setModel() +{ + QFETCH(QString, viewType); + TestView *view = 0; + if (viewType == "QListView") + view = reinterpret_cast(new QListView()); + else if (viewType == "QTableView") + view = reinterpret_cast(new QTableView()); + else if (viewType == "QTreeView") + view = reinterpret_cast(new QTreeView()); + else if (viewType == "QHeaderView") + view = reinterpret_cast(new QHeaderView(Qt::Vertical)); + else + QVERIFY(0); + view->show(); + + QStandardItemModel model(20,20); + view->setModel(0); + view->setModel(&model); + basic_tests(view); + delete view; +} + +void tst_QAbstractItemView::basic_tests(TestView *view) +{ + // setSelectionModel + // Will assert as it should + //view->setSelectionModel(0); + // setItemDelegate + //view->setItemDelegate(0); + // Will asswert as it should + + // setSelectionMode + view->setSelectionMode(QAbstractItemView::SingleSelection); + QCOMPARE(view->selectionMode(), QAbstractItemView::SingleSelection); + view->setSelectionMode(QAbstractItemView::ContiguousSelection); + QCOMPARE(view->selectionMode(), QAbstractItemView::ContiguousSelection); + view->setSelectionMode(QAbstractItemView::ExtendedSelection); + QCOMPARE(view->selectionMode(), QAbstractItemView::ExtendedSelection); + view->setSelectionMode(QAbstractItemView::MultiSelection); + QCOMPARE(view->selectionMode(), QAbstractItemView::MultiSelection); + view->setSelectionMode(QAbstractItemView::NoSelection); + QCOMPARE(view->selectionMode(), QAbstractItemView::NoSelection); + + // setSelectionBehavior + view->setSelectionBehavior(QAbstractItemView::SelectItems); + QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectItems); + view->setSelectionBehavior(QAbstractItemView::SelectRows); + QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectRows); + view->setSelectionBehavior(QAbstractItemView::SelectColumns); + QCOMPARE(view->selectionBehavior(), QAbstractItemView::SelectColumns); + + // setEditTriggers + view->setEditTriggers(QAbstractItemView::EditKeyPressed); + QCOMPARE(view->editTriggers(), QAbstractItemView::EditKeyPressed); + view->setEditTriggers(QAbstractItemView::NoEditTriggers); + QCOMPARE(view->editTriggers(), QAbstractItemView::NoEditTriggers); + view->setEditTriggers(QAbstractItemView::CurrentChanged); + QCOMPARE(view->editTriggers(), QAbstractItemView::CurrentChanged); + view->setEditTriggers(QAbstractItemView::DoubleClicked); + QCOMPARE(view->editTriggers(), QAbstractItemView::DoubleClicked); + view->setEditTriggers(QAbstractItemView::SelectedClicked); + QCOMPARE(view->editTriggers(), QAbstractItemView::SelectedClicked); + view->setEditTriggers(QAbstractItemView::AnyKeyPressed); + QCOMPARE(view->editTriggers(), QAbstractItemView::AnyKeyPressed); + view->setEditTriggers(QAbstractItemView::AllEditTriggers); + QCOMPARE(view->editTriggers(), QAbstractItemView::AllEditTriggers); + + // setAutoScroll + view->setAutoScroll(false); + QCOMPARE(view->hasAutoScroll(), false); + view->setAutoScroll(true); + QCOMPARE(view->hasAutoScroll(), true); + + // setTabKeyNavigation + view->setTabKeyNavigation(false); + QCOMPARE(view->tabKeyNavigation(), false); + view->setTabKeyNavigation(true); + QCOMPARE(view->tabKeyNavigation(), true); + +#ifndef QT_NO_DRAGANDDROP + // setDropIndicatorShown + view->setDropIndicatorShown(false); + QCOMPARE(view->showDropIndicator(), false); + view->setDropIndicatorShown(true); + QCOMPARE(view->showDropIndicator(), true); + + // setDragEnabled + view->setDragEnabled(false); + QCOMPARE(view->dragEnabled(), false); + view->setDragEnabled(true); + QCOMPARE(view->dragEnabled(), true); +#endif + + // setAlternatingRowColors + view->setAlternatingRowColors(false); + QCOMPARE(view->alternatingRowColors(), false); + view->setAlternatingRowColors(true); + QCOMPARE(view->alternatingRowColors(), true); + + // setIconSize + view->setIconSize(QSize(16, 16)); + QCOMPARE(view->iconSize(), QSize(16, 16)); + view->setIconSize(QSize(32, 32)); + QCOMPARE(view->iconSize(), QSize(32, 32)); + // Should this happen? + view->setIconSize(QSize(-1, -1)); + QCOMPARE(view->iconSize(), QSize(-1, -1)); + + QCOMPARE(view->currentIndex(), QModelIndex()); + QCOMPARE(view->rootIndex(), QModelIndex()); + + view->keyboardSearch(""); + view->keyboardSearch("foo"); + view->keyboardSearch("1"); + + QCOMPARE(view->visualRect(QModelIndex()), QRect()); + + view->scrollTo(QModelIndex()); + + QCOMPARE(view->sizeHintForIndex(QModelIndex()), QSize()); + QCOMPARE(view->indexAt(QPoint(-1, -1)), QModelIndex()); + + if (!view->model()){ + QCOMPARE(view->indexAt(QPoint(10, 10)), QModelIndex()); + QCOMPARE(view->sizeHintForRow(0), -1); + QCOMPARE(view->sizeHintForColumn(0), -1); + }else if (view->itemDelegate()){ + view->sizeHintForRow(0); + view->sizeHintForColumn(0); + } + view->openPersistentEditor(QModelIndex()); + view->closePersistentEditor(QModelIndex()); + + view->reset(); + view->setRootIndex(QModelIndex()); + view->doItemsLayout(); + view->selectAll(); + view->edit(QModelIndex()); + view->clearSelection(); + view->setCurrentIndex(QModelIndex()); + + // protected methods + view->tst_dataChanged(QModelIndex(), QModelIndex()); + view->tst_rowsInserted(QModelIndex(), -1, -1); + view->tst_rowsAboutToBeRemoved(QModelIndex(), -1, -1); + view->tst_selectionChanged(QItemSelection(), QItemSelection()); + if (view->model()){ + view->tst_currentChanged(QModelIndex(), QModelIndex()); + view->tst_currentChanged(QModelIndex(), view->model()->index(0,0)); + } + view->tst_updateEditorData(); + view->tst_updateEditorGeometries(); + view->tst_updateGeometries(); + view->tst_verticalScrollbarAction(QAbstractSlider::SliderSingleStepAdd); + view->tst_horizontalScrollbarAction(QAbstractSlider::SliderSingleStepAdd); + view->tst_verticalScrollbarValueChanged(10); + view->tst_horizontalScrollbarValueChanged(10); + view->tst_closeEditor(0, QAbstractItemDelegate::NoHint); + view->tst_commitData(0); + view->tst_editorDestroyed(0); + + view->tst_setHorizontalStepsPerItem(2); + view->tst_horizontalStepsPerItem(); + view->tst_setVerticalStepsPerItem(2); + view->tst_verticalStepsPerItem(); + + // Will assert as it should + // view->setIndexWidget(QModelIndex(), 0); + + view->tst_moveCursor(TestView::MoveUp, Qt::NoModifier); + view->tst_horizontalOffset(); + view->tst_verticalOffset(); + +// view->tst_isIndexHidden(QModelIndex()); // will (correctly) assert + if(view->model()) + view->tst_isIndexHidden(view->model()->index(0,0)); + + view->tst_setSelection(QRect(0, 0, 10, 10), QItemSelectionModel::ClearAndSelect); + view->tst_setSelection(QRect(-1, -1, -1, -1), QItemSelectionModel::ClearAndSelect); + view->tst_visualRegionForSelection(QItemSelection()); + view->tst_selectedIndexes(); + + view->tst_edit(QModelIndex(), QAbstractItemView::NoEditTriggers, 0); + + view->tst_selectionCommand(QModelIndex(), 0); + +#ifndef QT_NO_DRAGANDDROP + if (!view->model()) + view->tst_startDrag(Qt::CopyAction); + + view->tst_viewOptions(); + + view->tst_setState(TestView::NoState); + QVERIFY(view->tst_state()==TestView::NoState); + view->tst_setState(TestView::DraggingState); + QVERIFY(view->tst_state()==TestView::DraggingState); + view->tst_setState(TestView::DragSelectingState); + QVERIFY(view->tst_state()==TestView::DragSelectingState); + view->tst_setState(TestView::EditingState); + QVERIFY(view->tst_state()==TestView::EditingState); + view->tst_setState(TestView::ExpandingState); + QVERIFY(view->tst_state()==TestView::ExpandingState); + view->tst_setState(TestView::CollapsingState); + QVERIFY(view->tst_state()==TestView::CollapsingState); +#endif + + view->tst_startAutoScroll(); + view->tst_stopAutoScroll(); + view->tst_doAutoScroll(); + + // testing mouseFoo and key functions +// QTest::mousePress(view, Qt::LeftButton, Qt::NoModifier, QPoint(0,0)); +// mouseMove(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10)); +// QTest::mouseRelease(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10)); +// QTest::mouseClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10)); +// mouseDClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(10,10)); +// QTest::keyClick(view, Qt::Key_A); +} + +void tst_QAbstractItemView::noModel() +{ + // From task #85415 + + QStandardItemModel model(20,20); + QTreeView view; + + view.setModel(&model); + // Make the viewport smaller than the contents, so that we can scroll + view.resize(100,100); + view.show(); + + // make sure that the scrollbars are not at value 0 + view.scrollTo(view.model()->index(10,10)); + QApplication::processEvents(); + + view.setModel(0); + // Due to the model is removed, this will generate a valueChanged signal on both scrollbars. (value to 0) + QApplication::processEvents(); + QCOMPARE(view.model(), (QAbstractItemModel*)0); +} + +void tst_QAbstractItemView::dragSelect() +{ + // From task #86108 + + QStandardItemModel model(64,64); + + QTableView view; + view.setModel(&model); + view.setVisible(true); + + const int delay = 2; + for (int i = 0; i < 2; ++i) { + bool tracking = (i == 1); + view.setMouseTracking(false); + QTest::mouseMove(&view, QPoint(0, 0), delay); + view.setMouseTracking(tracking); + QTest::mouseMove(&view, QPoint(50, 50), delay); + QVERIFY(view.selectionModel()->selectedIndexes().isEmpty()); + } +} + +void tst_QAbstractItemView::rowDelegate() +{ + QStandardItemModel model(4,4); + MyAbstractItemDelegate delegate; + + QTableView view; + view.setModel(&model); + view.setItemDelegateForRow(3, &delegate); + view.show(); + + QModelIndex index = model.index(3, 0); + view.openPersistentEditor(index); + QWidget *w = view.indexWidget(index); + QVERIFY(w); + QCOMPARE(w->metaObject()->className(), "QWidget"); +} + +void tst_QAbstractItemView::columnDelegate() +{ + QStandardItemModel model(4,4); + MyAbstractItemDelegate delegate; + + QTableView view; + view.setModel(&model); + view.setItemDelegateForColumn(3, &delegate); + view.show(); + + QModelIndex index = model.index(0, 3); + view.openPersistentEditor(index); + QWidget *w = view.indexWidget(index); + QVERIFY(w); + QCOMPARE(w->metaObject()->className(), "QWidget"); +} + +void tst_QAbstractItemView::selectAll() +{ + QStandardItemModel model(4,4); + QTableView view; + view.setModel(&model); + + TestView *tst_view = (TestView*)&view; + + QCOMPARE(tst_view->tst_selectedIndexes().count(), 0); + view.selectAll(); + QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4); +} + +void tst_QAbstractItemView::ctrlA() +{ + QStandardItemModel model(4,4); + QTableView view; + view.setModel(&model); + + TestView *tst_view = (TestView*)&view; + + QCOMPARE(tst_view->tst_selectedIndexes().count(), 0); + QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier); + QCOMPARE(tst_view->tst_selectedIndexes().count(), 4*4); +} + +void tst_QAbstractItemView::persistentEditorFocus() +{ + // one row, three columns + QStandardItemModel model(1, 3); + for(int i = 0; i < model.columnCount(); ++i) + model.setData(model.index(0, i), i); + QTableView view; + view.setModel(&model); + + view.openPersistentEditor(model.index(0, 1)); + view.openPersistentEditor(model.index(0, 2)); + + //these are spinboxes because we put numbers inside + QList list = qFindChildren(view.viewport()); + QCOMPARE(list.count(), 2); //these should be the 2 editors + + view.setCurrentIndex(model.index(0, 0)); + QCOMPARE(view.currentIndex(), model.index(0, 0)); + view.show(); + QTRY_VERIFY(view.isVisible()); + + for (int i = 0; i < list.count(); ++i) { + TRY_COMPARE(list.at(i)->isVisible(), true); + QPoint p = QPoint(5, 5); + QMouseEvent mouseEvent(QEvent::MouseButtonPress, p, Qt::LeftButton, + Qt::LeftButton, Qt::NoModifier); + qApp->sendEvent(list.at(i), &mouseEvent); + if (!qApp->focusWidget()) + QSKIP("Some window managers don't handle focus that well", SkipAll); + QTRY_COMPARE(qApp->focusWidget(), static_cast(list.at(i))); + } +} + + +#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) + +#if 0 + +static void sendMouseMove(QWidget *widget, QPoint pos = QPoint()) +{ + if (pos.isNull()) + pos = widget->rect().center(); + QMouseEvent event(QEvent::MouseMove, pos, widget->mapToGlobal(pos), Qt::NoButton, 0, 0); + QCursor::setPos(widget->mapToGlobal(pos)); + qApp->processEvents(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(widget); +#endif + QApplication::sendEvent(widget, &event); +} + +static void sendMousePress( + QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton) +{ + if (pos.isNull()) + pos = widget->rect().center(); + QMouseEvent event(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, 0, 0); + QApplication::sendEvent(widget, &event); +} + +static void sendMouseRelease( + QWidget *widget, QPoint pos = QPoint(), Qt::MouseButton button = Qt::LeftButton) +{ + if (pos.isNull()) + pos = widget->rect().center(); + QMouseEvent event(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, 0, 0); + QApplication::sendEvent(widget, &event); +} + +class DnDTestModel : public QStandardItemModel +{ + Q_OBJECT + bool dropMimeData(const QMimeData *md, Qt::DropAction action, int r, int c, const QModelIndex &p) + { + dropAction_result = action; + QStandardItemModel::dropMimeData(md, action, r, c, p); + return true; + } + Qt::DropActions supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } + + Qt::DropAction dropAction_result; +public: + DnDTestModel() : QStandardItemModel(20, 20), dropAction_result(Qt::IgnoreAction) { + for (int i = 0; i < rowCount(); ++i) + setData(index(i, 0), QString("%1").arg(i)); + } + Qt::DropAction dropAction() const { return dropAction_result; } +}; + +class DnDTestView : public QTreeView +{ + Q_OBJECT + + QPoint dropPoint; + Qt::DropAction dropAction; + + void dragEnterEvent(QDragEnterEvent *event) + { + QAbstractItemView::dragEnterEvent(event); + } + + void dropEvent(QDropEvent *event) + { + event->setDropAction(dropAction); + QTreeView::dropEvent(event); + } + + void timerEvent(QTimerEvent *event) + { + killTimer(event->timerId()); + sendMouseMove(this, dropPoint); + sendMouseRelease(this); + } + + void mousePressEvent(QMouseEvent *e) + { + QTreeView::mousePressEvent(e); + + startTimer(0); + setState(DraggingState); + startDrag(dropAction); + } + +public: + DnDTestView(Qt::DropAction dropAction, QAbstractItemModel *model) + : dropAction(dropAction) + { + header()->hide(); + setModel(model); + setDragDropMode(QAbstractItemView::DragDrop); + setAcceptDrops(true); + setDragEnabled(true); + } + + void dragAndDrop(QPoint drag, QPoint drop) + { + dropPoint = drop; + setCurrentIndex(indexAt(drag)); + sendMousePress(viewport(), drag); + } +}; + +class DnDTestWidget : public QWidget +{ + Q_OBJECT + + Qt::DropAction dropAction_request; + Qt::DropAction dropAction_result; + QWidget *dropTarget; + + void timerEvent(QTimerEvent *event) + { + killTimer(event->timerId()); + sendMouseMove(dropTarget); + sendMouseRelease(dropTarget); + } + + void mousePressEvent(QMouseEvent *) + { + QDrag *drag = new QDrag(this); + QMimeData *mimeData = new QMimeData; + mimeData->setData("application/x-qabstractitemmodeldatalist", QByteArray("")); + drag->setMimeData(mimeData); + startTimer(0); + dropAction_result = drag->start(dropAction_request); + } + +public: + Qt::DropAction dropAction() const { return dropAction_result; } + + void dragAndDrop(QWidget *dropTarget, Qt::DropAction dropAction) + { + this->dropTarget = dropTarget; + dropAction_request = dropAction; + sendMousePress(this); + } +}; + +void tst_QAbstractItemView::dragAndDrop() +{ + // From Task 137729 + +#ifdef Q_WS_QWS + QSKIP("Embedded drag-and-drop not good enough yet...", SkipAll); +#endif + + const int attempts = 10; + int successes = 0; + for (int i = 0; i < attempts; ++i) { + Qt::DropAction dropAction = Qt::MoveAction; + + DnDTestModel model; + DnDTestView view(dropAction, &model); + DnDTestWidget widget; + + const int size = 200; + widget.setFixedSize(size, size); + view.setFixedSize(size, size); + + widget.move(0, 0); + view.move(int(size * 1.5), int(size * 1.5)); + + widget.show(); + view.show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&widget); + qt_x11_wait_for_window_manager(&view); +#endif + + widget.dragAndDrop(&view, dropAction); + if (model.dropAction() == dropAction + && widget.dropAction() == dropAction) + ++successes; + } + + if (successes < attempts) { + QString msg = QString("# successes (%1) < # attempts (%2)").arg(successes).arg(attempts); + QWARN(msg.toLatin1()); + } + QVERIFY(successes > 0); // allow for some "event unstability" (i.e. unless + // successes == 0, QAbstractItemView is probably ok!) +} + +void tst_QAbstractItemView::dragAndDropOnChild() +{ +#ifdef Q_WS_QWS + QSKIP("Embedded drag-and-drop not good enough yet...", SkipAll); +#endif + + const int attempts = 10; + int successes = 0; + for (int i = 0; i < attempts; ++i) { + Qt::DropAction dropAction = Qt::MoveAction; + + DnDTestModel model; + QModelIndex parent = model.index(0, 0); + model.insertRow(0, parent); + model.insertColumn(0, parent); + QModelIndex child = model.index(0, 0, parent); + model.setData(child, "child"); + QCOMPARE(model.rowCount(parent), 1); + DnDTestView view(dropAction, &model); + view.setExpanded(parent, true); + view.setDragDropMode(QAbstractItemView::InternalMove); + + const int size = 200; + view.setFixedSize(size, size); + view.move(int(size * 1.5), int(size * 1.5)); + view.show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&view); +#endif + + view.dragAndDrop(view.visualRect(parent).center(), + view.visualRect(child).center()); + if (model.dropAction() == dropAction) + ++successes; + } + + QVERIFY(successes == 0); +} + +#endif // 0 +#endif // !Q_OS_MAC && !Q_OS_WIN + +class TestModel : public QStandardItemModel +{ +public: + TestModel(int rows, int columns) : QStandardItemModel(rows, columns) + { + setData_count = 0; + } + + virtual bool setData(const QModelIndex &/*index*/, const QVariant &/*value*/, int /*role = Qt::EditRole*/) + { + ++setData_count; + return true; + } + + int setData_count; +}; + +typedef QList IntList; +Q_DECLARE_METATYPE(IntList) + +void tst_QAbstractItemView::setItemDelegate_data() +{ + // default is rows, a -1 will switch to columns + QTest::addColumn("rowsOrColumnsWithDelegate"); + QTest::addColumn("cellToEdit"); + QTest::newRow("4 columndelegates") + << (IntList() << -1 << 0 << 1 << 2 << 3) + << QPoint(0, 0); + QTest::newRow("2 identical rowdelegates on the same row") + << (IntList() << 0 << 0) + << QPoint(0, 0); + QTest::newRow("2 identical columndelegates on the same column") + << (IntList() << -1 << 2 << 2) + << QPoint(2, 0); + QTest::newRow("2 duplicate delegates, 1 row and 1 column") + << (IntList() << 0 << -1 << 2) + << QPoint(2, 0); + QTest::newRow("4 duplicate delegates, 2 row and 2 column") + << (IntList() << 0 << 0 << -1 << 2 << 2) + << QPoint(2, 0); + +} + +void tst_QAbstractItemView::setItemDelegate() +{ + QFETCH(IntList, rowsOrColumnsWithDelegate); + QFETCH(QPoint, cellToEdit); + QTableView v; + QItemDelegate *delegate = new QItemDelegate(&v); + TestModel model(5, 5); + v.setModel(&model); + + bool row = true; + foreach (int rc, rowsOrColumnsWithDelegate) { + if (rc == -1) { + row = !row; + } else { + if (row) { + v.setItemDelegateForRow(rc, delegate); + } else { + v.setItemDelegateForColumn(rc, delegate); + } + } + } + v.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&v); + QCursor::setPos(v.geometry().center()); + QApplication::syncX(); +#endif + QTest::qWait(20); + QApplication::setActiveWindow(&v); + + QModelIndex index = model.index(cellToEdit.y(), cellToEdit.x()); + v.edit(index); + + // This will close the editor + TRY_COMPARE(QApplication::focusWidget() == 0, false); + QWidget *editor = QApplication::focusWidget(); + QVERIFY(editor); + editor->hide(); + delete editor; + QCOMPARE(model.setData_count, 1); + delete delegate; +} + +void tst_QAbstractItemView::noFallbackToRoot() +{ + QStandardItemModel model(0, 1); + for (int i = 0; i < 5; ++i) + model.appendRow(new QStandardItem("top" + QString::number(i))); + QStandardItem *par1 = model.item(1); + for (int j = 0; j < 15; ++j) + par1->appendRow(new QStandardItem("sub" + QString::number(j))); + QStandardItem *par2 = par1->child(2); + for (int k = 0; k < 10; ++k) + par2->appendRow(new QStandardItem("bot" + QString::number(k))); + QStandardItem *it1 = par2->child(5); + + QModelIndex parent1 = model.indexFromItem(par1); + QModelIndex parent2 = model.indexFromItem(par2); + QModelIndex item1 = model.indexFromItem(it1); + + QTreeView v; + v.setModel(&model); + v.setRootIndex(parent1); + v.setCurrentIndex(item1); + QCOMPARE(v.currentIndex(), item1); + QVERIFY(model.removeRows(0, 10, parent2)); + QCOMPARE(v.currentIndex(), parent2); + QVERIFY(model.removeRows(0, 15, parent1)); + QCOMPARE(v.currentIndex(), QModelIndex()); +} + +void tst_QAbstractItemView::setCurrentIndex_data() +{ + QTest::addColumn("viewType"); + QTest::addColumn("itemFlags"); + QTest::addColumn("result"); + + QStringList widgets; + widgets << "QListView" << "QTreeView" << "QHeaderView" << "QTableView"; + + foreach(QString widget, widgets) { + QTest::newRow((widget+QLatin1String(": no flags")).toLocal8Bit().constData()) + << widget << (int)0 << false; + QTest::newRow((widget+QLatin1String(": checkable")).toLocal8Bit().constData()) + << widget << (int)Qt::ItemIsUserCheckable << false; + QTest::newRow((widget+QLatin1String(": selectable")).toLocal8Bit().constData()) + << widget << (int)Qt::ItemIsSelectable << false; + QTest::newRow((widget+QLatin1String(": enabled")).toLocal8Bit().constData()) + << widget << (int)Qt::ItemIsEnabled << true; + QTest::newRow((widget+QLatin1String(": enabled|selectable")).toLocal8Bit().constData()) + << widget << (int)(Qt::ItemIsSelectable|Qt::ItemIsEnabled) << true; + } +} + +void tst_QAbstractItemView::setCurrentIndex() +{ + QFETCH(QString, viewType); + QFETCH(int, itemFlags); + QFETCH(bool, result); + + TestView *view = 0; + if (viewType == "QListView") + view = reinterpret_cast(new QListView()); + else if (viewType == "QTableView") + view = reinterpret_cast(new QTableView()); + else if (viewType == "QTreeView") + view = reinterpret_cast(new QTreeView()); + else if (viewType == "QHeaderView") + view = reinterpret_cast(new QHeaderView(Qt::Vertical)); + else + QVERIFY(0); + view->show(); + + QStandardItemModel *model = new QStandardItemModel(view); + QStandardItem *item = new QStandardItem("first item"); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + model->appendRow(item); + + item = new QStandardItem("test item"); + item->setFlags(Qt::ItemFlags(itemFlags)); + model->appendRow(item); + + view->setModel(model); + + view->setCurrentIndex(model->index(0,0)); + QVERIFY(view->currentIndex() == model->index(0,0)); + view->setCurrentIndex(model->index(1,0)); + QVERIFY(view->currentIndex() == model->index(result ? 1 : 0,0)); + + delete view; +} + +void tst_QAbstractItemView::task221955_selectedEditor() +{ + QPushButton *button; + + QTreeWidget tree; + tree.setColumnCount(2); + + tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Foo" <<"1")); + tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Bar" <<"2")); + tree.addTopLevelItem(new QTreeWidgetItem(QStringList() << "Baz" <<"3")); + + QTreeWidgetItem *dummy = new QTreeWidgetItem(); + tree.addTopLevelItem(dummy); + tree.setItemWidget(dummy, 0, button = new QPushButton("More...")); + button->setAutoFillBackground(true); // as recommended in doc + + tree.show(); + tree.setFocus(); + tree.setCurrentIndex(tree.model()->index(1,0)); + QTest::qWait(100); + QApplication::setActiveWindow(&tree); + + QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); + + //We set the focus to the button, the index need to be selected + button->setFocus(); + QTest::qWait(100); + QVERIFY(tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); + + tree.setCurrentIndex(tree.model()->index(1,0)); + QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); + + //Same thing but with the flag NoSelection, nothing can be selected. + tree.setFocus(); + tree.setSelectionMode(QAbstractItemView::NoSelection); + tree.clearSelection(); + QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty()); + QTest::qWait(10); + button->setFocus(); + QTest::qWait(50); + QVERIFY(tree.selectionModel()->selectedIndexes().isEmpty()); +} + +void tst_QAbstractItemView::task250754_fontChange() +{ + QString app_css = qApp->styleSheet(); + qApp->setStyleSheet("/* */"); + + QWidget w; + QTreeView tree(&w); + QVBoxLayout *vLayout = new QVBoxLayout(&w); + vLayout->addWidget(&tree); + + QStandardItemModel *m = new QStandardItemModel(this); + for (int i=0; i<5; ++i) { + QStandardItem *item = new QStandardItem(QString("Item number %1").arg(i)); + for (int j=0; j<5; ++j) { + QStandardItem *child = new QStandardItem(QString("Child Item number %1").arg(j)); + item->setChild(j, 0, child); + } + m->setItem(i, 0, item); + } + tree.setModel(m); + + w.show(); + w.resize(150,240); + QTest::qWait(30); + QFont font = tree.font(); + font.setPixelSize(10); + tree.setFont(font); + QTRY_VERIFY(!tree.verticalScrollBar()->isVisible()); + + font.setPixelSize(60); + tree.setFont(font); + //now with the huge items, the scrollbar must be visible + QTRY_VERIFY(tree.verticalScrollBar()->isVisible()); + + qApp->setStyleSheet(app_css); +} + +void tst_QAbstractItemView::task200665_itemEntered() +{ +#ifdef Q_OS_WINCE_WM + QSKIP("On Windows Mobile the mouse tracking is unavailable at the moment", SkipAll); +#endif + //we test that view will emit entered + //when the scrollbar move but not the mouse itself + QStandardItemModel model(1000,1); + QListView view; + view.setModel(&model); + view.show(); + QTest::qWait(200); + QRect rect = view.visualRect(model.index(0,0)); + QCursor::setPos( view.viewport()->mapToGlobal(rect.center()) ); + QSignalSpy spy(&view, SIGNAL(entered(QModelIndex))); + view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum()); + + QCOMPARE(spy.count(), 1); +} + +void tst_QAbstractItemView::task257481_emptyEditor() +{ + QIcon icon = qApp->style()->standardIcon(QStyle::SP_ComputerIcon); + + QStandardItemModel model; + + model.appendRow( new QStandardItem(icon, QString()) ); + model.appendRow( new QStandardItem(icon, "Editor works") ); + model.appendRow( new QStandardItem( QString() ) ); + + QTreeView treeView; + treeView.setRootIsDecorated(false); + treeView.setModel(&model); + treeView.show(); + + treeView.edit(model.index(0,0)); + QList lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); + + QTest::qWait(30); + + treeView.edit(model.index(1,0)); + lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); + + QTest::qWait(30); + + treeView.edit(model.index(2,0)); + lineEditors = qFindChildren(treeView.viewport()); + QCOMPARE(lineEditors.count(), 1); + QVERIFY(!lineEditors.first()->size().isEmpty()); +} + +void tst_QAbstractItemView::shiftArrowSelectionAfterScrolling() +{ + QStandardItemModel model; + for (int i=0; i<10; ++i) { + QStandardItem *item = new QStandardItem(QString("%1").arg(i)); + model.setItem(i, 0, item); + } + + QListView view; + view.setFixedSize(150, 250); + view.setFlow(QListView::LeftToRight); + view.setGridSize(QSize(100, 100)); + view.setSelectionMode(QListView::ExtendedSelection); + view.setViewMode(QListView::IconMode); + view.setModel(&model); + view.show(); + QTest::qWait(30); + + QModelIndex index0 = model.index(0, 0); + QModelIndex index1 = model.index(1, 0); + QModelIndex index9 = model.index(9, 0); + + view.selectionModel()->setCurrentIndex(index0, QItemSelectionModel::NoUpdate); + QCOMPARE(view.currentIndex(), index0); + + view.scrollTo(index9); + QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier); + + QCOMPARE(view.currentIndex(), index1); + QModelIndexList selected = view.selectionModel()->selectedIndexes(); + QCOMPARE(selected.count(), 2); + QVERIFY(selected.contains(index0)); + QVERIFY(selected.contains(index1)); +} + +void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() +{ + QStandardItemModel model; + for (int i=0; i<3; ++i) { + QStandardItem *item = new QStandardItem(QString("%1").arg(i)); + model.setItem(i, 0, item); + } + + QListView view; + view.setFixedSize(150, 450); + view.setFlow(QListView::LeftToRight); + view.setGridSize(QSize(100, 100)); + view.setSelectionMode(QListView::ExtendedSelection); + view.setViewMode(QListView::IconMode); + view.setModel(&model); + view.show(); + QTest::qWait(30); + + QModelIndex index0 = model.index(0, 0); + QModelIndex index1 = model.index(1, 0); + QModelIndex index2 = model.index(2, 0); + + view.setCurrentIndex(index0); + QCOMPARE(view.currentIndex(), index0); + + // Determine the points where the rubberband selection starts and ends + QPoint pressPos = view.visualRect(index1).bottomRight() + QPoint(1, 1); + QPoint releasePos = view.visualRect(index1).center(); + QVERIFY(!view.indexAt(pressPos).isValid()); + QCOMPARE(view.indexAt(releasePos), index1); + + // Select item 1 using a rubberband selection + // The mouse move event has to be created manually because the QTest framework does not + // contain a function for mouse moves with buttons pressed + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos); + QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier); + bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent); + QVERIFY(moveEventReceived); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos); + QCOMPARE(view.currentIndex(), index1); + + // Shift-click item 2 + QPoint item2Pos = view.visualRect(index2).center(); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, item2Pos); + QCOMPARE(view.currentIndex(), index2); + + // Verify that the selection worked OK + QModelIndexList selected = view.selectionModel()->selectedIndexes(); + QCOMPARE(selected.count(), 2); + QVERIFY(selected.contains(index1)); + QVERIFY(selected.contains(index2)); + + // Select item 0 to revert the selection + view.setCurrentIndex(index0); + QCOMPARE(view.currentIndex(), index0); + + // Repeat the same steps as above, but with a Shift-Arrow selection + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, pressPos); + QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier); + moveEventReceived = qApp->notify(view.viewport(), &moveEvent2); + QVERIFY(moveEventReceived); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos); + QCOMPARE(view.currentIndex(), index1); + + // Press Shift-Down + QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier); + QCOMPARE(view.currentIndex(), index2); + + // Verify that the selection worked OK + selected = view.selectionModel()->selectedIndexes(); + QCOMPARE(selected.count(), 2); + QVERIFY(selected.contains(index1)); + QVERIFY(selected.contains(index2)); +} + +void tst_QAbstractItemView::ctrlRubberbandSelection() +{ + QStandardItemModel model; + for (int i=0; i<3; ++i) { + QStandardItem *item = new QStandardItem(QString("%1").arg(i)); + model.setItem(i, 0, item); + } + + QListView view; + view.setFixedSize(150, 450); + view.setFlow(QListView::LeftToRight); + view.setGridSize(QSize(100, 100)); + view.setSelectionMode(QListView::ExtendedSelection); + view.setViewMode(QListView::IconMode); + view.setModel(&model); + view.show(); + QTest::qWait(30); + + QModelIndex index1 = model.index(1, 0); + QModelIndex index2 = model.index(2, 0); + + // Select item 1 + view.setCurrentIndex(index1); + QModelIndexList selected = view.selectionModel()->selectedIndexes(); + QCOMPARE(selected.count(), 1); + QVERIFY(selected.contains(index1)); + + // Now press control and draw a rubberband around items 1 and 2. + // The mouse move event has to be created manually because the QTest framework does not + // contain a function for mouse moves with buttons pressed. + QPoint pressPos = view.visualRect(index1).topLeft() - QPoint(1, 1); + QPoint releasePos = view.visualRect(index2).bottomRight() + QPoint(1, 1); + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pressPos); + QMouseEvent moveEvent(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier); + bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent); + QVERIFY(moveEventReceived); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, releasePos); + + // Verify that item 2 is selected now + selected = view.selectionModel()->selectedIndexes(); + QCOMPARE(selected.count(), 1); + QVERIFY(selected.contains(index2)); +} + +void tst_QAbstractItemView::QTBUG6407_extendedSelection() +{ + QListWidget view; + view.setSelectionMode(QAbstractItemView::ExtendedSelection); + for(int i = 0; i < 50; ++i) + view.addItem(QString::number(i)); + + QFont font = view.font(); + font.setPixelSize(10); + view.setFont(font); + view.resize(200,240); + + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(static_cast(&view), QApplication::activeWindow()); + + view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum()); + QTest::qWait(20); + + QModelIndex index49 = view.model()->index(49,0); + QPoint p = view.visualRect(index49).center(); + QVERIFY(view.viewport()->rect().contains(p)); + QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p); + QCOMPARE(view.currentIndex(), index49); + QCOMPARE(view.selectedItems().count(), 1); + + QModelIndex index47 = view.model()->index(47,0); + p = view.visualRect(index47).center(); + QVERIFY(view.viewport()->rect().contains(p)); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p); + QCOMPARE(view.currentIndex(), index47); + QCOMPARE(view.selectedItems().count(), 3); //49, 48, 47; + + QModelIndex index44 = view.model()->index(44,0); + p = view.visualRect(index44).center(); + QVERIFY(view.viewport()->rect().contains(p)); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p); + QCOMPARE(view.currentIndex(), index44); + QCOMPARE(view.selectedItems().count(), 6); //49 .. 44; + +} + +void tst_QAbstractItemView::QTBUG6753_selectOnSelection() +{ + QTableWidget table(5, 5); + for (int i = 0; i < table.rowCount(); ++i) + for (int j = 0; j < table.columnCount(); ++j) + table.setItem(i, j, new QTableWidgetItem("choo-be-doo-wah")); + + table.show(); + table.setSelectionMode(QAbstractItemView::ExtendedSelection); + table.selectAll(); + QTest::qWaitForWindowShown(&table); + QModelIndex item = table.model()->index(1,1); + QRect itemRect = table.visualRect(item); + QTest::mouseMove(table.viewport(), itemRect.center()); + QTest::mouseClick(table.viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center()); + QTest::qWait(20); + + QCOMPARE(table.selectedItems().count(), 1); + QCOMPARE(table.selectedItems().first(), table.item(item.row(), item.column())); +} + +QTEST_MAIN(tst_QAbstractItemView) +#include "tst_qabstractitemview.moc" -- cgit v1.2.3