diff options
Diffstat (limited to 'tests/auto/widgets/itemviews/qabstractitemview')
3 files changed, 372 insertions, 137 deletions
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST b/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST index 249c91c3c4..778a25b2e4 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST +++ b/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST @@ -1,5 +1,4 @@ -[task200665_itemEntered] -macos # Can't move cursor (QTBUG-76312) -# QTBUG-87400 -[task200665_itemEntered] -android +[focusNextOnHide] +wayland +[selectionAutoScrolling] +wayland diff --git a/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt b/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt index e779b1a165..ca39501a95 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qabstractitemview.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractitemview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractitemview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractitemview SOURCES tst_qabstractitemview.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::GuiPrivate Qt::TestPrivate diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 5c52439859..4f2495375d 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <private/qguiapplication_p.h> @@ -55,6 +30,7 @@ #include <QVBoxLayout> #include <QtTest/private/qtesthelpers_p.h> #include <private/qabstractitemview_p.h> +#include <QtWidgets/private/qapplication_p.h> Q_DECLARE_METATYPE(Qt::ItemFlags); @@ -133,6 +109,7 @@ private slots: void QTBUG6407_extendedSelection(); void QTBUG6753_selectOnSelection(); void testDelegateDestroyEditor(); + void testDelegateDestroyEditorChild(); void testClickedSignal(); void testChangeEditorState(); void deselectInSingleSelection(); @@ -165,11 +142,16 @@ private slots: void selectionCommand(); void mouseSelection_data(); void mouseSelection(); + void keepSingleSelectionOnEmptyAreaClick(); void scrollerSmoothScroll(); void inputMethodOpensEditor_data(); void inputMethodOpensEditor(); void selectionAutoScrolling_data(); void selectionAutoScrolling(); + void testSpinBoxAsEditor_data(); + void testSpinBoxAsEditor(); + void removeIndexWhileEditing(); + void focusNextOnHide(); private: static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr) @@ -196,17 +178,19 @@ public: QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const override { openedEditor = new QWidget(parent); + virtualCtorCallCount++; return openedEditor; } void destroyEditor(QWidget *editor, const QModelIndex &) const override { - calledVirtualDtor = true; + virtualDtorCallCount++; editor->deleteLater(); } void changeSize() { size = QSize(50, 50); emit sizeHintChanged(QModelIndex()); } mutable QWidget *openedEditor = nullptr; QSize size; - mutable bool calledVirtualDtor = false; + mutable int virtualCtorCallCount = 0; + mutable int virtualDtorCallCount = 0; }; class DialogItemDelegate : public QStyledItemDelegate @@ -449,12 +433,12 @@ void tst_QAbstractItemView::basic_tests(QAbstractItemView *view) QVERIFY(spy.isValid()); view->setIconSize(QSize(32, 32)); QCOMPARE(view->iconSize(), QSize(32, 32)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).value<QSize>(), QSize(32, 32)); // Should this happen? view->setIconSize(QSize(-1, -1)); QCOMPARE(view->iconSize(), QSize(-1, -1)); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(view->currentIndex(), QModelIndex()); QCOMPARE(view->rootIndex(), QModelIndex()); @@ -688,9 +672,9 @@ void tst_QAbstractItemView::selectAll() GeometriesTestView view; view.setModel(&model); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); view.selectAll(); - QCOMPARE(view.selectedIndexes().count(), 4 * 4); + QCOMPARE(view.selectedIndexes().size(), 4 * 4); } void tst_QAbstractItemView::ctrlA() @@ -699,9 +683,9 @@ void tst_QAbstractItemView::ctrlA() GeometriesTestView view; view.setModel(&model); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier); - QCOMPARE(view.selectedIndexes().count(), 4 * 4); + QCOMPARE(view.selectedIndexes().size(), 4 * 4); } void tst_QAbstractItemView::persistentEditorFocus() @@ -718,7 +702,7 @@ void tst_QAbstractItemView::persistentEditorFocus() //these are spinboxes because we put numbers inside const QList<QSpinBox*> list = view.viewport()->findChildren<QSpinBox*>(); - QCOMPARE(list.count(), 2); //these should be the 2 editors + QCOMPARE(list.size(), 2); //these should be the 2 editors view.setCurrentIndex(model.index(0, 0)); QCOMPARE(view.currentIndex(), model.index(0, 0)); @@ -730,8 +714,8 @@ void tst_QAbstractItemView::persistentEditorFocus() const QPoint p(5, 5); for (QSpinBox *sb : list) { QTRY_VERIFY(sb->isVisible()); - QMouseEvent mouseEvent(QEvent::MouseButtonPress, p, Qt::LeftButton, - Qt::LeftButton, Qt::NoModifier); + QMouseEvent mouseEvent(QEvent::MouseButtonPress, p, sb->mapToGlobal(p), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QCoreApplication::sendEvent(sb, &mouseEvent); if (!QApplication::focusWidget()) QSKIP("Some window managers don't handle focus that well"); @@ -778,22 +762,6 @@ void tst_QAbstractItemView::pressClosesReleaseDoesntOpenEditor() QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, inChildOutsideEditor); // should not reopen editor QTest::qWait(QApplication::doubleClickInterval() * 2); QCOMPARE(view.state(), QAbstractItemView::NoState); - - // with multiple items selected, clicking from the currently edited item into another - // selected item closes the current and reopens a new editor - view.setSelectionMode(QAbstractItemView::ExtendedSelection); - const QRect child2Rect = view.visualRect(model.indexFromItem(parent->child(1))); - QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, child2Rect.center()); // select - QVERIFY(view.selectionModel()->selectedIndexes().contains(model.indexFromItem(parent->child(0)))); - QVERIFY(view.selectionModel()->selectedIndexes().contains(model.indexFromItem(parent->child(1)))); - QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, child2Rect.center()); // edit - QTRY_COMPARE(view.state(), QAbstractItemView::EditingState); - QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, inChildOutsideEditor); // editor closes - QCOMPARE(view.state(), QAbstractItemView::NoState); - QTest::qWait(10); // process some events, let the internal timer time out - QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, inChildOutsideEditor); // should open editor - QTest::qWait(QApplication::doubleClickInterval() * 2); - QCOMPARE(view.state(), QAbstractItemView::EditingState); } @@ -1083,7 +1051,6 @@ void tst_QAbstractItemView::setItemDelegate() centerOnScreen(&v); moveCursorAway(&v); v.show(); - QApplication::setActiveWindow(&v); QVERIFY(QTest::qWaitForWindowActive(&v)); QModelIndex index = model.index(cellToEdit.y(), cellToEdit.x()); @@ -1292,7 +1259,6 @@ void tst_QAbstractItemView::task221955_selectedEditor() tree.show(); tree.setFocus(); tree.setCurrentIndex(tree.model()->index(1,0)); - QApplication::setActiveWindow(&tree); QVERIFY(QTest::qWaitForWindowActive(&tree)); QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); @@ -1358,7 +1324,13 @@ void tst_QAbstractItemView::task200665_itemEntered() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: This fails. Figure out why."); - + { + // skip if we can't move mouse + const QPoint cursorPos = QCursor::pos() + QPoint(10, 10); + QCursor::setPos(cursorPos); + if (!QTest::qWaitFor([cursorPos] { return QCursor::pos() == cursorPos; }, 500)) + QSKIP("Can't move mouse"); + } //we test that view will emit entered //when the scrollbar move but not the mouse itself QStandardItemModel model(1000, 1); @@ -1373,7 +1345,7 @@ void tst_QAbstractItemView::task200665_itemEntered() QSignalSpy spy(&view, &QAbstractItemView::entered); view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum()); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); } void tst_QAbstractItemView::task257481_emptyEditor() @@ -1396,17 +1368,17 @@ void tst_QAbstractItemView::task257481_emptyEditor() treeView.edit(model.index(0, 0)); QList<QLineEdit *> lineEditors = treeView.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QVERIFY(!lineEditors.constFirst()->size().isEmpty()); treeView.edit(model.index(1, 0)); lineEditors = treeView.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QVERIFY(!lineEditors.constFirst()->size().isEmpty()); treeView.edit(model.index(2, 0)); lineEditors = treeView.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QVERIFY(!lineEditors.constFirst()->size().isEmpty()); } @@ -1440,7 +1412,7 @@ void tst_QAbstractItemView::shiftArrowSelectionAfterScrolling() QCOMPARE(view.currentIndex(), index1); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(index0)); QVERIFY(selected.contains(index1)); } @@ -1480,7 +1452,8 @@ void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() // 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); + QMouseEvent moveEvent(QEvent::MouseMove, releasePos, view.viewport()->mapToGlobal(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); @@ -1493,7 +1466,7 @@ void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() // Verify that the selection worked OK QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(index1)); QVERIFY(selected.contains(index2)); @@ -1503,7 +1476,8 @@ void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() // 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); + QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, view.viewport()->mapToGlobal(releasePos), + Qt::NoButton, Qt::LeftButton, Qt::NoModifier); moveEventReceived = qApp->notify(view.viewport(), &moveEvent2); QVERIFY(moveEventReceived); QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, releasePos); @@ -1515,7 +1489,7 @@ void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() // Verify that the selection worked OK selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(index1)); QVERIFY(selected.contains(index2)); } @@ -1544,7 +1518,7 @@ void tst_QAbstractItemView::ctrlRubberbandSelection() // Select item 1 view.setCurrentIndex(index1); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(index1)); // Now press control and draw a rubberband around items 1 and 2. @@ -1553,14 +1527,15 @@ void tst_QAbstractItemView::ctrlRubberbandSelection() 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); + QMouseEvent moveEvent(QEvent::MouseMove, releasePos, view.viewport()->mapToGlobal(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); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(index2)); } @@ -1582,7 +1557,6 @@ void tst_QAbstractItemView::QTBUG6407_extendedSelection() moveCursorAway(&view); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); @@ -1593,21 +1567,21 @@ void tst_QAbstractItemView::QTBUG6407_extendedSelection() QVERIFY(view.viewport()->rect().contains(p)); QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, p); QCOMPARE(view.currentIndex(), index49); - QCOMPARE(view.selectedItems().count(), 1); + QCOMPARE(view.selectedItems().size(), 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; + QCOMPARE(view.selectedItems().size(), 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; + QCOMPARE(view.selectedItems().size(), 6); //49 .. 44; } @@ -1632,7 +1606,7 @@ void tst_QAbstractItemView::QTBUG6753_selectOnSelection() QTest::mouseMove(table.viewport(), itemRect.center()); QTest::mouseClick(table.viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center()); - QCOMPARE(table.selectedItems().count(), 1); + QCOMPARE(table.selectedItems().size(), 1); QCOMPARE(table.selectedItems().first(), table.item(item.row(), item.column())); } @@ -1643,9 +1617,31 @@ void tst_QAbstractItemView::testDelegateDestroyEditor() table.setItemDelegate(&delegate); table.edit(table.model()->index(1, 1)); QAbstractItemView *tv = &table; - QVERIFY(!delegate.calledVirtualDtor); + QCOMPARE(delegate.virtualDtorCallCount, 0); tv->closeEditor(delegate.openedEditor, QAbstractItemDelegate::NoHint); - QVERIFY(delegate.calledVirtualDtor); + QCOMPARE(delegate.virtualDtorCallCount, 1); +} + +void tst_QAbstractItemView::testDelegateDestroyEditorChild() +{ + QTreeWidget tree; + MyAbstractItemDelegate delegate; + tree.setItemDelegate(&delegate); + QTreeWidgetItem *topLevel = new QTreeWidgetItem; + QTreeWidgetItem *levelOne1 = new QTreeWidgetItem(topLevel); + QTreeWidgetItem *levelTwo1 = new QTreeWidgetItem(levelOne1); + QTreeWidgetItem *levelOne2 = new QTreeWidgetItem(topLevel); + QTreeWidgetItem *levelTwo2 = new QTreeWidgetItem(levelOne2); + tree.insertTopLevelItem(0, topLevel); + tree.openPersistentEditor(levelOne1); + tree.openPersistentEditor(levelTwo1); + tree.openPersistentEditor(levelOne2); + tree.openPersistentEditor(levelTwo2); + QCOMPARE(delegate.virtualCtorCallCount, 4); + levelOne1->removeChild(levelTwo1); + QCOMPARE(delegate.virtualDtorCallCount, 1); + topLevel->removeChild(levelOne2); + QCOMPARE(delegate.virtualDtorCallCount, 3); } void tst_QAbstractItemView::testClickedSignal() @@ -1658,7 +1654,6 @@ void tst_QAbstractItemView::testClickedSignal() centerOnScreen(&view); moveCursorAway(&view); view.showNormal(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); @@ -1669,12 +1664,12 @@ void tst_QAbstractItemView::testClickedSignal() QSignalSpy clickedSpy(&view, &QTableWidget::clicked); QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, p); - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); QTest::mouseClick(view.viewport(), Qt::RightButton, {}, p); // We expect that right-clicks do not cause the clicked() signal to // be emitted. - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); } @@ -1709,7 +1704,6 @@ void tst_QAbstractItemView::testChangeEditorState() centerOnScreen(&view); moveCursorAway(&view); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); @@ -1730,7 +1724,6 @@ void tst_QAbstractItemView::deselectInSingleSelection() QVERIFY(QTest::qWaitForWindowExposed(&view)); view.setSelectionMode(QAbstractItemView::SingleSelection); view.setEditTriggers(QAbstractItemView::NoEditTriggers); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); // mouse QModelIndex index22 = s.index(2, 2); @@ -1738,28 +1731,28 @@ void tst_QAbstractItemView::deselectInSingleSelection() QPoint clickpos = rect22.center(); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, clickpos); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, clickpos); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0); // second click with modifier however does select QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, clickpos); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); // keyboard QTest::keyClick(&view, Qt::Key_Space, Qt::NoModifier); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QTest::keyClick(&view, Qt::Key_Space, Qt::ControlModifier); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0); // second keypress with modifier however does select QTest::keyClick(&view, Qt::Key_Space, Qt::ControlModifier); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); } void tst_QAbstractItemView::testNoActivateOnDisabledItem() @@ -1777,7 +1770,6 @@ void tst_QAbstractItemView::testNoActivateOnDisabledItem() moveCursorAway(&treeView); treeView.show(); - QApplication::setActiveWindow(&treeView); QVERIFY(QTest::qWaitForWindowActive(&treeView)); QSignalSpy activatedSpy(&treeView, &QAbstractItemView::activated); @@ -1787,7 +1779,7 @@ void tst_QAbstractItemView::testNoActivateOnDisabledItem() QPoint clickPos = treeView.visualRect(itemIndex).center(); QTest::mouseClick(treeView.viewport(), Qt::LeftButton, {}, clickPos); - QCOMPARE(activatedSpy.count(), 0); + QCOMPARE(activatedSpy.size(), 0); } void tst_QAbstractItemView::testFocusPolicy_data() @@ -1824,7 +1816,6 @@ void tst_QAbstractItemView::testFocusPolicy() moveCursorAway(&window); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); // itemview accepts focus => editor is closed => return focus to the itemview @@ -1862,7 +1853,6 @@ void tst_QAbstractItemView::QTBUG31411_noSelection() moveCursorAway(&window); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); qRegisterMetaType<QItemSelection>(); @@ -1881,7 +1871,7 @@ void tst_QAbstractItemView::QTBUG31411_noSelection() QVERIFY(editor2); QTest::keyClick(editor2, Qt::Key_Escape, Qt::NoModifier); - QCOMPARE(selectionChangeSpy.count(), 0); + QCOMPARE(selectionChangeSpy.size(), 0); } void tst_QAbstractItemView::QTBUG39324_settingSameInstanceOfIndexWidget() @@ -1923,7 +1913,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Click "C" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexC).center()); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexC)); // Insert new item "B1" @@ -1933,14 +1923,14 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Shift-click "D" -> we expect that "C" and "D" are selected QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexD).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(indexC)); QVERIFY(selected.contains(indexD)); // Click "D" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexD).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexD)); // Remove items "B" and "C" @@ -1952,7 +1942,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Shift-click "F" -> we expect that "D", "E", and "F" are selected QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexF).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); QVERIFY(selected.contains(indexD)); QVERIFY(selected.contains(indexE)); QVERIFY(selected.contains(indexF)); @@ -1961,7 +1951,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() while (view.currentIndex() != indexA) QTest::keyClick(&view, Qt::Key_Up); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexA)); // Change the sort order @@ -1970,7 +1960,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Shift-click "F" -> All items should be selected QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexF).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), model.rowCount()); + QCOMPARE(selected.size(), model.rowCount()); // Restore the old sort order proxyModel.sort(0, Qt::AscendingOrder); @@ -1978,7 +1968,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Click "D" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexD).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexD)); // Insert new item "B2" @@ -1988,7 +1978,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Press Shift+Down -> "D" and "E" should be selected. QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(indexD)); QVERIFY(selected.contains(indexE)); @@ -1997,7 +1987,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexA).center()); view.setCurrentIndex(indexD); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexD)); // Insert new item "B3" @@ -2007,7 +1997,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Press Shift+Down -> "D" and "E" should be selected. QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(indexD)); QVERIFY(selected.contains(indexE)); } @@ -2285,14 +2275,14 @@ void tst_QAbstractItemView::testClickToSelect() // Click the center of the visualRect of item "A" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, centerA); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.back().front().value<QRect>(), QRect(centerA, QSize(1, 1))); // Click a point slightly away from the center const QPoint nearCenterA = centerA + QPoint(1, 1); QVERIFY(visualRectA.contains(nearCenterA)); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, nearCenterA); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(spy.back().front().value<QRect>(), QRect(nearCenterA, QSize(1, 1))); } @@ -2462,15 +2452,11 @@ void tst_QAbstractItemView::inputMethodEnabled() // Check focus by switching the activation of the window to force a focus in view->setCurrentIndex(model->index(1, 0)); - QApplication::setActiveWindow(nullptr); - QApplication::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result); view->setCurrentIndex(QModelIndex()); QVERIFY(!view->testAttribute(Qt::WA_InputMethodEnabled)); - QApplication::setActiveWindow(nullptr); - QApplication::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); QModelIndex index = model->index(1, 0); QPoint p = view->visualRect(index).center(); @@ -2480,8 +2466,6 @@ void tst_QAbstractItemView::inputMethodEnabled() QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result); index = model->index(0, 0); - QApplication::setActiveWindow(nullptr); - QApplication::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); p = view->visualRect(index).center(); QTest::mouseClick(view->viewport(), Qt::LeftButton, Qt::NoModifier, p); @@ -2491,11 +2475,11 @@ void tst_QAbstractItemView::inputMethodEnabled() // There is a case when it goes to the first visible item so we // make the flags of the first item match the ones we are testing // to check the attribute correctly - QApplication::setActiveWindow(nullptr); + QApplicationPrivate::setActiveWindow(nullptr); view->setCurrentIndex(QModelIndex()); view->reset(); item->setFlags(Qt::ItemFlags(itemFlags)); - QApplication::setActiveWindow(view.data()); + QApplicationPrivate::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result); } @@ -2606,11 +2590,11 @@ void tst_QAbstractItemView::checkFocusAfterActivationChanges() QVERIFY(QTest::qWaitForWindowExposed(delegate.openedEditor)); QVERIFY(delegate.openedEditor->hasFocus()); - QApplication::setActiveWindow(&otherTopLevel); + QApplicationPrivate::setActiveWindow(&otherTopLevel); otherTopLevel.setFocus(); QTRY_VERIFY(!delegate.openedEditor); - QApplication::setActiveWindow(&w); + QApplicationPrivate::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QVERIFY(view->hasFocus()); } @@ -2650,7 +2634,7 @@ void tst_QAbstractItemView::dragSelectAfterNewPress() // Verify that the selection worked OK QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); for (int i = 0; i < 2; ++i) QVERIFY(selected.contains(model.index(i, 0))); @@ -2658,8 +2642,8 @@ void tst_QAbstractItemView::dragSelectAfterNewPress() const QPoint releasePos = view.visualRect(index5).center(); // The mouse move event has to be created manually because the QTest framework does not // contain a function for mouse moves with buttons pressed - QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, - Qt::ShiftModifier); + QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, view.viewport()->mapToGlobal(releasePos), + Qt::NoButton, Qt::LeftButton, Qt::ShiftModifier); const bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent2); QVERIFY(moveEventReceived); QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, releasePos); @@ -2667,18 +2651,19 @@ void tst_QAbstractItemView::dragSelectAfterNewPress() // Verify that the selection worked OK selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 6); + QCOMPARE(selected.size(), 6); for (int i = 0; i < 5; ++i) QVERIFY(selected.contains(model.index(i, 0))); } void tst_QAbstractItemView::dragWithSecondClick_data() { - QTest::addColumn<QString>("viewClass"); + QTest::addColumn<QByteArray>("viewClass"); QTest::addColumn<bool>("doubleClick"); - for (QString viewClass : {"QListView", "QTreeView"}) { - QTest::addRow("DoubleClick") << viewClass << true; - QTest::addRow("Two Single Clicks") << viewClass << false; + const QList<QByteArray> widgets { "QListView", "QTreeView" }; + for (const QByteArray &widget : widgets) { + QTest::newRow(widget + ": DoubleClick") << widget << true; + QTest::newRow(widget + ": Two Single Clicks") << widget << false; } } @@ -2707,7 +2692,7 @@ protected: void tst_QAbstractItemView::dragWithSecondClick() { - QFETCH(QString, viewClass); + QFETCH(QByteArray, viewClass); QFETCH(bool, doubleClick); QStandardItemModel model; @@ -2755,7 +2740,7 @@ void tst_QAbstractItemView::dragWithSecondClick() const QPoint dragTo = view->visualRect(index1).center() + QPoint(2 * QApplication::startDragDistance(), 2 * QApplication::startDragDistance()); - QMouseEvent mouseMoveEvent(QEvent::MouseMove, dragTo, + QMouseEvent mouseMoveEvent(QEvent::MouseMove, dragTo, view->viewport()->mapToGlobal(dragTo), Qt::NoButton, Qt::LeftButton, Qt::NoModifier); QVERIFY(QApplication::sendEvent(view->viewport(), &mouseMoveEvent)); // twice since the view will first enter dragging state, then start the drag @@ -2862,55 +2847,78 @@ void tst_QAbstractItemView::mouseSelection_data() { QTest::addColumn<QAbstractItemView::SelectionMode>("selectionMode"); QTest::addColumn<bool>("dragEnabled"); + QTest::addColumn<QAbstractItemView::EditTrigger>("editTrigger"); QTest::addColumn<QList<SelectionEvent>>("selectionEvents"); QTest::addColumn<QList<int>>("selectedRows"); // single selection mode - always one row selected, modifiers ignored QTest::addRow("Single:Press") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1)} << QList{1}; QTest::addRow("Single:Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Click, 1}} << QList{1}; QTest::addRow("Single:Press+Drag") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent{SelectionEvent::Move, 2}, SelectionEvent{SelectionEvent::Release}} << QList{2}; QTest::addRow("Single:Shift+Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Click, Qt::ShiftModifier, 2}} << QList{2}; + QTest::addRow("Single:Press;Ctrl+Press") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers + << QList{SelectionEvent{SelectionEvent::Press, 3}, + SelectionEvent{SelectionEvent::Press, Qt::ControlModifier, 3}} + << QList{3}; QTest::addRow("Single:Ctrl+Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Click, Qt::ControlModifier, 3}} << QList{3}; + QTest::addRow("Single:Click;Ctrl+Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers + << QList{SelectionEvent{SelectionEvent::Click, 3}, + SelectionEvent{SelectionEvent::Click, Qt::ControlModifier, 3}} + << QList<int>{}; // multi selection mode - selection toggles on press, selection can be drag-extended // modifiers ignored QTest::addRow("Multi:Press") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1)} << QList{1}; QTest::addRow("Multi:Press twice") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Press, 1)} << QList<int>{}; QTest::addRow("Multi:Press twice with drag enabled") << QAbstractItemView::MultiSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 1), SelectionEvent(SelectionEvent::Press, 1)} << QList{1}; QTest::addRow("Multi:Press and click with drag enabled") << QAbstractItemView::MultiSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Click, 1)} << QList<int>{}; QTest::addRow("Multi:Press,Press") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Press, 3)} << QList{2, 3}; QTest::addRow("Multi:Press,Drag") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release)} << QList{1, 2, 3, 4, 5}; QTest::addRow("Multi:Press,Drag,Deselect") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2918,6 +2926,7 @@ void tst_QAbstractItemView::mouseSelection_data() << QList{1, 2, 4, 5}; // drag-select a few indices; then drag-select a larger area that includes the first QTest::addRow("Multi:Press,Drag;Surround") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2927,6 +2936,7 @@ void tst_QAbstractItemView::mouseSelection_data() << QList{1, 2, 3, 4, 5, 6, 7, 8}; // drag-select a few indices; then try to select more starting with the last -> not working QTest::addRow("Multi:Press,Drag;Expand") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2937,6 +2947,7 @@ void tst_QAbstractItemView::mouseSelection_data() // Multi: Press-dragging a selection should not deselect #QTBUG-59888 QTest::addRow("Multi:Press-Drag selection") << QAbstractItemView::MultiSelection << true // with drag'n'drop enabled, we cannot drag a selection + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 2), SelectionEvent(SelectionEvent::Click, 3), SelectionEvent(SelectionEvent::Click, 4), @@ -2949,42 +2960,51 @@ void tst_QAbstractItemView::mouseSelection_data() // Extended selection: Press selects a single item QTest::addRow("Extended:Press") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3)} << QList{3}; QTest::addRow("Extended:Press twice") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Press, 3)} << QList{3}; QTest::addRow("Extended:Press,Press") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Press, 3)} << QList{3}; // Extended selection: press with Ctrl toggles item QTest::addRow("Extended:Press,Toggle") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} << QList<int>{}; QTest::addRow("Extended:Press,Add") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} << QList{1, 3}; // Extended selection: Shift creates a range between first and last pressed QTest::addRow("Extended:Press,Range") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 5)} << QList{1, 2, 3, 4, 5}; QTest::addRow("Extended:Press,Range,Fix Range") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 5), SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 3)} << QList{1, 2, 3}; // Extended: dragging extends the selection QTest::addRow("Extended:Press,Drag") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Move, 5)} << QList{2, 3, 4, 5}; // Extended: Ctrl+Press-dragging extends the selection QTest::addRow("Extended:Press,Drag;Ctrl-Press,Drag") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2993,7 +3013,8 @@ void tst_QAbstractItemView::mouseSelection_data() SelectionEvent(SelectionEvent::Release, Qt::ControlModifier, 8)} << QList{2, 3, 4, 5, 6, 7, 8}; // Extended: Ctrl+Press-dragging in a selection should not deselect #QTBUG-59888 - QTest::addRow("Extended:Ctrl-Drag selection") << QAbstractItemView::ExtendedSelection << true + QTest::addRow("Extended:Ctrl-Drag selection,no deselect") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 2), SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 5), SelectionEvent(SelectionEvent::Press, Qt::ControlModifier, 3), @@ -3003,6 +3024,7 @@ void tst_QAbstractItemView::mouseSelection_data() << QList{2, 3, 4, 5}; // Extended: Ctrl+Press-dragging with a selection extends, then drags #QTBUG-59888 QTest::addRow("Extended:Ctrl-Drag selection") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 2), SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 5), SelectionEvent(SelectionEvent::Press, Qt::ControlModifier, 6), @@ -3010,12 +3032,37 @@ void tst_QAbstractItemView::mouseSelection_data() // two moves needed because of distance and state logic in 7QAbstractItemView SelectionEvent(SelectionEvent::Move, Qt::ControlModifier, 8)} << QList{2, 3, 4, 5, 6}; + // Extended: when drag is enabled, click with Ctrl toggles item instead of editing # QTBUG-111131 + QTest::addRow("Extended:Click,Toggle,editable") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 3), + SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} + << QList<int>{}; + QTest::addRow("Extended:Click,Toggle,dragable,editable") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 3), + SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} + << QList<int>{}; + // Extended: when drag is enabled, click on selected without Ctrl clears before editing + QTest::addRow("Extended:Range,Click,editable") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 1), + SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 3), + SelectionEvent(SelectionEvent::Click, 2)} + << QList<int>{2}; + QTest::addRow("Extended:Range,Click,dragable,editable") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 1), + SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 3), + SelectionEvent(SelectionEvent::Click, 2)} + << QList<int>{2}; } void tst_QAbstractItemView::mouseSelection() { QFETCH(QAbstractItemView::SelectionMode, selectionMode); QFETCH(bool, dragEnabled); + QFETCH(QAbstractItemView::EditTrigger, editTrigger); QFETCH(QList<SelectionEvent>, selectionEvents); QFETCH(QList<int>, selectedRows); @@ -3024,7 +3071,7 @@ void tst_QAbstractItemView::mouseSelection() for (int i = 0; i < 10; ++i) { QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); item->setDragEnabled(dragEnabled); - item->setEditable(false); + item->setEditable(editTrigger != QAbstractItemView::NoEditTriggers); parentItem->appendRow(item); } @@ -3034,13 +3081,14 @@ void tst_QAbstractItemView::mouseSelection() view->setModel(&model); view->setDragEnabled(dragEnabled); view->setSelectionMode(selectionMode); + view->setEditTriggers(editTrigger); view->show(); QVERIFY(QTest::qWaitForWindowActive(view)); Qt::MouseButton buttonDown = Qt::NoButton; int targetRow = -1; QModelIndex pressedIndex; - for (const auto &event : qAsConst(selectionEvents)) { + for (const auto &event : std::as_const(selectionEvents)) { if (event.row != -1) targetRow = event.row; const QModelIndex targetIndex = model.index(targetRow, 0); @@ -3066,7 +3114,8 @@ void tst_QAbstractItemView::mouseSelection() break; case SelectionEvent::Move: { QMouseEvent mouseMoveEvent(QEvent::MouseMove, targetPoint, - Qt::NoButton, buttonDown, event.keyboardModifiers); + view->viewport()->mapToGlobal(targetPoint), + Qt::NoButton, buttonDown, event.keyboardModifiers); QApplication::sendEvent(view->viewport(), &mouseMoveEvent); } break; @@ -3084,6 +3133,37 @@ void tst_QAbstractItemView::mouseSelection() } /*! + Make sure that when clicking on empty space in the view, we don't + unselect the current row. + QTBUG-105870 +*/ +void tst_QAbstractItemView::keepSingleSelectionOnEmptyAreaClick() +{ + QListWidget view; + view.setSelectionMode(QAbstractItemView::SingleSelection); + QListWidgetItem *lastItem; + for (int i = 0; i < 5; i++) + lastItem = new QListWidgetItem("item " + QString::number(i), &view); + + // Make widget large enough so that there is empty area below the last item + view.setFixedSize(300, 500); + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + // Select third row + view.setCurrentRow(2); + + // Click below the last row + QPoint targetPoint = view.visualItemRect(lastItem).bottomLeft(); + targetPoint += QPoint(10, 10); + + QTest::mouseClick(view.viewport(), Qt::MouseButton::LeftButton, Qt::NoModifier, targetPoint); + + QCOMPARE(view.currentRow(), 2); + QVERIFY(view.currentItem()->isSelected()); +} + +/*! Verify that scrolling an autoScroll enabled itemview with a QScroller produces a continuous, smooth scroll without any jumping around due to the currentItem negotiation between QAbstractItemView and QScroller. @@ -3091,6 +3171,9 @@ void tst_QAbstractItemView::mouseSelection() */ void tst_QAbstractItemView::scrollerSmoothScroll() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QListWidget view; view.setAutoScroll(true); view.setVerticalScrollMode(QListView::ScrollPerPixel); @@ -3160,6 +3243,9 @@ void tst_QAbstractItemView::inputMethodOpensEditor_data() void tst_QAbstractItemView::inputMethodOpensEditor() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QTableWidget tableWidget(50, 50); tableWidget.setEditTriggers(QAbstractItemView::AnyKeyPressed); for (int r = 0; r < 50; ++r) { @@ -3315,7 +3401,8 @@ void tst_QAbstractItemView::selectionAutoScrolling() } QTest::mousePress(listview.viewport(), Qt::LeftButton, Qt::NoModifier, pressPoint); - QMouseEvent mmEvent(QEvent::MouseMove, dragPoint, Qt::NoButton, Qt::LeftButton, Qt::NoModifier); + QMouseEvent mmEvent(QEvent::MouseMove, dragPoint, listview.viewport()->mapToGlobal(dragPoint), + Qt::NoButton, Qt::LeftButton, Qt::NoModifier); QApplication::sendEvent(listview.viewport(), &mmEvent); // QTest::mouseMove is useless // check that we scrolled to the end @@ -3327,10 +3414,152 @@ void tst_QAbstractItemView::selectionAutoScrolling() QTRY_COMPARE(scrollBar->value(), 0); else QTRY_COMPARE(scrollBar->value(), scrollBar->maximum()); - QVERIFY(listview.selectionModel()->selectedIndexes().count() > 0); + QVERIFY(listview.selectionModel()->selectedIndexes().size() > 0); QTest::mouseRelease(listview.viewport(), Qt::LeftButton, Qt::NoModifier, dragPoint); } +class SpinBoxDelegate : public QStyledItemDelegate +{ +public: + using QStyledItemDelegate::QStyledItemDelegate; + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const override + { + QSpinBox *spinboxEditor = new QSpinBox(parent); + return spinboxEditor; + } + + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override + { + if (QSpinBox *spin = qobject_cast<QSpinBox *>(editor)) { + model->setData(index, spin->value()); + } + } +}; + +void tst_QAbstractItemView::testSpinBoxAsEditor_data() +{ + QTest::addColumn<bool>("keyboardTracking"); + QTest::newRow("true") << true; + QTest::newRow("false")<< false; +} + +void tst_QAbstractItemView::testSpinBoxAsEditor() +{ + QFETCH(bool, keyboardTracking); + + QStandardItemModel model(2, 2); + SpinBoxDelegate delegate; + + QTableView view; + view.setModel(&model); + view.setItemDelegate(&delegate); + + view.setCurrentIndex(model.index(0, 1)); + view.openPersistentEditor(model.index(0, 1)); + const QList<QSpinBox *> list = view.viewport()->findChildren<QSpinBox *>(); + QCOMPARE(list.size(), 1); + QSpinBox *sb = list.first(); + QVERIFY(sb); + + sb->setKeyboardTracking(keyboardTracking); + + centerOnScreen(&view); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + QTRY_COMPARE(QApplication::focusWidget(), sb); + + QTest::keyClick(sb, Qt::Key_1, Qt::NoModifier); + QPoint clickpos = view.visualRect(model.index(0, 0)).center(); + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, clickpos); + + QCOMPARE(model.data(model.index(0, 1)).toInt(), 1); +} + +void tst_QAbstractItemView::removeIndexWhileEditing() +{ + QTreeView view; + QStandardItemModel treeModel; + auto editableItem1 = new QStandardItem("aa"); + auto editableItem2 = new QStandardItem("ab"); + auto editableItem3 = new QStandardItem("ac"); + auto item = new QStandardItem("a"); + item->appendRow(editableItem1); + item->appendRow(editableItem2); + item->appendRow(editableItem3); + treeModel.setItem(0, 0, item); + QSortFilterProxyModel filterModel; + filterModel.setSourceModel(&treeModel); + view.setModel(&filterModel); + view.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + view.setExpanded(item->index(), true); + + filterModel.setFilterRegularExpression("a.*"); + + QTest::failOnWarning(QRegularExpression("QAbstractItemView::closeEditor called with an editor " + "that does not belong to this view")); + + // Verify that we shut editing down cleanly if the index we are editing is + // filtered out after committing + { + const QModelIndex filteredIndex = filterModel.mapFromSource(editableItem1->index()); + QVERIFY(filteredIndex.isValid()); + view.edit(filteredIndex); + QCOMPARE(view.state(), QAbstractItemView::EditingState); + QTRY_VERIFY(QApplication::focusWidget()); + QPointer<QLineEdit> lineEdit = qobject_cast<QLineEdit *>(QApplication::focusWidget()); + QVERIFY(lineEdit); + lineEdit->setText("c"); + QTest::keyClick(lineEdit, Qt::Key_Enter); + QTRY_VERIFY(!lineEdit); + QCOMPARE(editableItem1->data(Qt::DisplayRole), "c"); + QCOMPARE(view.state(), QAbstractItemView::NoState); + } + + // If we change the filter while we edit, then we should clean up state as well + { + const QModelIndex filteredIndex = filterModel.mapFromSource(editableItem2->index()); + QVERIFY(filteredIndex.isValid()); + view.edit(filteredIndex); + QCOMPARE(view.state(), QAbstractItemView::EditingState); + QTRY_VERIFY(QApplication::focusWidget()); + QPointer<QLineEdit> lineEdit = qobject_cast<QLineEdit *>(QApplication::focusWidget()); + QVERIFY(lineEdit); + filterModel.setFilterFixedString("c"); + QVERIFY(!filterModel.mapFromSource(editableItem2->index()).isValid()); + QTRY_VERIFY(!lineEdit); + QCOMPARE(view.state(), QAbstractItemView::NoState); + } +} + +void tst_QAbstractItemView::focusNextOnHide() +{ + QWidget widget; + QTableWidget table(10, 10); + table.setTabKeyNavigation(true); + QLineEdit lineEdit; + + QHBoxLayout layout; + layout.addWidget(&table); + layout.addWidget(&lineEdit); + widget.setLayout(&layout); + + widget.setTabOrder({&table, &lineEdit}); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + QVERIFY(table.hasFocus()); + QCOMPARE(table.currentIndex(), table.model()->index(0, 0)); + QTest::keyPress(&table, Qt::Key_Tab); + QCOMPARE(table.currentIndex(), table.model()->index(0, 1)); + + table.hide(); + QCOMPARE(table.currentIndex(), table.model()->index(0, 1)); + QVERIFY(lineEdit.hasFocus()); +} QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" |