diff options
Diffstat (limited to 'tests/auto/corelib/itemmodels')
26 files changed, 1468 insertions, 844 deletions
diff --git a/tests/auto/corelib/itemmodels/CMakeLists.txt b/tests/auto/corelib/itemmodels/CMakeLists.txt index 530a54c91e..90211669d9 100644 --- a/tests/auto/corelib/itemmodels/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from itemmodels.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qstringlistmodel) if(TARGET Qt::Gui) @@ -8,10 +9,11 @@ if(TARGET Qt::Gui) add_subdirectory(qidentityproxymodel) add_subdirectory(qitemselectionmodel) add_subdirectory(qsortfilterproxymodel_recursive) + add_subdirectory(qsortfilterproxymodel_regularexpression) add_subdirectory(qtransposeproxymodel) endif() if(TARGET Qt::Widgets) - add_subdirectory(qsortfilterproxymodel_regularexpression) + add_subdirectory(qsortfilterproxymodel) endif() if(TARGET Qt::Sql AND TARGET Qt::Widgets) add_subdirectory(qitemmodel) diff --git a/tests/auto/corelib/itemmodels/qabstractitemmodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qabstractitemmodel/CMakeLists.txt index 2f91f7d41a..e5c7c08fc8 100644 --- a/tests/auto/corelib/itemmodels/qabstractitemmodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qabstractitemmodel/CMakeLists.txt @@ -1,17 +1,23 @@ -# Generated from qabstractitemmodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractitemmodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractitemmodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractitemmodel SOURCES ../../../other/qabstractitemmodelutils/dynamictreemodel.cpp ../../../other/qabstractitemmodelutils/dynamictreemodel.h tst_qabstractitemmodel.cpp - DEFINES - QT_DISABLE_DEPRECATED_BEFORE=0 INCLUDE_DIRECTORIES ../../../other/qabstractitemmodelutils - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui + Qt::TestPrivate ) diff --git a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp index 5719d9e046..36eb9320a4 100644 --- a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp +++ b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp @@ -1,33 +1,10 @@ -/**************************************************************************** -** -** 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 <QTest> +#include <QtTest/private/qcomparisontesthelper_p.h> + #include <QtCore/QCoreApplication> #include <QtCore/QSortFilterProxyModel> #include <QtCore/QStringListModel> @@ -81,6 +58,7 @@ private slots: void reset(); void complexChangesWithPersistent(); + void modelIndexComparisons(); void testMoveSameParentUp_data(); void testMoveSameParentUp(); @@ -181,8 +159,8 @@ QtTestModel::QtTestModel(const QList<QList<QString> > tbl, QObject *parent) : QAbstractItemModel(parent), wrongIndex(false) { table = tbl; - rCount = tbl.count(); - cCount = tbl.at(0).count(); + rCount = tbl.size(); + cCount = tbl.at(0).size(); } QModelIndex QtTestModel::index(int row, int column, const QModelIndex &parent) const @@ -216,7 +194,7 @@ bool QtTestModel::insertRows(int row, int count, const QModelIndex &parent) QAbstractItemModel::beginInsertRows(parent, row, row + count - 1); int cc = columnCount(parent); table.insert(row, count, QList<QString>(cc)); - rCount = table.count(); + rCount = table.size(); QAbstractItemModel::endInsertRows(); return true; } @@ -227,7 +205,7 @@ bool QtTestModel::insertColumns(int column, int count, const QModelIndex &parent int rc = rowCount(parent); for (int i = 0; i < rc; ++i) table[i].insert(column, 1, ""); - cCount = table.at(0).count(); + cCount = table.at(0).size(); QAbstractItemModel::endInsertColumns(); return true; } @@ -243,7 +221,7 @@ bool QtTestModel::removeRows( int row, int count, const QModelIndex & parent) for (int r = row+count-1; r >= row; --r) table.remove(r); - rCount = table.count(); + rCount = table.size(); QAbstractItemModel::endRemoveRows(); return true; @@ -257,7 +235,7 @@ bool QtTestModel::removeColumns(int column, int count, const QModelIndex & paren for (int r = 0; r < rCount; ++r) table[r].remove(c); - cCount = table.at(0).count(); + cCount = table.at(0).size(); QAbstractItemModel::endRemoveColumns(); return true; @@ -285,7 +263,7 @@ bool QtTestModel::moveRows(const QModelIndex &sourceParent, int src, int cnt, } } - rCount = table.count(); + rCount = table.size(); QAbstractItemModel::endMoveRows(); return true; @@ -315,7 +293,7 @@ bool QtTestModel::moveColumns(const QModelIndex &sourceParent, int src, int cnt, } } - cCount = table.at(0).count(); + cCount = table.at(0).size(); QAbstractItemModel::endMoveColumns(); return true; @@ -439,11 +417,11 @@ void tst_QAbstractItemModel::itemFlags() void tst_QAbstractItemModel::match() { - QtTestModel model(4, 1); + QtTestModel model(5, 1); QModelIndex start = model.index(0, 0, QModelIndex()); QVERIFY(start.isValid()); QModelIndexList res = model.match(start, Qt::DisplayRole, QVariant("1"), 3); - QCOMPARE(res.count(), 1); + QCOMPARE(res.size(), 1); QModelIndex idx = model.index(1, 0, QModelIndex()); bool areEqual = (idx == res.first()); QVERIFY(areEqual); @@ -452,44 +430,45 @@ void tst_QAbstractItemModel::match() model.setData(model.index(1, 0, QModelIndex()), "cat", Qt::DisplayRole); model.setData(model.index(2, 0, QModelIndex()), "dog", Qt::DisplayRole); model.setData(model.index(3, 0, QModelIndex()), "boar", Qt::DisplayRole); + model.setData(model.index(4, 0, QModelIndex()), "bo/a/r", Qt::DisplayRole); // QTBUG-104585 res = model.match(start, Qt::DisplayRole, QVariant("dog"), -1, Qt::MatchExactly); - QCOMPARE(res.count(), 1); + QCOMPARE(res.size(), 1); res = model.match(start, Qt::DisplayRole, QVariant("a"), -1, Qt::MatchContains); - QCOMPARE(res.count(), 3); + QCOMPARE(res.size(), 4); res = model.match(start, Qt::DisplayRole, QVariant("b"), -1, Qt::MatchStartsWith); - QCOMPARE(res.count(), 2); + QCOMPARE(res.size(), 3); res = model.match(start, Qt::DisplayRole, QVariant("t"), -1, Qt::MatchEndsWith); - QCOMPARE(res.count(), 2); + QCOMPARE(res.size(), 2); res = model.match(start, Qt::DisplayRole, QVariant("*a*"), -1, Qt::MatchWildcard); - QCOMPARE(res.count(), 3); + QCOMPARE(res.size(), 4); res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegularExpression); - QCOMPARE(res.count(), 2); + QCOMPARE(res.size(), 3); res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegularExpression | Qt::MatchCaseSensitive); - QCOMPARE(res.count(), 0); + QCOMPARE(res.size(), 0); res = model.match(start, Qt::DisplayRole, QVariant("BOAR"), -1, Qt::MatchFixedString); - QCOMPARE(res.count(), 1); + QCOMPARE(res.size(), 1); res = model.match(start, Qt::DisplayRole, QVariant("bat"), -1, Qt::MatchFixedString | Qt::MatchCaseSensitive); - QCOMPARE(res.count(), 1); + QCOMPARE(res.size(), 1); res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegularExpression); - QCOMPARE(res.count(), 2); + QCOMPARE(res.size(), 3); res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegularExpression | Qt::MatchCaseSensitive); - QCOMPARE(res.count(), 0); + QCOMPARE(res.size(), 0); res = model.match(start, Qt::DisplayRole, QVariant(QRegularExpression(".*O.*")), -1, Qt::MatchRegularExpression); - QCOMPARE(res.count(), 0); + QCOMPARE(res.size(), 0); res = model.match(start, Qt::DisplayRole, QVariant(QRegularExpression(".*O.*", QRegularExpression::CaseInsensitiveOption)), -1, Qt::MatchRegularExpression); - QCOMPARE(res.count(), 2); + QCOMPARE(res.size(), 3); // Ensure that the case sensitivity is properly ignored when passing a // QRegularExpression object. @@ -499,7 +478,7 @@ void tst_QAbstractItemModel::match() QRegularExpression::CaseInsensitiveOption)), -1, Qt::MatchRegularExpression | Qt::MatchCaseSensitive); - QCOMPARE(res.count(), 2); + QCOMPARE(res.size(), 3); } typedef QPair<int, int> Position; @@ -782,7 +761,7 @@ void tst_QAbstractItemModel::dropMimeData() // get the mimeData from the "selected" indexes QModelIndexList selectedIndexes; - for (int i = 0; i < selection.count(); ++i) + for (int i = 0; i < selection.size(); ++i) selectedIndexes << src.index(selection.at(i).first, selection.at(i).second, QModelIndex()); QMimeData *md = src.mimeData(selectedIndexes); // do the drop @@ -853,8 +832,8 @@ void tst_QAbstractItemModel::removeRows() QVERIFY(rowsRemovedSpy.isValid()); QCOMPARE(model.removeRows(6, 4), true); - QCOMPARE(rowsAboutToBeRemovedSpy.count(), 1); - QCOMPARE(rowsRemovedSpy.count(), 1); + QCOMPARE(rowsAboutToBeRemovedSpy.size(), 1); + QCOMPARE(rowsRemovedSpy.size(), 1); } void tst_QAbstractItemModel::removeColumns() @@ -868,8 +847,8 @@ void tst_QAbstractItemModel::removeColumns() QVERIFY(columnsRemovedSpy.isValid()); QCOMPARE(model.removeColumns(6, 4), true); - QCOMPARE(columnsAboutToBeRemovedSpy.count(), 1); - QCOMPARE(columnsRemovedSpy.count(), 1); + QCOMPARE(columnsAboutToBeRemovedSpy.size(), 1); + QCOMPARE(columnsRemovedSpy.size(), 1); } void tst_QAbstractItemModel::insertRows() @@ -883,8 +862,8 @@ void tst_QAbstractItemModel::insertRows() QVERIFY(rowsInsertedSpy.isValid()); QCOMPARE(model.insertRows(6, 4), true); - QCOMPARE(rowsAboutToBeInsertedSpy.count(), 1); - QCOMPARE(rowsInsertedSpy.count(), 1); + QCOMPARE(rowsAboutToBeInsertedSpy.size(), 1); + QCOMPARE(rowsInsertedSpy.size(), 1); } void tst_QAbstractItemModel::insertColumns() @@ -898,8 +877,8 @@ void tst_QAbstractItemModel::insertColumns() QVERIFY(columnsInsertedSpy.isValid()); QCOMPARE(model.insertColumns(6, 4), true); - QCOMPARE(columnsAboutToBeInsertedSpy.count(), 1); - QCOMPARE(columnsInsertedSpy.count(), 1); + QCOMPARE(columnsAboutToBeInsertedSpy.size(), 1); + QCOMPARE(columnsInsertedSpy.size(), 1); } void tst_QAbstractItemModel::moveRows() @@ -913,8 +892,8 @@ void tst_QAbstractItemModel::moveRows() QVERIFY(rowsMovedSpy.isValid()); QCOMPARE(model.moveRows(QModelIndex(), 6, 4, QModelIndex(), 1), true); - QCOMPARE(rowsAboutToBeMovedSpy.count(), 1); - QCOMPARE(rowsMovedSpy.count(), 1); + QCOMPARE(rowsAboutToBeMovedSpy.size(), 1); + QCOMPARE(rowsMovedSpy.size(), 1); } void tst_QAbstractItemModel::moveColumns() @@ -928,12 +907,12 @@ void tst_QAbstractItemModel::moveColumns() QVERIFY(columnsMovedSpy.isValid()); QCOMPARE(model.moveColumns(QModelIndex(), 6, 4, QModelIndex(), 1), true); - QCOMPARE(columnsAboutToBeMovedSpy.count(), 1); - QCOMPARE(columnsMovedSpy.count(), 1); + QCOMPARE(columnsAboutToBeMovedSpy.size(), 1); + QCOMPARE(columnsMovedSpy.size(), 1); QCOMPARE(model.moveColumn(QModelIndex(), 4, QModelIndex(), 1), true); - QCOMPARE(columnsAboutToBeMovedSpy.count(), 2); - QCOMPARE(columnsMovedSpy.count(), 2); + QCOMPARE(columnsAboutToBeMovedSpy.size(), 2); + QCOMPARE(columnsMovedSpy.size(), 2); } void tst_QAbstractItemModel::reset() @@ -943,7 +922,7 @@ void tst_QAbstractItemModel::reset() QSignalSpy resetSpy(&model, &QtTestModel::modelReset); QVERIFY(resetSpy.isValid()); model.reset(); - QCOMPARE(resetSpy.count(), 1); + QCOMPARE(resetSpy.size(), 1); } void tst_QAbstractItemModel::complexChangesWithPersistent() @@ -1008,6 +987,27 @@ void tst_QAbstractItemModel::complexChangesWithPersistent() QVERIFY(e[i] == model.index(2, i-2 , QModelIndex())); } +void tst_QAbstractItemModel::modelIndexComparisons() +{ + QTestPrivate::testEqualityOperatorsCompile<QModelIndex>(); + QTestPrivate::testEqualityOperatorsCompile<QPersistentModelIndex>(); + QTestPrivate::testEqualityOperatorsCompile<QPersistentModelIndex, QModelIndex>(); + + QtTestModel model(3, 3); + + QModelIndex mi11 = model.index(1, 1); + QModelIndex mi22 = model.index(2, 2); + QPersistentModelIndex pmi11 = mi11; + QPersistentModelIndex pmi22 = mi22; + + QT_TEST_EQUALITY_OPS(mi11, mi11, true); + QT_TEST_EQUALITY_OPS(mi11, mi22, false); + QT_TEST_EQUALITY_OPS(pmi11, pmi11, true); + QT_TEST_EQUALITY_OPS(pmi11, pmi22, false); + QT_TEST_EQUALITY_OPS(pmi11, mi11, true); + QT_TEST_EQUALITY_OPS(pmi11, mi22, false); +} + void tst_QAbstractItemModel::testMoveSameParentDown_data() { QTest::addColumn<int>("startRow"); @@ -1872,7 +1872,7 @@ void ListenerObject::slotAboutToBeReset() void ListenerObject::slotReset() { - for (const auto &idx : qAsConst(m_persistentIndexes)) { + for (const auto &idx : std::as_const(m_persistentIndexes)) { QVERIFY(!idx.isValid()); } } diff --git a/tests/auto/corelib/itemmodels/qabstractproxymodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qabstractproxymodel/CMakeLists.txt index 277556b915..8799814324 100644 --- a/tests/auto/corelib/itemmodels/qabstractproxymodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qabstractproxymodel/CMakeLists.txt @@ -1,14 +1,20 @@ -# Generated from qabstractproxymodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractproxymodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractproxymodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractproxymodel SOURCES tst_qabstractproxymodel.cpp - DEFINES - QT_DISABLE_DEPRECATED_BEFORE=0 - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui + Qt::TestPrivate ) diff --git a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp index b6ee3c5d4a..62512889fd 100644 --- a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp @@ -1,32 +1,8 @@ -/**************************************************************************** -** -** 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) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> +#include <QtTest/private/qpropertytesthelper_p.h> #include <qabstractproxymodel.h> #include <QItemSelection> #include <qstandarditemmodel.h> @@ -43,6 +19,7 @@ private slots: void flags(); void headerData_data(); void headerData(); + void headerDataInBounds(); void itemData_data(); void itemData(); void mapFromSource_data(); @@ -60,6 +37,7 @@ private slots: void testRoleNames(); void testSwappingRowsProxy(); void testDragAndDrop(); + void sourceModelBinding(); }; // Subclass that exposes the protected functions. @@ -172,6 +150,133 @@ void tst_QAbstractProxyModel::headerData() QCOMPARE(model.headerData(section, orientation, role), headerData); } +class SimpleTableReverseColumnsProxy : public QAbstractProxyModel +{ +public: + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override + { + if (parent.isValid()) + return {}; + + if (row < 0 || row >= rowCount() || column < 0 || column >= columnCount()) + qFatal("error"); // cannot QFAIL here + + return createIndex(row, column); + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const override + { + if (parent.isValid()) + return 0; + return sourceModel()->rowCount(); + } + + int columnCount(const QModelIndex &parent = QModelIndex()) const override + { + if (parent.isValid()) + return 0; + return sourceModel()->columnCount(); + } + + QModelIndex parent(const QModelIndex &) const override + { + return QModelIndex(); + } + + QModelIndex mapToSource(const QModelIndex &idx) const override + { + if (!idx.isValid()) + return QModelIndex(); + return sourceModel()->index(idx.row(), columnCount() - 1 - idx.column()); + } + + QModelIndex mapFromSource(const QModelIndex &idx) const override + { + if (idx.parent().isValid()) + return QModelIndex(); + return createIndex(idx.row(), columnCount() - 1 - idx.column()); + } +}; + +void tst_QAbstractProxyModel::headerDataInBounds() +{ + QStandardItemModel qsim(0, 5); + qsim.setHorizontalHeaderLabels({"Col1", "Col2", "Col3", "Col4", "Col5"}); + + SimpleTableReverseColumnsProxy proxy; + QSignalSpy headerDataChangedSpy(&proxy, &QAbstractItemModel::headerDataChanged); + QVERIFY(headerDataChangedSpy.isValid()); + proxy.setSourceModel(&qsim); + QCOMPARE(proxy.rowCount(), 0); + QCOMPARE(proxy.columnCount(), 5); + + for (int i = 0; i < proxy.columnCount(); ++i) { + QString expected = QString("Col%1").arg(i + 1); + QCOMPARE(proxy.headerData(i, Qt::Horizontal).toString(), expected); + } + + qsim.appendRow({ + new QStandardItem("A"), + new QStandardItem("B"), + new QStandardItem("C"), + new QStandardItem("D"), + new QStandardItem("E") + }); + + QCOMPARE(proxy.rowCount(), 1); + QCOMPARE(proxy.columnCount(), 5); + QTRY_COMPARE(headerDataChangedSpy.size(), 1); + QCOMPARE(headerDataChangedSpy[0][0].value<Qt::Orientation>(), Qt::Horizontal); + QCOMPARE(headerDataChangedSpy[0][1].value<int>(), 0); + QCOMPARE(headerDataChangedSpy[0][2].value<int>(), 4); + + for (int i = 0; i < proxy.columnCount(); ++i) { + QString expected = QString("Col%1").arg(proxy.columnCount() - i); + QCOMPARE(proxy.headerData(i, Qt::Horizontal).toString(), expected); + } + + qsim.appendRow({ + new QStandardItem("A"), + new QStandardItem("B"), + new QStandardItem("C"), + new QStandardItem("D"), + new QStandardItem("E") + }); + QCOMPARE(proxy.rowCount(), 2); + QCOMPARE(proxy.columnCount(), 5); + QCOMPARE(headerDataChangedSpy.size(), 1); + + for (int i = 0; i < proxy.columnCount(); ++i) { + QString expected = QString("Col%1").arg(proxy.columnCount() - i); + QCOMPARE(proxy.headerData(i, Qt::Horizontal).toString(), expected); + } + + QVERIFY(qsim.removeRows(0, 1)); + + QCOMPARE(proxy.rowCount(), 1); + QCOMPARE(proxy.columnCount(), 5); + QCOMPARE(headerDataChangedSpy.size(), 1); + + for (int i = 0; i < proxy.columnCount(); ++i) { + QString expected = QString("Col%1").arg(proxy.columnCount() - i); + QCOMPARE(proxy.headerData(i, Qt::Horizontal).toString(), expected); + } + + QVERIFY(qsim.removeRows(0, 1)); + + QCOMPARE(proxy.rowCount(), 0); + QCOMPARE(proxy.columnCount(), 5); + QTRY_COMPARE(headerDataChangedSpy.size(), 2); + QCOMPARE(headerDataChangedSpy[1][0].value<Qt::Orientation>(), Qt::Horizontal); + QCOMPARE(headerDataChangedSpy[1][1].value<int>(), 0); + QCOMPARE(headerDataChangedSpy[1][2].value<int>(), 4); + + for (int i = 0; i < proxy.columnCount(); ++i) { + QString expected = QString("Col%1").arg(i + 1); + QCOMPARE(proxy.headerData(i, Qt::Horizontal).toString(), expected); + } +} + void tst_QAbstractProxyModel::itemData_data() { QTest::addColumn<QModelIndex>("index"); @@ -186,7 +291,7 @@ void tst_QAbstractProxyModel::itemData() QFETCH(QModelIndex, index); QFETCH(int, count); SubQAbstractProxyModel model; - QCOMPARE(model.itemData(index).count(), count); + QCOMPARE(model.itemData(index).size(), count); } void tst_QAbstractProxyModel::mapFromSource_data() @@ -500,6 +605,34 @@ void tst_QAbstractProxyModel::testDragAndDrop() QCOMPARE(proxy.supportedDropActions(), sourceModel.supportedDropActions()); } +void tst_QAbstractProxyModel::sourceModelBinding() +{ + SubQAbstractProxyModel proxy; + QStandardItemModel model1; + QStandardItemModel model2; + QTestPrivate::testReadWritePropertyBasics<SubQAbstractProxyModel, QAbstractItemModel *>( + proxy, &model1, &model2, "sourceModel"); + if (QTest::currentTestFailed()) { + qDebug("Failed model - model test"); + return; + } + + proxy.setSourceModel(&model2); + QTestPrivate::testReadWritePropertyBasics<SubQAbstractProxyModel, QAbstractItemModel *>( + proxy, &model1, nullptr, "sourceModel"); + if (QTest::currentTestFailed()) { + qDebug("Failed model - nullptr test"); + return; + } + + proxy.setSourceModel(&model1); + QTestPrivate::testReadWritePropertyBasics<SubQAbstractProxyModel, QAbstractItemModel *>( + proxy, nullptr, &model2, "sourceModel"); + if (QTest::currentTestFailed()) { + qDebug("Failed nullptr - model test"); + return; + } +} QTEST_MAIN(tst_QAbstractProxyModel) #include "tst_qabstractproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/CMakeLists.txt index 40dd512489..37a74470af 100644 --- a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qconcatenatetablesproxymodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qconcatenatetablesproxymodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qconcatenatetablesproxymodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qconcatenatetablesproxymodel SOURCES tst_qconcatenatetablesproxymodel.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp index 40617c1f7d..989a57b30f 100644 --- a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QSignalSpy> #include <QSortFilterProxyModel> @@ -82,9 +46,9 @@ static QString rowSpyToText(const QSignalSpy &spy) if (!spy.isValid()) return QStringLiteral("THE SIGNALSPY IS INVALID!"); QString str; - for (int i = 0; i < spy.count(); ++i) { + for (int i = 0; i < spy.size(); ++i) { str += spy.at(i).at(1).toString() + QLatin1Char(',') + spy.at(i).at(2).toString(); - if (i + 1 < spy.count()) + if (i + 1 < spy.size()) str += QLatin1Char(';'); } return str; @@ -116,7 +80,9 @@ private Q_SLOTS: void shouldPropagateDropBetweenItemsAtModelBoundary(); void shouldPropagateDropAfterLastRow_data(); void shouldPropagateDropAfterLastRow(); - + void qtbug91788(); + void qtbug91878(); + void createPersistentOnLayoutAboutToBeChanged(); private: QStandardItemModel mod; QStandardItemModel mod2; @@ -183,8 +149,8 @@ void tst_QConcatenateTablesProxyModel::shouldAggregateThenRemoveTwoEmptyModelsCo // Then the proxy should still be empty (and no signals emitted) QCOMPARE(pm.rowCount(), 0); QCOMPARE(pm.columnCount(), 0); - QCOMPARE(rowATBISpy.count(), 0); - QCOMPARE(rowInsertedSpy.count(), 0); + QCOMPARE(rowATBISpy.size(), 0); + QCOMPARE(rowInsertedSpy.size(), 0); // When removing the empty models pm.removeSourceModel(&i1); @@ -193,8 +159,8 @@ void tst_QConcatenateTablesProxyModel::shouldAggregateThenRemoveTwoEmptyModelsCo // Then the proxy should still be empty (and no signals emitted) QCOMPARE(pm.rowCount(), 0); QCOMPARE(pm.columnCount(), 0); - QCOMPARE(rowATBRSpy.count(), 0); - QCOMPARE(rowRemovedSpy.count(), 0); + QCOMPARE(rowATBRSpy.size(), 0); + QCOMPARE(rowRemovedSpy.size(), 0); } void tst_QConcatenateTablesProxyModel::shouldAggregateTwoEmptyModelsWhichThenGetFilled() @@ -239,14 +205,14 @@ void tst_QConcatenateTablesProxyModel::shouldHandleDataChanged() mod.item(0, 0)->setData("a", Qt::EditRole); // Then the change should be notified to the proxy - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0)); QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("aBC")); // Same test with the other model mod2.item(0, 2)->setData("f", Qt::EditRole); - QCOMPARE(dataChangedSpy.count(), 2); + QCOMPARE(dataChangedSpy.size(), 2); QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2)); QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEf")); } @@ -264,14 +230,14 @@ void tst_QConcatenateTablesProxyModel::shouldHandleSetData() pm.setData(pm.index(0, 0), "a"); // Then the change should be notified to the proxy - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0)); QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("aBC")); // Same test with the other model pm.setData(pm.index(1, 2), "f"); - QCOMPARE(dataChangedSpy.count(), 2); + QCOMPARE(dataChangedSpy.size(), 2); QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2)); QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEf")); } @@ -290,7 +256,7 @@ void tst_QConcatenateTablesProxyModel::shouldHandleSetItemData() std::make_pair<int, QVariant>(Qt::UserRole, 88) }); // Then the change should be notified to the proxy - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0)); QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("XBC")); QCOMPARE(pm.index(0, 0).data(Qt::UserRole).toInt(), 88); @@ -299,7 +265,7 @@ void tst_QConcatenateTablesProxyModel::shouldHandleSetItemData() pm.setItemData(pm.index(1, 2), QMap<int, QVariant>{ std::make_pair<int, QVariant>(Qt::DisplayRole, QStringLiteral("Y")), std::make_pair<int, QVariant>(Qt::UserRole, 89) }); - QCOMPARE(dataChangedSpy.count(), 2); + QCOMPARE(dataChangedSpy.size(), 2); QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2)); QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEY")); QCOMPARE(pm.index(1, 2).data(Qt::UserRole).toInt(), 89); @@ -336,10 +302,10 @@ void tst_QConcatenateTablesProxyModel::shouldHandleRowInsertionAndRemoval() mod2.removeRow(0); // Then the proxy should notify its users and show changes - QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.size(), 1); QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1); QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1); - QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.size(), 1); QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1); QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1); QCOMPARE(pm.rowCount(), 2); @@ -352,10 +318,10 @@ void tst_QConcatenateTablesProxyModel::shouldHandleRowInsertionAndRemoval() mod2.removeRow(0); // Then the proxy should notify its users and show changes - QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.size(), 1); QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1); QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1); - QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.size(), 1); QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1); QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1); QCOMPARE(pm.rowCount(), 1); @@ -391,10 +357,10 @@ void tst_QConcatenateTablesProxyModel::shouldAggregateAnotherModelThenRemoveMode pm.removeSourceModel(&mod3); // Then the proxy should notify its users about the row removed - QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.size(), 1); QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 2); QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 3); - QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.size(), 1); QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 2); QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 3); QCOMPARE(pm.rowCount(), 2); @@ -405,10 +371,10 @@ void tst_QConcatenateTablesProxyModel::shouldAggregateAnotherModelThenRemoveMode rowATBRSpy.clear(); rowRemovedSpy.clear(); pm.removeSourceModel(&mod2); - QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.size(), 1); QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1); QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1); - QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.size(), 1); QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1); QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1); QCOMPARE(pm.rowCount(), 1); @@ -418,10 +384,10 @@ void tst_QConcatenateTablesProxyModel::shouldAggregateAnotherModelThenRemoveMode rowATBRSpy.clear(); rowRemovedSpy.clear(); pm.removeSourceModel(&mod); - QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.size(), 1); QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 0); QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 0); - QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.size(), 1); QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 0); QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 0); QCOMPARE(pm.rowCount(), 0); @@ -453,6 +419,17 @@ void tst_QConcatenateTablesProxyModel::shouldUseSmallestColumnCount() const QModelIndex indexD = pm.mapFromSource(mod2.index(0, 0)); QVERIFY(indexD.isValid()); QCOMPARE(indexD, pm.index(1, 0)); + + // Test setData in an ignored column (QTBUG-91253) + QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + mod.setData(mod.index(0, 1), "b"); + QCOMPARE(dataChangedSpy.size(), 0); + + // Test dataChanged across all columns, some visible, some ignored + mod.dataChanged(mod.index(0, 0), mod.index(0, 2)); + QCOMPARE(dataChangedSpy.size(), 1); + QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0)); + QCOMPARE(dataChangedSpy.at(0).at(1).toModelIndex(), pm.index(0, 0)); } void tst_QConcatenateTablesProxyModel::shouldIncreaseColumnCountWhenRemovingFirstModel() @@ -540,8 +517,8 @@ void tst_QConcatenateTablesProxyModel::shouldPropagateLayoutChanged() QItemSelectionModel selection(&pm); selection.select(pm.index(1, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows); const QModelIndexList lst = selection.selectedIndexes(); - QCOMPARE(lst.count(), 3); - for (int col = 0; col < lst.count(); ++col) { + QCOMPARE(lst.size(), 3); + for (int col = 0; col < lst.size(); ++col) { QCOMPARE(lst.at(col).row(), 1); QCOMPARE(lst.at(col).column(), col); } @@ -556,13 +533,13 @@ void tst_QConcatenateTablesProxyModel::shouldPropagateLayoutChanged() QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("123")); - QCOMPARE(layoutATBCSpy.count(), 1); - QCOMPARE(layoutChangedSpy.count(), 1); + QCOMPARE(layoutATBCSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); // And the selection should be updated accordingly (it became row 2) const QModelIndexList lstAfter = selection.selectedIndexes(); - QCOMPARE(lstAfter.count(), 3); - for (int col = 0; col < lstAfter.count(); ++col) { + QCOMPARE(lstAfter.size(), 3); + for (int col = 0; col < lstAfter.size(); ++col) { QCOMPARE(lstAfter.at(col).row(), 2); QCOMPARE(lstAfter.at(col).column(), col); } @@ -597,14 +574,14 @@ void tst_QConcatenateTablesProxyModel::shouldReactToModelReset() // Then the proxy should emit the reset signals, and show the new data QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); - QCOMPARE(rowATBRSpy.count(), 0); - QCOMPARE(rowRemovedSpy.count(), 0); - QCOMPARE(rowATBISpy.count(), 0); - QCOMPARE(rowInsertedSpy.count(), 0); - QCOMPARE(colATBRSpy.count(), 0); - QCOMPARE(colRemovedSpy.count(), 0); - QCOMPARE(modelATBResetSpy.count(), 1); - QCOMPARE(modelResetSpy.count(), 1); + QCOMPARE(rowATBRSpy.size(), 0); + QCOMPARE(rowRemovedSpy.size(), 0); + QCOMPARE(rowATBISpy.size(), 0); + QCOMPARE(rowInsertedSpy.size(), 0); + QCOMPARE(colATBRSpy.size(), 0); + QCOMPARE(colRemovedSpy.size(), 0); + QCOMPARE(modelATBResetSpy.size(), 1); + QCOMPARE(modelResetSpy.size(), 1); } void tst_QConcatenateTablesProxyModel::shouldUpdateColumnsOnModelReset() @@ -639,14 +616,14 @@ void tst_QConcatenateTablesProxyModel::shouldUpdateColumnsOnModelReset() qsfpm.setSourceModel(&mod2Columns); // Then the proxy should reset, and show the new data - QCOMPARE(modelATBResetSpy.count(), 1); - QCOMPARE(modelResetSpy.count(), 1); - QCOMPARE(rowATBRSpy.count(), 0); - QCOMPARE(rowRemovedSpy.count(), 0); - QCOMPARE(rowATBISpy.count(), 0); - QCOMPARE(rowInsertedSpy.count(), 0); - QCOMPARE(colATBRSpy.count(), 0); - QCOMPARE(colRemovedSpy.count(), 0); + QCOMPARE(modelATBResetSpy.size(), 1); + QCOMPARE(modelResetSpy.size(), 1); + QCOMPARE(rowATBRSpy.size(), 0); + QCOMPARE(rowRemovedSpy.size(), 0); + QCOMPARE(rowATBISpy.size(), 0); + QCOMPARE(rowInsertedSpy.size(), 0); + QCOMPARE(colATBRSpy.size(), 0); + QCOMPARE(colRemovedSpy.size(), 0); QCOMPARE(pm.rowCount(), 2); QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("WX")); @@ -818,6 +795,73 @@ void tst_QConcatenateTablesProxyModel::shouldPropagateDropAfterLastRow() } +void tst_QConcatenateTablesProxyModel::qtbug91788() +{ + QConcatenateTablesProxyModel proxyConcat; + QStringList strList{QString("one"),QString("two")}; + QStringListModel strListModelA(strList); + QSortFilterProxyModel proxyFilter; + proxyFilter.setSourceModel(&proxyConcat); + + proxyConcat.addSourceModel(&strListModelA); + proxyConcat.removeSourceModel(&strListModelA); // This should not assert + QCOMPARE(proxyConcat.columnCount(), 0); +} + +void tst_QConcatenateTablesProxyModel::qtbug91878() +{ + QStandardItemModel m; + m.setRowCount(4); + m.setColumnCount(4); + + QConcatenateTablesProxyModel pm; + QSortFilterProxyModel proxyFilter; + proxyFilter.setSourceModel(&pm); + proxyFilter.setFilterFixedString("something"); + pm.addSourceModel(&m); // This should not assert + + QCOMPARE(pm.columnCount(), 4); + QCOMPARE(pm.rowCount(), 4); +} + +void tst_QConcatenateTablesProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466 +{ + QStandardItemModel model1(3, 1); + QStandardItemModel model2(3, 1); + for (int row = 0; row < 3; ++row) { + model1.setData(model1.index(row, 0), row); + model2.setData(model2.index(row, 0), row + 5); + } + QConcatenateTablesProxyModel proxy; + new QAbstractItemModelTester(&proxy, &proxy); + proxy.addSourceModel(&model1); + proxy.addSourceModel(&model2); + QList<QPersistentModelIndex> idxList; + QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged); + QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged); + connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){ + idxList.clear(); + for (int row = 0; row < 3; ++row) + idxList << QPersistentModelIndex(proxy.index(row, 0)); + }); + connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){ + QCOMPARE(idxList.size(), 3); + QCOMPARE(idxList.at(0).row(), 1); + QCOMPARE(idxList.at(0).column(), 0); + QCOMPARE(idxList.at(0).data().toInt(), 0); + QCOMPARE(idxList.at(1).row(), 0); + QCOMPARE(idxList.at(1).column(), 0); + QCOMPARE(idxList.at(1).data().toInt(), -1); + QCOMPARE(idxList.at(2).row(), 2); + QCOMPARE(idxList.at(2).column(), 0); + QCOMPARE(idxList.at(2).data().toInt(), 2); + }); + QVERIFY(model1.setData(model1.index(1, 0), -1)); + model1.sort(0); + QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); +} + QTEST_GUILESS_MAIN(tst_QConcatenateTablesProxyModel) #include "tst_qconcatenatetablesproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qidentityproxymodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qidentityproxymodel/CMakeLists.txt index fb2ae55215..87a2cdcba1 100644 --- a/tests/auto/corelib/itemmodels/qidentityproxymodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qidentityproxymodel/CMakeLists.txt @@ -1,15 +1,22 @@ -# Generated from qidentityproxymodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qidentityproxymodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qidentityproxymodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qidentityproxymodel SOURCES ../../../other/qabstractitemmodelutils/dynamictreemodel.cpp ../../../other/qabstractitemmodelutils/dynamictreemodel.h tst_qidentityproxymodel.cpp INCLUDE_DIRECTORIES ../../../other/qabstractitemmodelutils - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp index 4828df8b94..99b74bc09a 100644 --- a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module 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) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QAbstractItemModelTester> #include <QCoreApplication> @@ -52,6 +27,16 @@ public: const QModelIndex idx = index(0, 0, QModelIndex()); Q_EMIT dataChanged(idx, idx, QList<int>() << 1); } + + // Workaround QObject::isSignalConnected() being a protected method + bool isConnected(const QMetaMethod &m) const { return isSignalConnected(m); } +}; + +class IdentityProxyModel : public QIdentityProxyModel +{ +public: + // The name has to be different than the method from the base class + void setHandleSLC(bool b) { setHandleSourceLayoutChanges(b); } }; class tst_QIdentityProxyModel : public QObject @@ -77,6 +62,9 @@ private slots: void itemData(); void persistIndexOnLayoutChange(); + void createPersistentOnLayoutAboutToBeChanged(); + + void testSetHandleLayoutChanges(); protected: void verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent = QModelIndex()); @@ -404,8 +392,17 @@ public: const QVariant result = QIdentityProxyModel::data(index, role); if (role != Qt::DisplayRole) return result; - return result.toString() + "_appended"; + return result.toString() + QLatin1String("_appended"); } + QMap<int, QVariant> itemData(const QModelIndex &index) const override + { + QMap<int, QVariant> result = QIdentityProxyModel::itemData(index); + auto displayIter = result.find(Qt::DisplayRole); + if (displayIter != result.end()) + displayIter.value() = displayIter.value().toString() + QLatin1String("_appended"); + return result; + } + }; void tst_QIdentityProxyModel::itemData() @@ -494,5 +491,62 @@ void tst_QIdentityProxyModel::persistIndexOnLayoutChange() QVERIFY(persistentIndex.isValid()); } +void tst_QIdentityProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466 +{ + QStandardItemModel model(3, 1); + for (int row = 0; row < 3; ++row) + model.setData(model.index(row, 0), row, Qt::UserRole); + model.setSortRole(Qt::UserRole); + QIdentityProxyModel proxy; + new QAbstractItemModelTester(&proxy, &proxy); + proxy.setSourceModel(&model); + QList<QPersistentModelIndex> idxList; + QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged); + QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged); + connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){ + idxList.clear(); + for (int row = 0; row < 3; ++row) + idxList << QPersistentModelIndex(proxy.index(row, 0)); + }); + connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){ + QCOMPARE(idxList.size(), 3); + QCOMPARE(idxList.at(0).row(), 1); + QCOMPARE(idxList.at(0).column(), 0); + QCOMPARE(idxList.at(0).data(Qt::UserRole).toInt(), 0); + QCOMPARE(idxList.at(1).row(), 0); + QCOMPARE(idxList.at(1).column(), 0); + QCOMPARE(idxList.at(1).data(Qt::UserRole).toInt(), -1); + QCOMPARE(idxList.at(2).row(), 2); + QCOMPARE(idxList.at(2).column(), 0); + QCOMPARE(idxList.at(2).data(Qt::UserRole).toInt(), 2); + }); + model.setData(model.index(1, 0), -1, Qt::UserRole); + model.sort(0); + QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); +} + +void tst_QIdentityProxyModel::testSetHandleLayoutChanges() +{ + const std::array layoutSignals = { + QMetaMethod::fromSignal(&QAbstractItemModel::layoutChanged), + QMetaMethod::fromSignal(&QAbstractItemModel::layoutAboutToBeChanged), + }; + + DataChangedModel model; + IdentityProxyModel proxy; + proxy.setSourceModel(&model); + for (const auto &m : layoutSignals) + QVERIFY(model.isConnected(m)); // Connected by default + + proxy.setSourceModel(nullptr); + + // Disable handling (connecting to layotu signals) of source model layout changes + proxy.setHandleSLC(false); + proxy.setSourceModel(&model); + for (const auto &m : layoutSignals) + QVERIFY(!model.isConnected(m)); +} + QTEST_MAIN(tst_QIdentityProxyModel) #include "tst_qidentityproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qitemmodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qitemmodel/CMakeLists.txt index 7dda1a3964..57d9ba4913 100644 --- a/tests/auto/corelib/itemmodels/qitemmodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qitemmodel/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qitemmodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qitemmodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qitemmodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qitemmodel SOURCES tst_qitemmodel.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::Sql Qt::Widgets diff --git a/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp b/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp index 3eb6c15ec2..b2d507875d 100644 --- a/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp +++ b/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.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 <QTest> @@ -142,14 +117,14 @@ QAbstractItemModel *ModelsToTest::createModel(const QString &modelType) if (modelType == "QSortFilterProxyModelEmpty") { QSortFilterProxyModel *model = new QSortFilterProxyModel; - QStandardItemModel *standardItemModel = new QStandardItemModel; + QStandardItemModel *standardItemModel = new QStandardItemModel(model); model->setSourceModel(standardItemModel); return model; } if (modelType == "QSortFilterProxyModelRegExp") { QSortFilterProxyModel *model = new QSortFilterProxyModel; - QStandardItemModel *standardItemModel = new QStandardItemModel; + QStandardItemModel *standardItemModel = new QStandardItemModel(model); model->setSourceModel(standardItemModel); populateTestArea(model); model->setFilterRegularExpression(QRegularExpression("(^$|I.*)")); @@ -158,7 +133,7 @@ QAbstractItemModel *ModelsToTest::createModel(const QString &modelType) if (modelType == "QSortFilterProxyModel") { QSortFilterProxyModel *model = new QSortFilterProxyModel; - QStandardItemModel *standardItemModel = new QStandardItemModel; + QStandardItemModel *standardItemModel = new QStandardItemModel(model); model->setSourceModel(standardItemModel); populateTestArea(model); return model; diff --git a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp index 40495c1d9e..b1f91fe9a3 100644 --- a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp +++ b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.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 <QTest> #include <QSignalSpy> @@ -612,7 +587,7 @@ void tst_QItemModel::setData() QVERIFY(currentModel); QSignalSpy spy(currentModel, &QAbstractItemModel::dataChanged); QVERIFY(spy.isValid()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QFETCH(bool, isEmpty); if (isEmpty) @@ -636,7 +611,7 @@ void tst_QItemModel::setData() // Changing the text shouldn't change the layout, parent, pointer etc. QModelIndex changedIndex = currentModel->index(0, 0, topIndex); QCOMPARE(changedIndex, index); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QItemModel::setHeaderData_data() @@ -686,7 +661,7 @@ void tst_QItemModel::setHeaderData() ++signalCount; } } - QCOMPARE(spy.count(), signalCount); + QCOMPARE(spy.size(), signalCount); } void tst_QItemModel::sort_data() @@ -717,7 +692,7 @@ void tst_QItemModel::sort() for (int i=-1; i < 10; ++i){ currentModel->sort(i); if (index != currentModel->index(0, 0, topIndex)){ - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); index = currentModel->index(0, 0, topIndex); spy.clear(); } @@ -883,7 +858,7 @@ void tst_QItemModel::remove() if (shouldSucceed && dyingIndex.isValid()) QCOMPARE(dyingIndex.row(), start + 1); - if (rowsAboutToBeRemovedSpy.count() > 0){ + if (rowsAboutToBeRemovedSpy.size() > 0){ QList<QVariant> arguments = rowsAboutToBeRemovedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); @@ -893,7 +868,7 @@ void tst_QItemModel::remove() QVERIFY(parentOfRemoved == parent); } - if (rowsRemovedSpy.count() > 0){ + if (rowsRemovedSpy.size() > 0){ QList<QVariant> arguments = rowsRemovedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); @@ -904,26 +879,26 @@ void tst_QItemModel::remove() } // Only the row signals should have been emitted - if (modelResetSpy.count() >= 1 || modelLayoutChangedSpy.count() >=1 ){ - QCOMPARE(columnsAboutToBeRemovedSpy.count(), 0); - QCOMPARE(rowsAboutToBeRemovedSpy.count(), 0); - QCOMPARE(columnsRemovedSpy.count(), 0); - QCOMPARE(rowsRemovedSpy.count(), 0); + if (modelResetSpy.size() >= 1 || modelLayoutChangedSpy.size() >=1 ){ + QCOMPARE(columnsAboutToBeRemovedSpy.size(), 0); + QCOMPARE(rowsAboutToBeRemovedSpy.size(), 0); + QCOMPARE(columnsRemovedSpy.size(), 0); + QCOMPARE(rowsRemovedSpy.size(), 0); } else { - QCOMPARE(columnsAboutToBeRemovedSpy.count(), 0); - QCOMPARE(rowsAboutToBeRemovedSpy.count(), numberOfRowsAboutToBeRemovedSignals); - QCOMPARE(columnsRemovedSpy.count(), 0); - QCOMPARE(rowsRemovedSpy.count(), numberOfRowsRemovedSignals); + QCOMPARE(columnsAboutToBeRemovedSpy.size(), 0); + QCOMPARE(rowsAboutToBeRemovedSpy.size(), numberOfRowsAboutToBeRemovedSignals); + QCOMPARE(columnsRemovedSpy.size(), 0); + QCOMPARE(rowsRemovedSpy.size(), numberOfRowsRemovedSignals); } // The row count should only change *after* rowsAboutToBeRemoved has been emitted if (shouldSucceed) { - if (modelResetSpy.count() == 0 && modelLayoutChangedSpy.count() == 0){ + if (modelResetSpy.size() == 0 && modelLayoutChangedSpy.size() == 0){ QCOMPARE(afterAboutToRemoveRowCount, beforeRemoveRowCount); QCOMPARE(afterRemoveRowCount, beforeRemoveRowCount-count-(numberOfRowsRemovedSignals-1)); } - if (modelResetSpy.count() == 0 ) + if (modelResetSpy.size() == 0 ) QCOMPARE(currentModel->rowCount(parentOfRemoved), beforeRemoveRowCount-count-(numberOfRowsRemovedSignals-1)); } else { @@ -938,7 +913,7 @@ void tst_QItemModel::remove() disconnect(currentModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(slot_rowsRemoved(QModelIndex))); modelResetSpy.clear(); - QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(modelResetSpy.size(), 0); // // Test remove column @@ -953,26 +928,26 @@ void tst_QItemModel::remove() if (currentModel->removeColumns(start, count, parentOfRemoved)) { currentModel->submit(); // Didn't reset the rows, so they should still be at the same value - if (modelResetSpy.count() >= 1 || modelLayoutChangedSpy.count() >= 1){ - QCOMPARE(columnsAboutToBeRemovedSpy.count(), 0); + if (modelResetSpy.size() >= 1 || modelLayoutChangedSpy.size() >= 1){ + QCOMPARE(columnsAboutToBeRemovedSpy.size(), 0); //QCOMPARE(rowsAboutToBeRemovedSpy.count(), numberOfRowsAboutToBeRemovedSignals); - QCOMPARE(columnsRemovedSpy.count(), 0); + QCOMPARE(columnsRemovedSpy.size(), 0); //QCOMPARE(rowsRemovedSpy.count(), numberOfRowsRemovedSignals); } else { - QCOMPARE(columnsAboutToBeRemovedSpy.count(), numberOfColumnsAboutToBeRemovedSignals); - QCOMPARE(rowsAboutToBeRemovedSpy.count(), numberOfRowsAboutToBeRemovedSignals); - QCOMPARE(columnsRemovedSpy.count(), numberOfColumnsRemovedSignals); - QCOMPARE(rowsRemovedSpy.count(), numberOfRowsRemovedSignals); + QCOMPARE(columnsAboutToBeRemovedSpy.size(), numberOfColumnsAboutToBeRemovedSignals); + QCOMPARE(rowsAboutToBeRemovedSpy.size(), numberOfRowsAboutToBeRemovedSignals); + QCOMPARE(columnsRemovedSpy.size(), numberOfColumnsRemovedSignals); + QCOMPARE(rowsRemovedSpy.size(), numberOfRowsRemovedSignals); } // The column count should only change *after* rowsAboutToBeRemoved has been emitted if (shouldSucceed) { - if (modelResetSpy.count() == 0 && modelLayoutChangedSpy.count() == 0){ + if (modelResetSpy.size() == 0 && modelLayoutChangedSpy.size() == 0){ QCOMPARE(afterAboutToRemoveColumnCount, beforeRemoveColumnCount); QCOMPARE(afterRemoveColumnCount, beforeRemoveColumnCount-count-(numberOfColumnsRemovedSignals-1)); } - if (modelResetSpy.count() == 0) + if (modelResetSpy.size() == 0) QCOMPARE(currentModel->columnCount(parentOfRemoved), beforeRemoveColumnCount-count-(numberOfColumnsRemovedSignals-1)); } else @@ -983,7 +958,7 @@ void tst_QItemModel::remove() disconnect(currentModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(slot_columnsRemoved(QModelIndex))); - if (columnsAboutToBeRemovedSpy.count() > 0){ + if (columnsAboutToBeRemovedSpy.size() > 0){ QList<QVariant> arguments = columnsAboutToBeRemovedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); @@ -993,7 +968,7 @@ void tst_QItemModel::remove() QVERIFY(parentOfRemoved == parent); } - if (columnsRemovedSpy.count() > 0){ + if (columnsRemovedSpy.size() > 0){ QList<QVariant> arguments = columnsRemovedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); @@ -1222,7 +1197,7 @@ void tst_QItemModel::insert() QCOMPARE(currentModel->insertRows(start, count, parentOfInserted), shouldSucceed); currentModel->submit(); - if (rowsAboutToBeInsertedSpy.count() > 0){ + if (rowsAboutToBeInsertedSpy.size() > 0){ QList<QVariant> arguments = rowsAboutToBeInsertedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); @@ -1232,7 +1207,7 @@ void tst_QItemModel::insert() QVERIFY(parentOfInserted == parent); } - if (rowsInsertedSpy.count() > 0){ + if (rowsInsertedSpy.size() > 0){ QList<QVariant> arguments = rowsInsertedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); @@ -1243,25 +1218,25 @@ void tst_QItemModel::insert() } // Only the row signals should have been emitted - if (modelResetSpy.count() >= 1 || modelLayoutChangedSpy.count() >= 1) { - QCOMPARE(columnsAboutToBeInsertedSpy.count(), 0); - QCOMPARE(rowsAboutToBeInsertedSpy.count(), 0); - QCOMPARE(columnsInsertedSpy.count(), 0); - QCOMPARE(rowsInsertedSpy.count(), 0); + if (modelResetSpy.size() >= 1 || modelLayoutChangedSpy.size() >= 1) { + QCOMPARE(columnsAboutToBeInsertedSpy.size(), 0); + QCOMPARE(rowsAboutToBeInsertedSpy.size(), 0); + QCOMPARE(columnsInsertedSpy.size(), 0); + QCOMPARE(rowsInsertedSpy.size(), 0); } else { - QCOMPARE(columnsAboutToBeInsertedSpy.count(), 0); - QCOMPARE(rowsAboutToBeInsertedSpy.count(), numberOfRowsAboutToBeInsertedSignals); - QCOMPARE(columnsInsertedSpy.count(), 0); - QCOMPARE(rowsInsertedSpy.count(), numberOfRowsInsertedSignals); + QCOMPARE(columnsAboutToBeInsertedSpy.size(), 0); + QCOMPARE(rowsAboutToBeInsertedSpy.size(), numberOfRowsAboutToBeInsertedSignals); + QCOMPARE(columnsInsertedSpy.size(), 0); + QCOMPARE(rowsInsertedSpy.size(), numberOfRowsInsertedSignals); } // The row count should only change *after* rowsAboutToBeInserted has been emitted if (shouldSucceed) { - if (modelResetSpy.count() == 0 && modelLayoutChangedSpy.count() == 0) { + if (modelResetSpy.size() == 0 && modelLayoutChangedSpy.size() == 0) { QCOMPARE(afterAboutToInsertRowCount, beforeInsertRowCount); QCOMPARE(afterInsertRowCount, beforeInsertRowCount+count+(numberOfRowsInsertedSignals-1)); } - if (modelResetSpy.count() == 0) + if (modelResetSpy.size() == 0) QCOMPARE(currentModel->rowCount(parentOfInserted), beforeInsertRowCount+count+(numberOfRowsInsertedSignals-1)); } else { @@ -1289,27 +1264,27 @@ void tst_QItemModel::insert() // Some models don't let you insert the column, only row if (currentModel->insertColumns(start, count, parentOfInserted)) { currentModel->submit(); - if (modelResetSpy.count() >= 1 || modelLayoutChangedSpy.count() >= 1) { + if (modelResetSpy.size() >= 1 || modelLayoutChangedSpy.size() >= 1) { // Didn't reset the rows, so they should still be at the same value - QCOMPARE(columnsAboutToBeInsertedSpy.count(), 0); + QCOMPARE(columnsAboutToBeInsertedSpy.size(), 0); //QCOMPARE(rowsAboutToBeInsertedSpy.count(), numberOfRowsAboutToBeInsertedSignals); - QCOMPARE(columnsInsertedSpy.count(), 0); + QCOMPARE(columnsInsertedSpy.size(), 0); //QCOMPARE(rowsInsertedSpy.count(), numberOfRowsInsertedSignals); } else { // Didn't reset the rows, so they should still be at the same value - QCOMPARE(columnsAboutToBeInsertedSpy.count(), numberOfColumnsAboutToBeInsertedSignals); - QCOMPARE(rowsAboutToBeInsertedSpy.count(), numberOfRowsAboutToBeInsertedSignals); - QCOMPARE(columnsInsertedSpy.count(), numberOfColumnsInsertedSignals); - QCOMPARE(rowsInsertedSpy.count(), numberOfRowsInsertedSignals); + QCOMPARE(columnsAboutToBeInsertedSpy.size(), numberOfColumnsAboutToBeInsertedSignals); + QCOMPARE(rowsAboutToBeInsertedSpy.size(), numberOfRowsAboutToBeInsertedSignals); + QCOMPARE(columnsInsertedSpy.size(), numberOfColumnsInsertedSignals); + QCOMPARE(rowsInsertedSpy.size(), numberOfRowsInsertedSignals); } // The column count should only change *after* rowsAboutToBeInserted has been emitted if (shouldSucceed) { - if (modelResetSpy.count() == 0 && modelLayoutChangedSpy.count() == 0) { + if (modelResetSpy.size() == 0 && modelLayoutChangedSpy.size() == 0) { QCOMPARE(afterAboutToInsertColumnCount, beforeInsertColumnCount); QCOMPARE(afterInsertColumnCount, beforeInsertColumnCount+count+(numberOfColumnsInsertedSignals-1)); } - if (modelResetSpy.count() == 0) + if (modelResetSpy.size() == 0) QCOMPARE(currentModel->columnCount(parentOfInserted), beforeInsertColumnCount+count+(numberOfColumnsInsertedSignals-1)); } else @@ -1320,7 +1295,7 @@ void tst_QItemModel::insert() disconnect(currentModel, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(slot_columnsInserted(QModelIndex))); - if (columnsAboutToBeInsertedSpy.count() > 0){ + if (columnsAboutToBeInsertedSpy.size() > 0){ QList<QVariant> arguments = columnsAboutToBeInsertedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); @@ -1330,7 +1305,7 @@ void tst_QItemModel::insert() QVERIFY(parentOfInserted == parent); } - if (columnsInsertedSpy.count() > 0){ + if (columnsInsertedSpy.size() > 0){ QList<QVariant> arguments = columnsInsertedSpy.at(0); QModelIndex parent = (qvariant_cast<QModelIndex>(arguments.at(0))); int first = arguments.at(1).toInt(); diff --git a/tests/auto/corelib/itemmodels/qitemselectionmodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qitemselectionmodel/CMakeLists.txt index 2dfa6f98f8..88ec493305 100644 --- a/tests/auto/corelib/itemmodels/qitemselectionmodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qitemselectionmodel/CMakeLists.txt @@ -1,12 +1,20 @@ -# Generated from qitemselectionmodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qitemselectionmodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qitemselectionmodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qitemselectionmodel SOURCES tst_qitemselectionmodel.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui + Qt::TestPrivate ) diff --git a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp index 052abe0700..45f7a6c08d 100644 --- a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -1,32 +1,9 @@ -/**************************************************************************** -** -** 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 <QTest> +#include <QtTest/private/qcomparisontesthelper_p.h> +#include <QtTest/private/qpropertytesthelper_p.h> #include <QSignalSpy> #include <QtGui/QtGui> @@ -48,6 +25,7 @@ public slots: void cleanupTestCase(); void init(); private slots: + void compareCompiles(); void clear_data(); void clear(); void clearAndSelect(); @@ -85,6 +63,8 @@ private slots: void deselectRemovedMiddleRange(); void setModel(); + void bindableModel(); + void testDifferentModels(); void testValidRangesInSelectionsAfterReset(); @@ -100,7 +80,13 @@ private slots: void QTBUG18001_data(); void QTBUG18001(); + void QTBUG93305(); + + void testSignalsDisconnection(); + void destroyModel(); + private: + static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); QAbstractItemModel *model; QItemSelectionModel *selection; }; @@ -161,8 +147,8 @@ QDataStream &operator>>(QDataStream &s, QModelIndex &output) QDataStream &operator<<(QDataStream &s, const QModelIndexList &input) { - s << input.count(); - for (int i=0; i<input.count(); ++i) + s << input.size(); + for (int i=0; i<input.size(); ++i) s << input.at(i); return s; } @@ -229,6 +215,11 @@ void tst_QItemSelectionModel::init() model->insertRow(0, QModelIndex()); } +void tst_QItemSelectionModel::compareCompiles() +{ + QTestPrivate::testEqualityOperatorsCompile<QItemSelectionRange>(); +} + void tst_QItemSelectionModel::clear_data() { QTest::addColumn<QModelIndexList>("indexList"); @@ -298,7 +289,7 @@ void tst_QItemSelectionModel::clear() QFETCH(IntList, commandList); // do selections - for (int i=0; i<indexList.count(); ++i) { + for (int i=0; i<indexList.size(); ++i) { selection->select(indexList.at(i), (QItemSelectionModel::SelectionFlags)commandList.at(i)); } // test that we have selected items @@ -312,7 +303,7 @@ void tst_QItemSelectionModel::clearAndSelect() { // populate selectionmodel selection->select(model->index(1, 1, QModelIndex()), QItemSelectionModel::Select); - QCOMPARE(selection->selectedIndexes().count(), 1); + QCOMPARE(selection->selectedIndexes().size(), 1); QVERIFY(selection->hasSelection()); // ClearAndSelect with empty selection @@ -330,26 +321,26 @@ void tst_QItemSelectionModel::toggleSelection() //and hasSelection returns the correct value selection->clearSelection(); - QCOMPARE(selection->selectedIndexes().count(), 0); + QCOMPARE(selection->selectedIndexes().size(), 0); QVERIFY(selection->hasSelection()==false); QModelIndex index=model->index(1, 1, QModelIndex()); // populate selectionmodel selection->select(index, QItemSelectionModel::Toggle); - QCOMPARE(selection->selectedIndexes().count(), 1); + QCOMPARE(selection->selectedIndexes().size(), 1); QVERIFY(selection->hasSelection()==true); selection->select(index, QItemSelectionModel::Toggle); - QCOMPARE(selection->selectedIndexes().count(), 0); + QCOMPARE(selection->selectedIndexes().size(), 0); QVERIFY(selection->hasSelection()==false); // populate selectionmodel with rows selection->select(index, QItemSelectionModel::Toggle | QItemSelectionModel::Rows); - QCOMPARE(selection->selectedIndexes().count(), model->columnCount()); + QCOMPARE(selection->selectedIndexes().size(), model->columnCount()); QVERIFY(selection->hasSelection()==true); selection->select(index, QItemSelectionModel::Toggle | QItemSelectionModel::Rows); - QCOMPARE(selection->selectedIndexes().count(), 0); + QCOMPARE(selection->selectedIndexes().size(), 0); QVERIFY(selection->hasSelection()==false); } @@ -1241,7 +1232,7 @@ void tst_QItemSelectionModel::select() int lastCommand = 0; // do selections - for (int i = 0; i<commandList.count(); ++i) { + for (int i = 0; i<commandList.size(); ++i) { if (useRanges) { selection->select(QItemSelection(indexList.at(2*i), indexList.at(2*i+1)), (QItemSelectionModel::SelectionFlags)commandList.at(i)); @@ -1258,13 +1249,13 @@ void tst_QItemSelectionModel::select() QVERIFY(selection->hasSelection()!=selectedList.isEmpty()); // test that the number of indices are as expected - QVERIFY2(selectedList.count() == expectedList.count(), + QVERIFY2(selectedList.size() == expectedList.size(), QString("expected indices: %1 actual indices: %2") - .arg(expectedList.count()) - .arg(selectedList.count()).toLatin1()); + .arg(expectedList.size()) + .arg(selectedList.size()).toLatin1()); // test existence of each index - for (int i=0; i<expectedList.count(); ++i) { + for (int i=0; i<expectedList.size(); ++i) { QVERIFY2(selectedList.contains(expectedList.at(i)), QString("expected index(%1, %2) not found in selectedIndexes()") .arg(expectedList.at(i).row()) @@ -1272,7 +1263,7 @@ void tst_QItemSelectionModel::select() } // test that isSelected agrees - for (int i=0; i<indexList.count(); ++i) { + for (int i=0; i<indexList.size(); ++i) { QModelIndex idx = indexList.at(i); QVERIFY2(selection->isSelected(idx) == selectedList.contains(idx), QString("isSelected(index: %1, %2) does not match selectedIndexes()") @@ -1283,7 +1274,7 @@ void tst_QItemSelectionModel::select() //for now we assume Rows/Columns flag is the same for all commands, therefore we just check lastCommand // test that isRowSelected agrees if (lastCommand & QItemSelectionModel::Rows) { - for (int i=0; i<selectedList.count(); ++i) + for (int i=0; i<selectedList.size(); ++i) QVERIFY2(selection->isRowSelected(selectedList.at(i).row(), model->parent(selectedList.at(i))), QString("isRowSelected(row: %1) does not match selectedIndexes()") @@ -1292,7 +1283,7 @@ void tst_QItemSelectionModel::select() // test that isColumnSelected agrees if (lastCommand & QItemSelectionModel::Columns) { - for (int i=0; i<selectedList.count(); ++i) + for (int i=0; i<selectedList.size(); ++i) QVERIFY2(selection->isColumnSelected(selectedList.at(i).column(), model->parent(selectedList.at(i))), QString("isColumnSelected(column: %1) does not match selectedIndexes()") @@ -1476,8 +1467,8 @@ void tst_QItemSelectionModel::persistentselections() QCOMPARE(model->columnCount(QModelIndex()), 5); // do selections - for (int i=0; i<commandList.count(); ++i) { - if (indexList.count() == commandList.count()) { + for (int i=0; i<commandList.size(); ++i) { + if (indexList.size() == commandList.size()) { QModelIndex index = model->index(indexList.at(i).first, indexList.at(i).second, QModelIndex()); @@ -1498,18 +1489,18 @@ void tst_QItemSelectionModel::persistentselections() QVERIFY(selection->hasSelection()); // insert/delete row and/or columns - if (insertRows.count() > 1) + if (insertRows.size() > 1) model->insertRows(insertRows.at(0), insertRows.at(1), QModelIndex()); - if (insertColumns.count() > 1) + if (insertColumns.size() > 1) model->insertColumns(insertColumns.at(0), insertColumns.at(1), QModelIndex()); - if (deleteRows.count() > 1) + if (deleteRows.size() > 1) model->removeRows(deleteRows.at(0), deleteRows.at(1), QModelIndex()); - if (deleteColumns.count() > 1) + if (deleteColumns.size() > 1) model->removeColumns(deleteColumns.at(0), deleteColumns.at(1), QModelIndex()); // check that the selected items are the correct number and indexes QModelIndexList selectedList = selection->selectedIndexes(); - QCOMPARE(selectedList.count(), expectedList.count()); + QCOMPARE(selectedList.size(), expectedList.size()); for (const auto &pair : expectedList) { QModelIndex index = model->index(pair.first, pair.second, QModelIndex()); QVERIFY(selectedList.contains(index)); @@ -1535,7 +1526,7 @@ void tst_QItemSelectionModel::resetModel() selectionModel->select(QItemSelection(model.index(0, 0), model.index(5, 5)), QItemSelectionModel::Select); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); model.reset(); @@ -1544,8 +1535,8 @@ void tst_QItemSelectionModel::resetModel() selectionModel->select(QItemSelection(model.index(0, 0), model.index(5, 5)), QItemSelectionModel::Select); - QCOMPARE(spy.count(), 2); - QCOMPARE(spy.at(1).count(), 2); + QCOMPARE(spy.size(), 2); + QCOMPARE(spy.at(1).size(), 2); // make sure we don't get an "old selection" QCOMPARE(spy.at(1).at(1).userType(), qMetaTypeId<QItemSelection>()); QVERIFY(qvariant_cast<QItemSelection>(spy.at(1).at(1)).isEmpty()); @@ -1600,14 +1591,14 @@ void tst_QItemSelectionModel::removeRows() QModelIndex br = model.index(selectBottom, selectRight); selections.select(QItemSelection(tl, br), QItemSelectionModel::ClearAndSelect); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QVERIFY(selections.isSelected(tl)); QVERIFY(selections.isSelected(br)); QVERIFY(selections.hasSelection()); model.removeRows(removeTop, removeBottom - removeTop + 1); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); tl = model.index(expectedTop, expectedLeft); br = model.index(expectedBottom, expectedRight); QVERIFY(selections.isSelected(tl)); @@ -1663,14 +1654,14 @@ void tst_QItemSelectionModel::removeColumns() QModelIndex br = model.index(selectBottom, selectRight); selections.select(QItemSelection(tl, br), QItemSelectionModel::ClearAndSelect); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QVERIFY(selections.isSelected(tl)); QVERIFY(selections.isSelected(br)); QVERIFY(selections.hasSelection()); model.removeColumns(removeLeft, removeRight - removeLeft + 1); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); tl = model.index(expectedTop, expectedLeft); br = model.index(expectedBottom, expectedRight); QVERIFY(selections.isSelected(tl)); @@ -1741,7 +1732,7 @@ void tst_QItemSelectionModel::modelLayoutChanged() QFETCH(int, sortColumn); QFETCH(IntPairPairList, expectedSelectedRanges); - MyStandardItemModel model(items.at(0).count(), items.count()); + MyStandardItemModel model(items.at(0).size(), items.size()); // initialize model data for (int i = 0; i < model.rowCount(); ++i) { for (int j = 0; j < model.columnCount(); ++j) { @@ -1766,10 +1757,10 @@ void tst_QItemSelectionModel::modelLayoutChanged() // verify that selection is as expected QItemSelection selection = selectionModel.selection(); - QCOMPARE(selection.count(), expectedSelectedRanges.count()); + QCOMPARE(selection.size(), expectedSelectedRanges.size()); QCOMPARE(selectionModel.hasSelection(), !expectedSelectedRanges.isEmpty()); - for (int i = 0; i < expectedSelectedRanges.count(); ++i) { + for (int i = 0; i < expectedSelectedRanges.size(); ++i) { IntPairPair expectedRange = expectedSelectedRanges.at(i); IntPair expectedTl = expectedRange.first; IntPair expectedBr = expectedRange.second; @@ -1823,21 +1814,21 @@ void tst_QItemSelectionModel::selectedRows() MyStandardItemModel model(rowCount, columnCount); QItemSelectionModel selectionModel(&model); - for (int i = 0; i < selectRows.count(); ++i) + for (int i = 0; i < selectRows.size(); ++i) selectionModel.select(model.index(selectRows.at(i), 0), QItemSelectionModel::Select |QItemSelectionModel::Rows); - for (int j = 0; j < selectRows.count(); ++j) + for (int j = 0; j < selectRows.size(); ++j) QVERIFY(selectionModel.isRowSelected(expectedRows.at(j), QModelIndex())); - for (int k = 0; k < selectRows.count(); ++k) + for (int k = 0; k < selectRows.size(); ++k) QVERIFY(!selectionModel.isRowSelected(unexpectedRows.at(k), QModelIndex())); QModelIndexList selectedRowIndexes = selectionModel.selectedRows(column); - QCOMPARE(selectedRowIndexes.count(), expectedRows.count()); + QCOMPARE(selectedRowIndexes.size(), expectedRows.size()); std::sort(selectedRowIndexes.begin(), selectedRowIndexes.end()); - for (int l = 0; l < selectedRowIndexes.count(); ++l) { + for (int l = 0; l < selectedRowIndexes.size(); ++l) { QCOMPARE(selectedRowIndexes.at(l).row(), expectedRows.at(l)); QCOMPARE(selectedRowIndexes.at(l).column(), column); } @@ -1883,21 +1874,21 @@ void tst_QItemSelectionModel::selectedColumns() MyStandardItemModel model(rowCount, columnCount); QItemSelectionModel selectionModel(&model); - for (int i = 0; i < selectColumns.count(); ++i) + for (int i = 0; i < selectColumns.size(); ++i) selectionModel.select(model.index(0, selectColumns.at(i)), QItemSelectionModel::Select |QItemSelectionModel::Columns); - for (int j = 0; j < selectColumns.count(); ++j) + for (int j = 0; j < selectColumns.size(); ++j) QVERIFY(selectionModel.isColumnSelected(expectedColumns.at(j), QModelIndex())); - for (int k = 0; k < selectColumns.count(); ++k) + for (int k = 0; k < selectColumns.size(); ++k) QVERIFY(!selectionModel.isColumnSelected(unexpectedColumns.at(k), QModelIndex())); QModelIndexList selectedColumnIndexes = selectionModel.selectedColumns(row); - QCOMPARE(selectedColumnIndexes.count(), expectedColumns.count()); + QCOMPARE(selectedColumnIndexes.size(), expectedColumns.size()); std::sort(selectedColumnIndexes.begin(), selectedColumnIndexes.end()); - for (int l = 0; l < selectedColumnIndexes.count(); ++l) { + for (int l = 0; l < selectedColumnIndexes.size(); ++l) { QCOMPARE(selectedColumnIndexes.at(l).column(), expectedColumns.at(l)); QCOMPARE(selectedColumnIndexes.at(l).row(), row); } @@ -1928,18 +1919,18 @@ void tst_QItemSelectionModel::setCurrentIndex() treemodel->index(0, 0, treemodel->index(1, 0)), QItemSelectionModel::SelectCurrent); - QCOMPARE(currentSpy.count(), 1); - QCOMPARE(rowSpy.count(), 1); - QCOMPARE(columnSpy.count(), 1); + QCOMPARE(currentSpy.size(), 1); + QCOMPARE(rowSpy.size(), 1); + QCOMPARE(columnSpy.size(), 1); // Select another row in the same parent selectionModel.setCurrentIndex( treemodel->index(1, 0, treemodel->index(1, 0)), QItemSelectionModel::SelectCurrent); - QCOMPARE(currentSpy.count(), 2); - QCOMPARE(rowSpy.count(), 2); - QCOMPARE(columnSpy.count(), 1); + QCOMPARE(currentSpy.size(), 2); + QCOMPARE(rowSpy.size(), 2); + QCOMPARE(columnSpy.size(), 1); } void tst_QItemSelectionModel::splitOnInsert() @@ -2063,12 +2054,14 @@ void tst_QItemSelectionModel::unselectable() } QItemSelectionModel selectionModel(&model); selectionModel.select(QItemSelection(model.index(0, 0), model.index(9, 0)), QItemSelectionModel::Select); - QCOMPARE(selectionModel.selectedIndexes().count(), 10); - QCOMPARE(selectionModel.selectedRows().count(), 10); + QCOMPARE(selectionModel.selectedIndexes().size(), 10); + QCOMPARE(selectionModel.selectedRows().size(), 10); + QVERIFY(selectionModel.hasSelection()); for (int j = 0; j < 10; ++j) model.item(j)->setFlags({ }); - QCOMPARE(selectionModel.selectedIndexes().count(), 0); - QCOMPARE(selectionModel.selectedRows().count(), 0); + QVERIFY(!selectionModel.hasSelection()); + QCOMPARE(selectionModel.selectedIndexes().size(), 0); + QCOMPARE(selectionModel.selectedRows().size(), 0); } void tst_QItemSelectionModel::selectedIndexes() @@ -2082,8 +2075,8 @@ void tst_QItemSelectionModel::selectedIndexes() //we select the 1st row selectionModel.select(selection, QItemSelectionModel::Rows | QItemSelectionModel::Select); - QCOMPARE(selectionModel.selectedRows().count(), 1); - QCOMPARE(selectionModel.selectedIndexes().count(), model.columnCount()); + QCOMPARE(selectionModel.selectedRows().size(), 1); + QCOMPARE(selectionModel.selectedIndexes().size(), model.columnCount()); } @@ -2121,14 +2114,14 @@ void tst_QItemSelectionModel::layoutChanged() QtTestTableModel model(1,1); QItemSelectionModel selectionModel(&model); selectionModel.select(model.index(0,0), QItemSelectionModel::Select); - QCOMPARE(selectionModel.selectedIndexes().count() , 1); + QCOMPARE(selectionModel.selectedIndexes().size() , 1); emit model.layoutAboutToBeChanged(); model.row_count = 5; emit model.layoutChanged(); //The selection should not change. - QCOMPARE(selectionModel.selectedIndexes().count() , 1); + QCOMPARE(selectionModel.selectedIndexes().size() , 1); QCOMPARE(selectionModel.selectedIndexes().first() , model.index(0,0)); } @@ -2208,7 +2201,7 @@ void tst_QItemSelectionModel::isRowSelected() model.setData(model.index(0,0), 0, Qt::UserRole - 1); QItemSelectionModel sel(&model); sel.select( QItemSelection(model.index(0,0), model.index(0, 1)), QItemSelectionModel::Select); - QCOMPARE(sel.selectedIndexes().count(), 1); + QCOMPARE(sel.selectedIndexes().size(), 1); QVERIFY(sel.isRowSelected(0, QModelIndex())); } @@ -2233,7 +2226,7 @@ void tst_QItemSelectionModel::childrenDeselectionSignal() QSignalSpy deselectSpy(&selectionModel, &QItemSelectionModel::selectionChanged); QVERIFY(deselectSpy.isValid()); model.removeRows(0, 1, root); - QCOMPARE(deselectSpy.count(), 1); + QCOMPARE(deselectSpy.size(), 1); // More testing stress for the patch. model.clear(); @@ -2262,7 +2255,7 @@ void tst_QItemSelectionModel::childrenDeselectionSignal() QVERIFY(selectionModel.selection().contains(sel2)); deselectSpy.clear(); model.removeRow(0, model.index(0, 0)); - QCOMPARE(deselectSpy.count(), 1); + QCOMPARE(deselectSpy.size(), 1); QVERIFY(!selectionModel.selection().contains(sel)); QVERIFY(selectionModel.selection().contains(sel2)); } @@ -2284,7 +2277,7 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected1() selection.select(QItemSelection(indexList.first(), indexList.last()), QItemSelectionModel::Select); //let's check the selection hasn't changed - QCOMPARE(selection.selectedIndexes().count(), indexList.count()); + QCOMPARE(selection.selectedIndexes().size(), indexList.size()); for (const auto &index : indexList) QVERIFY(selection.isSelected(index)); @@ -2292,7 +2285,7 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected1() QCOMPARE(proxy.rowCount(), 3); //let's check the selection hasn't changed - QCOMPARE(selection.selectedIndexes().count(), indexList.count()); + QCOMPARE(selection.selectedIndexes().size(), indexList.size()); for (const auto &index : indexList) QVERIFY(selection.isSelected(index)); } @@ -2341,7 +2334,7 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected2() QCOMPARE(proxy.rowCount(), int(cNumRows)); //let's check the selection hasn't changed - QCOMPARE(selection.selectedIndexes().count(), indexList.count()); + QCOMPARE(selection.selectedIndexes().size(), indexList.size()); for (const auto &index : indexList) QVERIFY(selection.isSelected(index)); } @@ -2365,11 +2358,11 @@ void tst_QItemSelectionModel::layoutChangedTreeSelection() selModel.select(sub23.index(), QItemSelectionModel::Select); QModelIndexList list = selModel.selectedIndexes(); - QCOMPARE(list.count(), 4); + QCOMPARE(list.size(), 4); model.sort(0); //this will provoke a relayout - QCOMPARE(selModel.selectedIndexes().count(), 4); + QCOMPARE(selModel.selectedIndexes().size(), 4); } class RemovalObserver : public QObject @@ -2428,13 +2421,36 @@ void tst_QItemSelectionModel::setModel() QStringListModel model(QStringList() << "Blah" << "Blah" << "Blah"); sel.setModel(&model); QCOMPARE(sel.model(), &model); - QCOMPARE(modelChangedSpy.count(), 1); + QCOMPARE(modelChangedSpy.size(), 1); sel.select(model.index(0), QItemSelectionModel::Select); QVERIFY(!sel.selection().isEmpty()); sel.setModel(0); QVERIFY(sel.selection().isEmpty()); } +void tst_QItemSelectionModel::bindableModel() +{ + QItemSelectionModel sel; + QVERIFY(!sel.model()); + + std::unique_ptr<QStringListModel> firstModel( + new QStringListModel(QStringList { "Some", "random", "content" })); + std::unique_ptr<QStringListModel> changedModel( + new QStringListModel(QStringList { "Other", "random", "content" })); + + QTestPrivate::testReadWritePropertyBasics<QItemSelectionModel, QAbstractItemModel *>( + sel, firstModel.get(), changedModel.get(), "model"); + if (QTest::currentTestFailed()) { + qDebug("Failed property test for QItemSelectionModel::model"); + return; + } + + // check that model is set to nullptr when the object pointed to is deleted: + sel.setModel(firstModel.get()); + firstModel.reset(); + QCOMPARE(sel.model(), nullptr); +} + void tst_QItemSelectionModel::testDifferentModels() { QStandardItemModel model1; @@ -2705,6 +2721,9 @@ void tst_QItemSelectionModel::QTBUG48402() model.removeRows(removeTop, removeBottom - removeTop + 1); QCOMPARE(QItemSelectionRange(helper.tl, helper.br), QItemSelectionRange(dtl, dbr)); + QT_TEST_EQUALITY_OPS(QItemSelectionRange(helper.tl, helper.br), QItemSelectionRange(dtl, dbr), true); + QT_TEST_EQUALITY_OPS(QItemSelectionRange(), QItemSelectionRange(), true); + QT_TEST_EQUALITY_OPS(QItemSelectionRange(helper.tl, helper.br), QItemSelectionRange(), false); } void tst_QItemSelectionModel::QTBUG58851_data() @@ -2772,7 +2791,7 @@ void tst_QItemSelectionModel::QTBUG58851() QVERIFY(selections.isSelected(i)); } proxy.sort(1, Qt::DescendingOrder); - QCOMPARE(selections.selectedIndexes().count(), (int)expectedSelectedIndexes.size()); + QCOMPARE(selections.selectedIndexes().size(), (int)expectedSelectedIndexes.size()); for (const QPersistentModelIndex &i : expectedSelectedIndexes) { QVERIFY(selections.isSelected(i)); } @@ -2846,12 +2865,12 @@ void tst_QItemSelectionModel::QTBUG18001() QItemSelectionModel selectionModel(&model); - for (int i = 0; i < indexesToSelect.count(); ++i) { + for (int i = 0; i < indexesToSelect.size(); ++i) { QModelIndex idx = model.index( indexesToSelect.at(i).first, indexesToSelect.at(i).second ); selectionModel.select(idx, QItemSelectionModel::SelectionFlag(selectionCommands.at(i))); } - for (int i = 0; i < expectedSelectedRows.count(); ++i) { + for (int i = 0; i < expectedSelectedRows.size(); ++i) { const bool expected = expectedSelectedRows.at(i); const bool actual = selectionModel.isRowSelected(i, QModelIndex()); QByteArray description = QByteArray("Row ") + QByteArray::number(i) @@ -2860,7 +2879,7 @@ void tst_QItemSelectionModel::QTBUG18001() QVERIFY2(expected == actual, description.data()); } - for (int i = 0; i < expectedSelectedColums.count(); ++i) { + for (int i = 0; i < expectedSelectedColums.size(); ++i) { const bool expected = expectedSelectedColums.at(i); const bool actual = selectionModel.isColumnSelected(i, QModelIndex()); QByteArray description = QByteArray("Col ") + QByteArray::number(i) @@ -2871,5 +2890,94 @@ void tst_QItemSelectionModel::QTBUG18001() } +void tst_QItemSelectionModel::QTBUG93305() +{ + // make sure the model is sane (5x5) + QCOMPARE(model->rowCount(QModelIndex()), 5); + QCOMPARE(model->columnCount(QModelIndex()), 5); + + QSignalSpy spy(selection, &QItemSelectionModel::selectionChanged); + + // select in row 1 + QModelIndex index = model->index(1, 0, QModelIndex()); + selection->select(index, QItemSelectionModel::ClearAndSelect); + QVERIFY(selection->hasSelection()); + QCOMPARE(spy.size(), 1); + + // removing row 0 does not change which cells are selected, but it + // does change the row number of the selected cells. Thus it changes + // what selectedIndexes() returns. + // The property selectedIndexes() has selectionChanged() as its + // NOTIFY signal, so selectionChanged() should be emitted. + + // delete row 0 + model->removeRows(0, 1, QModelIndex()); + QVERIFY(selection->hasSelection()); + QCOMPARE(spy.size(), 2); + + // inserting a row before the first row again does not change which cells + // are selected, but does change the row number of the selected cells. + // This changes what selectedIndexes() returns and should thus trigger + // a selectionChanged() signal + + // insert row 0 again + model->insertRows(0, 1, QModelIndex()); + QVERIFY(selection->hasSelection()); + QCOMPARE(spy.size(), 3); + + // test for inserting multiple (6) rows + model->insertRows(0, 6, QModelIndex()); + QVERIFY(selection->hasSelection()); + QCOMPARE(spy.size(), 4); +} + +static void (*oldMessageHandler)(QtMsgType, const QMessageLogContext&, const QString&); +static bool signalError = false; + +// detect disconnect warning: +// qt.core.qobject.connect: QObject::disconnect: No such signal +void tst_QItemSelectionModel::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + Q_ASSERT(oldMessageHandler); + + if (type == QtWarningMsg + && QString(context.category) == "qt.core.qobject.connect" + && msg.contains("No such")) { + signalError = true; + } + + return oldMessageHandler(type, context, msg); +} + +void tst_QItemSelectionModel::testSignalsDisconnection() +{ + oldMessageHandler = qInstallMessageHandler(messageHandler); + auto resetMessageHandler = qScopeGuard([] { qInstallMessageHandler(oldMessageHandler); }); + auto *newModel = new QStandardItemModel(model); + selection->setModel(newModel); + QSignalSpy spy(newModel, &QObject::destroyed); + delete newModel; + QTRY_COMPARE(spy.count(), 1); + qDebug() << spy; + selection->setModel(nullptr); + QVERIFY(!signalError); +} + +void tst_QItemSelectionModel::destroyModel() +{ + auto itemModel = std::make_unique<QStandardItemModel>(5, 5); + auto selectionModel = std::make_unique<QItemSelectionModel>(); + selectionModel->setModel(itemModel.get()); + selectionModel->select(itemModel->index(0, 0), QItemSelectionModel::Select); + QVERIFY(!selectionModel->selection().isEmpty()); + selectionModel->setCurrentIndex(itemModel->index(1, 0), QItemSelectionModel::Select); + QVERIFY(selectionModel->currentIndex().isValid()); + + QTest::failOnWarning(QRegularExpression(".*")); + itemModel.reset(); + QVERIFY(!selectionModel->currentIndex().isValid()); + QVERIFY(selectionModel->selection().isEmpty()); +} + QTEST_MAIN(tst_QItemSelectionModel) #include "tst_qitemselectionmodel.moc" diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/CMakeLists.txt new file mode 100644 index 0000000000..5427c52e78 --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qsortfilterproxymodel Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsortfilterproxymodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qsortfilterproxymodel + SOURCES + ../../../other/qabstractitemmodelutils/dynamictreemodel.cpp ../../../other/qabstractitemmodelutils/dynamictreemodel.h + tst_qsortfilterproxymodel.cpp + INCLUDE_DIRECTORIES + ../../../other/qabstractitemmodelutils + LIBRARIES + Qt::Gui + Qt::Widgets + Qt::TestPrivate +) diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 0fabd5ea57..0e027461aa 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.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) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "tst_qsortfilterproxymodel.h" #include "dynamictreemodel.h" @@ -40,6 +15,7 @@ #include <QStack> #include <QSignalSpy> #include <QAbstractItemModelTester> +#include <QtTest/private/qpropertytesthelper_p.h> Q_LOGGING_CATEGORY(lcItemModels, "qt.corelib.tests.itemmodels") @@ -71,6 +47,7 @@ void tst_QSortFilterProxyModel::initTestCase() m_model = new QStandardItemModel(0, 1); m_proxy = new QSortFilterProxyModel(); m_proxy->setSourceModel(m_model); + new QAbstractItemModelTester(m_proxy, this); } void tst_QSortFilterProxyModel::cleanupTestCase() @@ -85,6 +62,7 @@ void tst_QSortFilterProxyModel::cleanup() m_proxy->sort(-1, Qt::AscendingOrder); m_model->clear(); m_model->insertColumns(0, 1); + QCoreApplication::processEvents(); // cleanup possibly queued events } /* @@ -239,16 +217,16 @@ void tst_QSortFilterProxyModel::sort() // prepare model QStandardItem *root = m_model->invisibleRootItem (); QList<QStandardItem *> items; - for (int i = 0; i < initial.count(); ++i) { + for (int i = 0; i < initial.size(); ++i) { items.append(new QStandardItem(initial.at(i))); } root->insertRows(0, items); - QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); + QCOMPARE(m_model->rowCount(QModelIndex()), initial.size()); QCOMPARE(m_model->columnCount(QModelIndex()), 1); // make sure the proxy is unsorted QCOMPARE(m_proxy->columnCount(QModelIndex()), 1); - QCOMPARE(m_proxy->rowCount(QModelIndex()), initial.count()); + QCOMPARE(m_proxy->rowCount(QModelIndex()), initial.size()); for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { QModelIndex index = m_proxy->index(row, 0, QModelIndex()); QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); @@ -269,13 +247,16 @@ void tst_QSortFilterProxyModel::sort() QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row)); } - // restore the unsorted order - m_proxy->sort(-1); + // restore the unsorted order in the given order + m_proxy->sort(-1, sortOrder); - // make sure the proxy is unsorted again + // make sure the proxy is sorted by source row in the given order + int sourceIndex = sortOrder == Qt::AscendingOrder ? 0 : initial.size() - 1; + int adjustmentValue = sortOrder == Qt::AscendingOrder ? 1 : -1; for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { QModelIndex index = m_proxy->index(row, 0, QModelIndex()); - QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); + QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(sourceIndex)); + sourceIndex += adjustmentValue; } } @@ -436,10 +417,10 @@ void tst_QSortFilterProxyModel::insertRows() QFETCH(QStringList, insert); QFETCH(int, position); // prepare model - m_model->insertRows(0, initial.count(), QModelIndex()); + m_model->insertRows(0, initial.size(), QModelIndex()); //m_model->insertColumns(0, 1, QModelIndex()); QCOMPARE(m_model->columnCount(QModelIndex()), 1); - QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); + QCOMPARE(m_model->rowCount(QModelIndex()), initial.size()); for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { QModelIndex index = m_model->index(row, 0, QModelIndex()); m_model->setData(index, initial.at(row), Qt::DisplayRole); @@ -456,12 +437,12 @@ void tst_QSortFilterProxyModel::insertRows() } // insert the row - m_proxy->insertRows(position, insert.count(), QModelIndex()); - QCOMPARE(m_model->rowCount(QModelIndex()), expected.count()); - QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count()); + m_proxy->insertRows(position, insert.size(), QModelIndex()); + QCOMPARE(m_model->rowCount(QModelIndex()), expected.size()); + QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.size()); // set the data for the inserted row - for (int i = 0; i < insert.count(); ++i) { + for (int i = 0; i < insert.size(); ++i) { QModelIndex index = m_proxy->index(position + i, 0, QModelIndex()); m_proxy->setData(index, insert.at(i), Qt::DisplayRole); } @@ -850,8 +831,8 @@ void tst_QSortFilterProxyModel::removeRows() // remove the rows QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success); - QCOMPARE(model.rowCount(QModelIndex()), expectedSource.count()); - QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxy.count()); + QCOMPARE(model.rowCount(QModelIndex()), expectedSource.size()); + QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxy.size()); // make sure the model is correct after remove for (int row = 0; row < model.rowCount(QModelIndex()); ++row) @@ -1096,8 +1077,8 @@ void tst_QSortFilterProxyModel::removeColumns() // remove the columns QCOMPARE(proxy.removeColumns(position, count, QModelIndex()), success); - QCOMPARE(model.columnCount(QModelIndex()), expectedSource.count()); - QCOMPARE(proxy.columnCount(QModelIndex()), expectedProxy.count()); + QCOMPARE(model.columnCount(QModelIndex()), expectedSource.size()); + QCOMPARE(proxy.columnCount(QModelIndex()), expectedProxy.size()); // make sure the model is correct after remove for (int col = 0; col < model.columnCount(QModelIndex()); ++col) @@ -1123,7 +1104,6 @@ void tst_QSortFilterProxyModel::filterColumns_data() << "bravo" << "lima") << true; - QTest::newRow("some") << "lie" << (QStringList() << "charlie" @@ -1147,9 +1127,10 @@ void tst_QSortFilterProxyModel::filterColumns() QFETCH(QStringList, initial); QFETCH(bool, data); // prepare model - m_model->setColumnCount(initial.count()); + m_model->setColumnCount(initial.size()); m_model->setRowCount(1); - QCOMPARE(m_model->columnCount(QModelIndex()), initial.count()); + QCoreApplication::processEvents(); // QAbstractProxyModel queues the headerDataChanged() signal + QCOMPARE(m_model->columnCount(QModelIndex()), initial.size()); QCOMPARE(m_model->rowCount(QModelIndex()), 1); // set data QCOMPARE(m_model->rowCount(QModelIndex()), 1); @@ -1226,8 +1207,8 @@ void tst_QSortFilterProxyModel::filter() QFETCH(QStringList, expected); // prepare model - QVERIFY(m_model->insertRows(0, initial.count(), QModelIndex())); - QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); + QVERIFY(m_model->insertRows(0, initial.size(), QModelIndex())); + QCOMPARE(m_model->rowCount(QModelIndex()), initial.size()); // set data QCOMPARE(m_model->columnCount(QModelIndex()), 1); for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { @@ -1237,7 +1218,7 @@ void tst_QSortFilterProxyModel::filter() setupFilter(m_proxy, pattern); // make sure the proxy is unfiltered QCOMPARE(m_proxy->columnCount(QModelIndex()), 1); - QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count()); + QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.size()); // make sure the model is unchanged for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { QModelIndex index = m_model->index(row, 0, QModelIndex()); @@ -1280,22 +1261,19 @@ void tst_QSortFilterProxyModel::filterHierarchy() void tst_QSortFilterProxyModel::buildHierarchy(const QStringList &l, QAbstractItemModel *m) { - int ind = 0; int row = 0; QStack<int> row_stack; QModelIndex parent; QStack<QModelIndex> parent_stack; - for (int i = 0; i < l.count(); ++i) { + for (int i = 0; i < l.size(); ++i) { QString token = l.at(i); if (token == QLatin1String("<")) { // start table - ++ind; parent_stack.push(parent); row_stack.push(row); parent = m->index(row - 1, 0, parent); row = 0; QVERIFY(m->insertColumns(0, 1, parent)); // add column } else if (token == QLatin1String(">")) { // end table - --ind; parent = parent_stack.pop(); row = row_stack.pop(); } else { // append row @@ -1311,21 +1289,18 @@ void tst_QSortFilterProxyModel::buildHierarchy(const QStringList &l, QAbstractIt void tst_QSortFilterProxyModel::checkHierarchy(const QStringList &l, const QAbstractItemModel *m) { int row = 0; - int indent = 0; QStack<int> row_stack; QModelIndex parent; QStack<QModelIndex> parent_stack; - for (int i = 0; i < l.count(); ++i) { + for (int i = 0; i < l.size(); ++i) { QString token = l.at(i); if (token == QLatin1String("<")) { // start table - ++indent; parent_stack.push(parent); row_stack.push(row); parent = m->index(row - 1, 0, parent); QVERIFY(parent.isValid()); row = 0; } else if (token == QLatin1String(">")) { // end table - --indent; parent = parent_stack.pop(); row = row_stack.pop(); } else { // compare row @@ -1425,9 +1400,9 @@ void tst_QSortFilterProxyModel::filterCurrent() QVERIFY(spy.isValid()); view.setCurrentIndex(proxy.index(0, 0)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); setupFilter(&proxy, QLatin1String("^B")); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QSortFilterProxyModel::filter_qtbug30662() @@ -1495,7 +1470,7 @@ void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut() // Filter everything out setupFilter(&proxy, QLatin1String("c")); - QCOMPARE(removeSpy.count(), 1); + QCOMPARE(removeSpy.size(), 1); QCOMPARE(0, proxy.rowCount()); // change layout of source model @@ -1505,7 +1480,7 @@ void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut() // Remove filter; we expect an insert setupFilter(&proxy, ""); - QCOMPARE(insertSpy.count(), 1); + QCOMPARE(insertSpy.size(), 1); QCOMPARE(beforeSortFilter, proxy.rowCount()); } @@ -1584,9 +1559,9 @@ void tst_QSortFilterProxyModel::removeSourceRows() proxy.setSourceModel(&model); model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); + model.insertRows(0, sourceItems.size()); - for (int i = 0; i < sourceItems.count(); ++i) { + for (int i = 0; i < sourceItems.size(); ++i) { QModelIndex sindex = model.index(i, 0, QModelIndex()); model.setData(sindex, sourceItems.at(i), Qt::DisplayRole); QModelIndex pindex = proxy.index(i, 0, QModelIndex()); @@ -1609,16 +1584,16 @@ void tst_QSortFilterProxyModel::removeSourceRows() model.removeRows(start, count, QModelIndex()); - QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < aboutToRemoveSpy.count(); ++i) { + QCOMPARE(aboutToRemoveSpy.size(), expectedRemovedProxyIntervals.size()); + for (int i = 0; i < aboutToRemoveSpy.size(); ++i) { const auto &args = aboutToRemoveSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); } - QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < removeSpy.count(); ++i) { + QCOMPARE(removeSpy.size(), expectedRemovedProxyIntervals.size()); + for (int i = 0; i < removeSpy.size(); ++i) { const auto &args = removeSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); @@ -1626,11 +1601,11 @@ void tst_QSortFilterProxyModel::removeSourceRows() QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); } - QCOMPARE(insertSpy.count(), 0); - QCOMPARE(aboutToInsertSpy.count(), 0); + QCOMPARE(insertSpy.size(), 0); + QCOMPARE(aboutToInsertSpy.size(), 0); - QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count()); - for (int i = 0; i < expectedProxyItems.count(); ++i) { + QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.size()); + for (int i = 0; i < expectedProxyItems.size(); ++i) { QModelIndex pindex = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i)); } @@ -1677,9 +1652,9 @@ void tst_QSortFilterProxyModel::insertSourceRows() proxy.setSourceModel(&model); model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); + model.insertRows(0, sourceItems.size()); - for (int i = 0; i < sourceItems.count(); ++i) { + for (int i = 0; i < sourceItems.size(); ++i) { QModelIndex index = model.index(i, 0, QModelIndex()); model.setData(index, sourceItems.at(i), Qt::DisplayRole); } @@ -1689,13 +1664,13 @@ void tst_QSortFilterProxyModel::insertSourceRows() model.insertRows(start, newItems.size(), QModelIndex()); - QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count()); - for (int i = 0; i < newItems.count(); ++i) { + QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.size()); + for (int i = 0; i < newItems.size(); ++i) { QModelIndex index = model.index(start + i, 0, QModelIndex()); model.setData(index, newItems.at(i), Qt::DisplayRole); } - for (int i = 0; i < proxyItems.count(); ++i) { + for (int i = 0; i < proxyItems.size(); ++i) { QModelIndex index = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i)); } @@ -1768,9 +1743,9 @@ void tst_QSortFilterProxyModel::changeFilter() proxy.setSourceModel(&model); model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); + model.insertRows(0, sourceItems.size()); - for (int i = 0; i < sourceItems.count(); ++i) { + for (int i = 0; i < sourceItems.size(); ++i) { QModelIndex index = model.index(i, 0, QModelIndex()); model.setData(index, sourceItems.at(i), Qt::DisplayRole); } @@ -1786,9 +1761,9 @@ void tst_QSortFilterProxyModel::changeFilter() setupFilter(&proxy, initialFilter); - QCOMPARE(initialRemoveSpy.count(), initialRemoveIntervals.count()); - QCOMPARE(initialInsertSpy.count(), 0); - for (int i = 0; i < initialRemoveSpy.count(); ++i) { + QCOMPARE(initialRemoveSpy.size(), initialRemoveIntervals.size()); + QCOMPARE(initialInsertSpy.size(), 0); + for (int i = 0; i < initialRemoveSpy.size(); ++i) { const auto &args = initialRemoveSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); @@ -1796,8 +1771,8 @@ void tst_QSortFilterProxyModel::changeFilter() QCOMPARE(args.at(2).toInt(), initialRemoveIntervals.at(i).second); } - QCOMPARE(proxy.rowCount(QModelIndex()), initialProxyItems.count()); - for (int i = 0; i < initialProxyItems.count(); ++i) { + QCOMPARE(proxy.rowCount(QModelIndex()), initialProxyItems.size()); + for (int i = 0; i < initialProxyItems.size(); ++i) { QModelIndex index = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initialProxyItems.at(i)); } @@ -1810,8 +1785,8 @@ void tst_QSortFilterProxyModel::changeFilter() setupFilter(&proxy, finalFilter); - QCOMPARE(finalRemoveSpy.count(), finalRemoveIntervals.count()); - for (int i = 0; i < finalRemoveSpy.count(); ++i) { + QCOMPARE(finalRemoveSpy.size(), finalRemoveIntervals.size()); + for (int i = 0; i < finalRemoveSpy.size(); ++i) { const auto &args = finalRemoveSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); @@ -1819,8 +1794,8 @@ void tst_QSortFilterProxyModel::changeFilter() QCOMPARE(args.at(2).toInt(), finalRemoveIntervals.at(i).second); } - QCOMPARE(finalInsertSpy.count(), insertIntervals.count()); - for (int i = 0; i < finalInsertSpy.count(); ++i) { + QCOMPARE(finalInsertSpy.size(), insertIntervals.size()); + for (int i = 0; i < finalInsertSpy.size(); ++i) { const auto &args = finalInsertSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); @@ -1828,8 +1803,8 @@ void tst_QSortFilterProxyModel::changeFilter() QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second); } - QCOMPARE(proxy.rowCount(QModelIndex()), finalProxyItems.count()); - for (int i = 0; i < finalProxyItems.count(); ++i) { + QCOMPARE(proxy.rowCount(QModelIndex()), finalProxyItems.size()); + for (int i = 0; i < finalProxyItems.size(); ++i) { QModelIndex index = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), finalProxyItems.at(i)); } @@ -1992,9 +1967,9 @@ void tst_QSortFilterProxyModel::changeSourceData() proxy.setDynamicSortFilter(dynamic); proxy.setSourceModel(&model); model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); + model.insertRows(0, sourceItems.size()); - for (int i = 0; i < sourceItems.count(); ++i) { + for (int i = 0; i < sourceItems.size(); ++i) { QModelIndex index = model.index(i, 0, QModelIndex()); model.setData(index, sourceItems.at(i), Qt::DisplayRole); } @@ -2004,8 +1979,8 @@ void tst_QSortFilterProxyModel::changeSourceData() setupFilter(&proxy, filter); - QCOMPARE(proxy.rowCount(), expectedInitialProxyItems.count()); - for (int i = 0; i < expectedInitialProxyItems.count(); ++i) { + QCOMPARE(proxy.rowCount(), expectedInitialProxyItems.size()); + for (int i = 0; i < expectedInitialProxyItems.size(); ++i) { const QModelIndex index = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedInitialProxyItems.at(i)); } @@ -2025,8 +2000,8 @@ void tst_QSortFilterProxyModel::changeSourceData() model.setData(index, newValue, Qt::DisplayRole); } - QCOMPARE(removeSpy.count(), removeIntervals.count()); - for (int i = 0; i < removeSpy.count(); ++i) { + QCOMPARE(removeSpy.size(), removeIntervals.size()); + for (int i = 0; i < removeSpy.size(); ++i) { const auto &args = removeSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); @@ -2034,8 +2009,8 @@ void tst_QSortFilterProxyModel::changeSourceData() QCOMPARE(args.at(2).toInt(), removeIntervals.at(i).second); } - QCOMPARE(insertSpy.count(), insertIntervals.count()); - for (int i = 0; i < insertSpy.count(); ++i) { + QCOMPARE(insertSpy.size(), insertIntervals.size()); + for (int i = 0; i < insertSpy.size(); ++i) { const auto &args = insertSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); @@ -2043,29 +2018,29 @@ void tst_QSortFilterProxyModel::changeSourceData() QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second); } - QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count()); - for (int i = 0; i < proxyItems.count(); ++i) { + QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.size()); + for (int i = 0; i < proxyItems.size(); ++i) { QModelIndex index = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i)); } if (expectedDataChangedRow == -1) { - QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(dataChangedSpy.size(), 0); } else { - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); const QModelIndex idx = dataChangedSpy.at(0).at(0).value<QModelIndex>(); QCOMPARE(idx.row(), expectedDataChangedRow); QCOMPARE(idx.column(), 0); } - QCOMPARE(layoutChangedSpy.count(), expectedLayoutChanged ? 1 : 0); + QCOMPARE(layoutChangedSpy.size(), expectedLayoutChanged ? 1 : 0); } // Checks that the model is a table, and that each and every row is like this: // i-th row: ( rows.at(i), i ) static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows) { - QCOMPARE(model->rowCount(), rows.length()); + QCOMPARE(model->rowCount(), rows.size()); QCOMPARE(model->columnCount(), 2); for (int row = 0; row < model->rowCount(); ++row) { @@ -2089,7 +2064,7 @@ void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548() // Build a table of pairs (string, #row) in each row QStandardItemModel model(0, 2); - for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) { + for (int rowNumber = 0; rowNumber < rows.size(); ++rowNumber) { QStandardItem *column0 = new QStandardItem(rows.at(rowNumber)); column0->setCheckable(true); column0->setCheckState(Qt::Unchecked); @@ -2143,7 +2118,7 @@ void tst_QSortFilterProxyModel::changeSourceDataForwardsRoles_qtbug35440() QSignalSpy spy(&proxy, &QAbstractItemModel::dataChanged); QVERIFY(spy.isValid()); - QCOMPARE(spy.length(), 0); + QCOMPARE(spy.size(), 0); QModelIndex index; @@ -2156,13 +2131,13 @@ void tst_QSortFilterProxyModel::changeSourceDataForwardsRoles_qtbug35440() index = model.index(0, 0); QVERIFY(index.isValid()); model.setData(index, QStringLiteral("teststring"), Qt::DisplayRole); - QCOMPARE(spy.length(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(2).value<QList<int> >(), expectedChangedRoles); index = model.index(1, 0); QVERIFY(index.isValid()); model.setData(index, QStringLiteral("teststring2"), Qt::EditRole); - QCOMPARE(spy.length(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(spy.at(1).at(2).value<QList<int> >(), expectedChangedRoles); } @@ -2195,6 +2170,40 @@ void tst_QSortFilterProxyModel::changeSourceDataProxySendDataChanged_qtbug87781( QCOMPARE(afterDataChangedSpy.size(), 1); } +void tst_QSortFilterProxyModel::changeSourceDataTreeModel() +{ + QStandardItemModel treeModel; + QSortFilterProxyModel treeProxyModelBefore; + QSortFilterProxyModel treeProxyModelAfter; + + QSignalSpy treeBaseDataChangedSpy(&treeModel, &QStandardItemModel::dataChanged); + QSignalSpy treeBeforeDataChangedSpy(&treeProxyModelBefore, &QSortFilterProxyModel::dataChanged); + QSignalSpy treeAfterDataChangedSpy(&treeProxyModelAfter, &QSortFilterProxyModel::dataChanged); + + QVERIFY(treeBaseDataChangedSpy.isValid()); + QVERIFY(treeBeforeDataChangedSpy.isValid()); + QVERIFY(treeAfterDataChangedSpy.isValid()); + + treeProxyModelBefore.setSourceModel(&treeModel); + QStandardItem treeNode1("data1"); + QStandardItem treeNode11("data11"); + QStandardItem treeNode111("data111"); + + treeNode1.appendRow(&treeNode11); + treeNode11.appendRow(&treeNode111); + treeModel.appendRow(&treeNode1); + treeProxyModelAfter.setSourceModel(&treeModel); + + QCOMPARE(treeBaseDataChangedSpy.size(), 0); + QCOMPARE(treeBeforeDataChangedSpy.size(), 0); + QCOMPARE(treeAfterDataChangedSpy.size(), 0); + + treeNode111.setData(QStringLiteral("new data"), Qt::DisplayRole); + QCOMPARE(treeBaseDataChangedSpy.size(), 1); + QCOMPARE(treeBeforeDataChangedSpy.size(), 1); + QCOMPARE(treeAfterDataChangedSpy.size(), 1); +} + void tst_QSortFilterProxyModel::changeSourceDataProxyFilterSingleColumn() { enum modelRow { Row0, Row1, RowCount }; @@ -2375,8 +2384,8 @@ void tst_QSortFilterProxyModel::sortFilterRole() const QList<int> orderedItems({2, 1}); - model.insertRows(0, sourceItems.count()); - for (int i = 0; i < sourceItems.count(); ++i) { + model.insertRows(0, sourceItems.size()); + for (int i = 0; i < sourceItems.size(); ++i) { QModelIndex index = model.index(i, 0, QModelIndex()); model.setData(index, sourceItems.at(i).first, Qt::DisplayRole); model.setData(index, sourceItems.at(i).second, Qt::UserRole); @@ -2406,7 +2415,7 @@ void tst_QSortFilterProxyModel::sortFilterRole() proxy.setFilterRole(Qt::DisplayRole); setupFilter(&proxy, QLatin1String("a|c")); - QCOMPARE(proxy.rowCount(), orderedItems.count()); + QCOMPARE(proxy.rowCount(), orderedItems.size()); for (int i = 0; i < proxy.rowCount(); ++i) { QModelIndex index = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(index, Qt::DisplayRole), sourceItems.at(orderedItems.at(i)).first); @@ -2428,10 +2437,10 @@ void tst_QSortFilterProxyModel::selectionFilteredOut() QVERIFY(spy.isValid()); view.setCurrentIndex(proxy.index(0, 0)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); setupFilter(&proxy, QLatin1String("^B")); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QSortFilterProxyModel::match_data() @@ -2508,9 +2517,9 @@ void tst_QSortFilterProxyModel::match() proxy.setSourceModel(&model); model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); + model.insertRows(0, sourceItems.size()); - for (int i = 0; i < sourceItems.count(); ++i) { + for (int i = 0; i < sourceItems.size(); ++i) { QModelIndex index = model.index(i, 0, QModelIndex()); model.setData(index, sourceItems.at(i), Qt::DisplayRole); } @@ -2520,10 +2529,10 @@ void tst_QSortFilterProxyModel::match() QModelIndex startIndex = proxy.index(proxyStartRow, 0); QModelIndexList indexes = proxy.match(startIndex, Qt::DisplayRole, what, - expectedProxyItems.count(), + expectedProxyItems.size(), matchFlags); - QCOMPARE(indexes.count(), expectedProxyItems.count()); - for (int i = 0; i < indexes.count(); ++i) + QCOMPARE(indexes.size(), expectedProxyItems.size()); + for (int i = 0; i < indexes.size(); ++i) QCOMPARE(indexes.at(i).row(), expectedProxyItems.at(i)); } @@ -2586,13 +2595,13 @@ void tst_QSortFilterProxyModel::insertIntoChildrenlessItem() QVERIFY(rowsInsertedSpy.isValid()); (void)proxy.rowCount(QModelIndex()); // force mapping of "a", "b", "c" - QCOMPARE(colsInsertedSpy.count(), 0); - QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(colsInsertedSpy.size(), 0); + QCOMPARE(rowsInsertedSpy.size(), 0); // now add a child to itemB ==> should get insert notification from the proxy itemB->appendRow(new QStandardItem("a.0")); - QCOMPARE(colsInsertedSpy.count(), 1); - QCOMPARE(rowsInsertedSpy.count(), 1); + QCOMPARE(colsInsertedSpy.size(), 1); + QCOMPARE(rowsInsertedSpy.size(), 1); QVariantList args = colsInsertedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), proxy.mapFromSource(itemB->index())); @@ -2668,11 +2677,11 @@ void tst_QSortFilterProxyModel::insertRowIntoFilteredParent() QStandardItem *itemB = new QStandardItem(); itemA->appendRow(itemB); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); itemA->removeRow(0); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild() @@ -2699,9 +2708,9 @@ void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild() setupFilter(&proxy, QLatin1String("C")); // A and B will be filtered out, C filtered in // we should now have been notified that the subtree represented by itemA has been removed - QCOMPARE(removedSpy.count(), 1); + QCOMPARE(removedSpy.size(), 1); // we should NOT get any inserts; itemC should be filtered because its parent (itemA) is - QCOMPARE(insertedSpy.count(), 0); + QCOMPARE(insertedSpy.size(), 0); } void tst_QSortFilterProxyModel::sourceInsertRows() @@ -2794,13 +2803,13 @@ void tst_QSortFilterProxyModel::sortColumnTracking2() model.insertColumn(0,items); QCOMPARE(proxyModel.sortColumn(), 0); QCOMPARE(proxyModel.data(proxyModel.index(0,0)).toString(),QString::fromLatin1("aa")); - const int zzIndex = items.count() - 3; // 2 invalid at end. + const int zzIndex = items.size() - 3; // 2 invalid at end. QCOMPARE(proxyModel.data(proxyModel.index(zzIndex,0)).toString(),QString::fromLatin1("zz")); } void tst_QSortFilterProxyModel::sortStable() { - QStandardItemModel* model = new QStandardItemModel(5, 2); + QStandardItemModel model(5, 2); for (int r = 0; r < 5; r++) { const QString prefix = QLatin1String("Row:") + QString::number(r) + QLatin1String(", Column:"); for (int c = 0; c < 2; c++) { @@ -2809,24 +2818,24 @@ void tst_QSortFilterProxyModel::sortStable() QStandardItem* child = new QStandardItem(QLatin1String("Item ") + QString::number(i)); item->appendRow( child ); } - model->setItem(r, c, item); + model.setItem(r, c, item); } } - model->setHorizontalHeaderItem( 0, new QStandardItem( "Name" )); - model->setHorizontalHeaderItem( 1, new QStandardItem( "Value" )); + model.setHorizontalHeaderItem( 0, new QStandardItem( "Name" )); + model.setHorizontalHeaderItem( 1, new QStandardItem( "Value" )); - QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(model); - filterModel->setSourceModel(model); + QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(&model); + filterModel->setSourceModel(&model); - QTreeView *view = new QTreeView; - view->setModel(filterModel); + QTreeView view; + view.setModel(filterModel); QModelIndex firstRoot = filterModel->index(0,0); - view->expand(firstRoot); - view->setSortingEnabled(true); + view.expand(firstRoot); + view.setSortingEnabled(true); - view->model()->sort(1, Qt::DescendingOrder); + view.model()->sort(1, Qt::DescendingOrder); QVariant lastItemData =filterModel->index(2,0, firstRoot).data(); - view->model()->sort(1, Qt::DescendingOrder); + view.model()->sort(1, Qt::DescendingOrder); QCOMPARE(lastItemData, filterModel->index(2,0, firstRoot).data()); } @@ -2886,16 +2895,16 @@ void tst_QSortFilterProxyModel::staticSorting() // prepare model QStandardItem *root = model.invisibleRootItem (); QList<QStandardItem *> items; - for (int i = 0; i < initial.count(); ++i) { + for (int i = 0; i < initial.size(); ++i) { items.append(new QStandardItem(initial.at(i))); } root->insertRows(0, items); - QCOMPARE(model.rowCount(QModelIndex()), initial.count()); + QCOMPARE(model.rowCount(QModelIndex()), initial.size()); QCOMPARE(model.columnCount(QModelIndex()), 1); // make sure the proxy is unsorted QCOMPARE(proxy.columnCount(QModelIndex()), 1); - QCOMPARE(proxy.rowCount(QModelIndex()), initial.count()); + QCOMPARE(proxy.rowCount(QModelIndex()), initial.size()); for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { QModelIndex index = proxy.index(row, 0, QModelIndex()); QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initial.at(row)); @@ -2945,7 +2954,7 @@ void tst_QSortFilterProxyModel::dynamicSorting() QCOMPARE(proxy1.columnCount(QModelIndex()), 1); //the model should not be sorted because sorting has not been set to dynamic yet. - QCOMPARE(proxy1.rowCount(QModelIndex()), initial.count()); + QCOMPARE(proxy1.rowCount(QModelIndex()), initial.size()); for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { QModelIndex index = proxy1.index(row, 0, QModelIndex()); QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), initial.at(row)); @@ -3161,7 +3170,8 @@ void tst_QSortFilterProxyModel::mapFromToSource() QCOMPARE(proxy.mapFromSource(QModelIndex()), QModelIndex()); QCOMPARE(proxy.mapToSource(QModelIndex()), QModelIndex()); -#ifdef QT_NO_DEBUG //if Qt is compiled in debug mode, this will assert + // Will assert in debug, so only test in release +#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapToSource"); QCOMPARE(proxy.mapToSource(source.index(2, 3)), QModelIndex()); QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapFromSource"); @@ -3202,25 +3212,25 @@ void tst_QSortFilterProxyModel::removeRowsRecursive() QList<QPersistentModelIndex> sourceIndexes; QList<QPersistentModelIndex> proxyIndexes; - for (const auto item : qAsConst(items)) { + for (const auto item : std::as_const(items)) { QModelIndex idx = item->index(); sourceIndexes << idx; proxyIndexes << proxy.mapFromSource(idx); } - for (const auto &pidx : qAsConst(sourceIndexes)) + for (const auto &pidx : std::as_const(sourceIndexes)) QVERIFY(pidx.isValid()); - for (const auto &pidx : qAsConst(proxyIndexes)) + for (const auto &pidx : std::as_const(proxyIndexes)) QVERIFY(pidx.isValid()); QList<QStandardItem*> itemRow = pItem1->takeRow(0); - QCOMPARE(itemRow.count(), 1); + QCOMPARE(itemRow.size(), 1); QCOMPARE(itemRow.first(), pItem11); - for (const auto &pidx : qAsConst(sourceIndexes)) + for (const auto &pidx : std::as_const(sourceIndexes)) QVERIFY(!pidx.isValid()); - for (const auto &pidx : qAsConst(proxyIndexes)) + for (const auto &pidx : std::as_const(proxyIndexes)) QVERIFY(!pidx.isValid()); delete pItem11; @@ -3228,36 +3238,36 @@ void tst_QSortFilterProxyModel::removeRowsRecursive() void tst_QSortFilterProxyModel::doubleProxySelectionSetSourceModel() { - QStandardItemModel *model1 = new QStandardItemModel; - QStandardItem *parentItem = model1->invisibleRootItem(); + QStandardItemModel model1; + QStandardItem *parentItem = model1.invisibleRootItem(); for (int i = 0; i < 4; ++i) { QStandardItem *item = new QStandardItem(QLatin1String("model1 item ") + QString::number(i)); parentItem->appendRow(item); parentItem = item; } - QStandardItemModel *model2 = new QStandardItemModel; - QStandardItem *parentItem2 = model2->invisibleRootItem(); + QStandardItemModel model2; + QStandardItem *parentItem2 = model2.invisibleRootItem(); for (int i = 0; i < 4; ++i) { QStandardItem *item = new QStandardItem(QLatin1String("model2 item ") + QString::number(i)); parentItem2->appendRow(item); parentItem2 = item; } - QSortFilterProxyModel *toggleProxy = new QSortFilterProxyModel; - toggleProxy->setSourceModel(model1); + QSortFilterProxyModel toggleProxy; + toggleProxy.setSourceModel(&model1); - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel; - proxyModel->setSourceModel(toggleProxy); + QSortFilterProxyModel proxyModel; + proxyModel.setSourceModel(&toggleProxy); - QModelIndex mi = proxyModel->index(0, 0, proxyModel->index(0, 0, proxyModel->index(0, 0))); - QItemSelectionModel ism(proxyModel); + QModelIndex mi = proxyModel.index(0, 0, proxyModel.index(0, 0, proxyModel.index(0, 0))); + QItemSelectionModel ism(&proxyModel); ism.select(mi, QItemSelectionModel::Select); QModelIndexList mil = ism.selectedIndexes(); - QCOMPARE(mil.count(), 1); + QCOMPARE(mil.size(), 1); QCOMPARE(mil.first(), mi); - toggleProxy->setSourceModel(model2); + toggleProxy.setSourceModel(&model2); // No crash, it's good news! QVERIFY(ism.selection().isEmpty()); } @@ -3325,10 +3335,10 @@ void tst_QSortFilterProxyModel::appearsAndSort() QCOMPARE(secondProxyModel.data(secondProxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b")); QCOMPARE(secondProxyModel.data(secondProxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("a")); - QCOMPARE(spyAbout1.count(), 1); - QCOMPARE(spyChanged1.count(), 1); - QCOMPARE(spyAbout2.count(), 1); - QCOMPARE(spyChanged2.count(), 1); + QCOMPARE(spyAbout1.size(), 1); + QCOMPARE(spyChanged1.size(), 1); + QCOMPARE(spyAbout2.size(), 1); + QCOMPARE(spyChanged2.size(), 1); } void tst_QSortFilterProxyModel::unnecessaryDynamicSorting() @@ -4635,7 +4645,7 @@ public: return lst.at(index.row()); return QVariant(); } - int rowCount(const QModelIndex & = QModelIndex()) const override { return lst.count(); } + int rowCount(const QModelIndex & = QModelIndex()) const override { return lst.size(); } void replaceData(const QStringList &newData) { @@ -4776,7 +4786,7 @@ void tst_QSortFilterProxyModel::removeIntervals() model.replaceData(sourceItems); proxy.setSourceModel(&model); - for (int i = 0; i < sourceItems.count(); ++i) { + for (int i = 0; i < sourceItems.size(); ++i) { QModelIndex sindex = model.index(i, 0, QModelIndex()); QModelIndex pindex = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole)); @@ -4801,16 +4811,16 @@ void tst_QSortFilterProxyModel::removeIntervals() model.replaceData(replacementSourceItems); - QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < aboutToRemoveSpy.count(); ++i) { + QCOMPARE(aboutToRemoveSpy.size(), expectedRemovedProxyIntervals.size()); + for (int i = 0; i < aboutToRemoveSpy.size(); ++i) { const auto &args = aboutToRemoveSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); } - QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < removeSpy.count(); ++i) { + QCOMPARE(removeSpy.size(), expectedRemovedProxyIntervals.size()); + for (int i = 0; i < removeSpy.size(); ++i) { const auto &args = removeSpy.at(i); QCOMPARE(args.at(1).userType(), QMetaType::Int); QCOMPARE(args.at(2).userType(), QMetaType::Int); @@ -4818,11 +4828,11 @@ void tst_QSortFilterProxyModel::removeIntervals() QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); } - QCOMPARE(insertSpy.count(), 0); - QCOMPARE(aboutToInsertSpy.count(), 0); + QCOMPARE(insertSpy.size(), 0); + QCOMPARE(aboutToInsertSpy.size(), 0); - QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count()); - for (int i = 0; i < expectedProxyItems.count(); ++i) { + QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.size()); + for (int i = 0; i < expectedProxyItems.size(); ++i) { QModelIndex pindex = proxy.index(i, 0, QModelIndex()); QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i)); } @@ -4849,7 +4859,7 @@ void tst_QSortFilterProxyModel::dynamicFilterWithoutSort() QCOMPARE(model.stringList(), QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday"); - QCOMPARE(resetSpy.count(), 1); + QCOMPARE(resetSpy.size(), 1); } void tst_QSortFilterProxyModel::checkSetNewModel() @@ -5102,7 +5112,7 @@ void tst_QSortFilterProxyModel::filterAndInsertRow() QVERIFY(proxyModel.insertRow(row)); QCOMPARE(model.stringList(), expectedModelList); - QCOMPARE(proxyModel.rowCount(), expectedProxyModelList.count()); + QCOMPARE(proxyModel.rowCount(), expectedProxyModelList.size()); for (int r = 0; r < proxyModel.rowCount(); ++r) { QModelIndex index = proxyModel.index(r, 0); QVERIFY(index.isValid()); @@ -5291,4 +5301,201 @@ void tst_QSortFilterProxyModel::invalidateColumnsOrRowsFilter() QCOMPARE(proxy.rowFiltered, 20); } +void tst_QSortFilterProxyModel::filterKeyColumnBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.filterKeyColumn(), 0); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, int>(proxyModel, 10, 5, + "filterKeyColumn"); +} + +void tst_QSortFilterProxyModel::dynamicSortFilterBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.dynamicSortFilter(), true); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, bool>(proxyModel, false, true, + "dynamicSortFilter"); +} + +void tst_QSortFilterProxyModel::sortCaseSensitivityBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.sortCaseSensitivity(), Qt::CaseSensitive); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, Qt::CaseSensitivity>( + proxyModel, Qt::CaseInsensitive, Qt::CaseSensitive, "sortCaseSensitivity"); +} + +void tst_QSortFilterProxyModel::isSortLocaleAwareBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.isSortLocaleAware(), false); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, bool>(proxyModel, true, false, + "isSortLocaleAware"); +} + +void tst_QSortFilterProxyModel::sortRoleBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.sortRole(), Qt::DisplayRole); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, int>( + proxyModel, Qt::TextAlignmentRole, Qt::ToolTipRole, "sortRole"); +} + +void tst_QSortFilterProxyModel::filterRoleBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.filterRole(), Qt::DisplayRole); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, int>( + proxyModel, Qt::DecorationRole, Qt::CheckStateRole, "filterRole"); +} + +void tst_QSortFilterProxyModel::recursiveFilteringEnabledBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.isRecursiveFilteringEnabled(), false); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, bool>( + proxyModel, true, false, "recursiveFilteringEnabled"); +} + +void tst_QSortFilterProxyModel::autoAcceptChildRowsBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.autoAcceptChildRows(), false); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, bool>(proxyModel, true, false, + "autoAcceptChildRows"); +} + +void tst_QSortFilterProxyModel::filterCaseSensitivityBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseSensitive); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, Qt::CaseSensitivity>( + proxyModel, Qt::CaseInsensitive, Qt::CaseSensitive, "filterCaseSensitivity"); + if (QTest::currentTestFailed()) + return; + + // Make sure that setting QRegularExpression updates filterCaseSensitivity + // and invalidates its binding. + QProperty<Qt::CaseSensitivity> setter(Qt::CaseSensitive); + proxyModel.bindableFilterCaseSensitivity().setBinding(Qt::makePropertyBinding(setter)); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseSensitive); + QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding()); + + QSignalSpy spy(&proxyModel, &QSortFilterProxyModel::filterCaseSensitivityChanged); + QRegularExpression regExp("pattern", QRegularExpression::CaseInsensitiveOption); + proxyModel.setFilterRegularExpression(regExp); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseInsensitive); + QCOMPARE(spy.size(), 1); + QVERIFY(!proxyModel.bindableFilterCaseSensitivity().hasBinding()); +} + +void tst_QSortFilterProxyModel::filterRegularExpressionBinding() +{ + QSortFilterProxyModel proxyModel; + QCOMPARE(proxyModel.filterRegularExpression(), QRegularExpression()); + const QRegularExpression initial("initial", QRegularExpression::CaseInsensitiveOption); + const QRegularExpression changed("changed"); + QTestPrivate::testReadWritePropertyBasics<QSortFilterProxyModel, QRegularExpression>( + proxyModel, initial, changed, "filterRegularExpression"); + if (QTest::currentTestFailed()) + return; + + // Make sure that setting filterCaseSensitivity updates QRegularExpression + // and invalidates its binding. + QProperty<QRegularExpression> setter(initial); + proxyModel.bindableFilterRegularExpression().setBinding(Qt::makePropertyBinding(setter)); + QCOMPARE(proxyModel.filterRegularExpression(), initial); + QVERIFY(proxyModel.bindableFilterRegularExpression().hasBinding()); + + int counter = 0; + auto handler = proxyModel.bindableFilterRegularExpression().onValueChanged( + [&counter]() { ++counter; }); + Q_UNUSED(handler); + proxyModel.setFilterCaseSensitivity(Qt::CaseSensitive); + QCOMPARE(proxyModel.filterRegularExpression(), QRegularExpression(initial.pattern())); + QCOMPARE(counter, 1); + QVERIFY(!proxyModel.bindableFilterRegularExpression().hasBinding()); + + QProperty<Qt::CaseSensitivity> csSetter(Qt::CaseInsensitive); + // Make sure that setting filter string updates QRegularExpression, but does + // not break the binding for case sensitivity. + proxyModel.setFilterRegularExpression(initial); + proxyModel.bindableFilterCaseSensitivity().setBinding(Qt::makePropertyBinding(csSetter)); + QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding()); + + counter = 0; + proxyModel.setFilterRegularExpression("ch(ang|opp)ed"); + // The pattern has changed, but the case sensitivity options are the same. + QCOMPARE(proxyModel.filterRegularExpression(), + QRegularExpression("ch(ang|opp)ed", QRegularExpression::CaseInsensitiveOption)); + QCOMPARE(counter, 1); + QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding()); + + // Make sure that setting filter wildcard updates QRegularExpression, but + // does not break the binding for case sensitivity. + proxyModel.setFilterRegularExpression(initial); + proxyModel.bindableFilterCaseSensitivity().setBinding(Qt::makePropertyBinding(csSetter)); + QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding()); + + counter = 0; + proxyModel.setFilterWildcard("*.jpeg"); + const QString wildcardStr = QRegularExpression::wildcardToRegularExpression( + "*.jpeg", QRegularExpression::UnanchoredWildcardConversion); + // The pattern has changed, but the case sensitivity options are the same. + QCOMPARE(proxyModel.filterRegularExpression(), + QRegularExpression(wildcardStr, QRegularExpression::CaseInsensitiveOption)); + QCOMPARE(counter, 1); + QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding()); + + // Make sure that setting filter fixed string updates QRegularExpression, + // but does not break the binding for case sensitivity. + proxyModel.setFilterRegularExpression(initial); + proxyModel.bindableFilterCaseSensitivity().setBinding(Qt::makePropertyBinding(csSetter)); + QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding()); + + counter = 0; + proxyModel.setFilterFixedString("test"); + // The pattern has changed, but the case sensitivity options are the same. + QCOMPARE(proxyModel.filterRegularExpression(), + QRegularExpression("test", QRegularExpression::CaseInsensitiveOption)); + QCOMPARE(counter, 1); + QVERIFY(proxyModel.bindableFilterCaseSensitivity().hasBinding()); +} + +void tst_QSortFilterProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466 +{ + QStandardItemModel model(3, 1); + for (int row = 0; row < 3; ++row) + model.setData(model.index(row, 0), row, Qt::UserRole); + QSortFilterProxyModel proxy; + new QAbstractItemModelTester(&proxy, &proxy); + proxy.setSourceModel(&model); + proxy.setSortRole(Qt::UserRole); + QList<QPersistentModelIndex> idxList; + QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged); + QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged); + connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){ + idxList.clear(); + for (int row = 0; row < 3; ++row) + idxList << QPersistentModelIndex(proxy.index(row, 0)); + }); + connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){ + QCOMPARE(idxList.size(), 3); + QCOMPARE(idxList.at(0).row(), 1); + QCOMPARE(idxList.at(0).column(), 0); + QCOMPARE(idxList.at(0).data(Qt::UserRole).toInt(), 0); + QCOMPARE(idxList.at(1).row(), 0); + QCOMPARE(idxList.at(1).column(), 0); + QCOMPARE(idxList.at(1).data(Qt::UserRole).toInt(), -1); + QCOMPARE(idxList.at(2).row(), 2); + QCOMPARE(idxList.at(2).column(), 0); + QCOMPARE(idxList.at(2).data(Qt::UserRole).toInt(), 2); + }); + model.setData(model.index(1, 0), -1, Qt::UserRole); + proxy.sort(0); + QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); +} + +QTEST_MAIN(tst_QSortFilterProxyModel) #include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.h index 3fca4aad28..088a5b552e 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.h @@ -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) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef TST_QSORTFILTERPROXYMODEL_H #define TST_QSORTFILTERPROXYMODEL_H @@ -55,6 +30,7 @@ private slots: void sort(); void sortHierarchy_data(); void sortHierarchy(); + void createPersistentOnLayoutAboutToBeChanged(); void insertRows_data(); void insertRows(); @@ -91,6 +67,7 @@ private slots: void changeSourceDataKeepsStableSorting_qtbug1548(); void changeSourceDataForwardsRoles_qtbug35440(); void changeSourceDataProxySendDataChanged_qtbug87781(); + void changeSourceDataTreeModel(); void changeSourceDataProxyFilterSingleColumn(); void changeSourceDataProxyFilterMultipleColumns(); void resortingDoesNotBreakTreeModels(); @@ -165,6 +142,17 @@ private slots: void checkFilteredIndexes(); void invalidateColumnsOrRowsFilter(); + void filterKeyColumnBinding(); + void dynamicSortFilterBinding(); + void sortCaseSensitivityBinding(); + void isSortLocaleAwareBinding(); + void sortRoleBinding(); + void filterRoleBinding(); + void recursiveFilteringEnabledBinding(); + void autoAcceptChildRowsBinding(); + void filterCaseSensitivityBinding(); + void filterRegularExpressionBinding(); + protected: void buildHierarchy(const QStringList &data, QAbstractItemModel *model); void checkHierarchy(const QStringList &data, const QAbstractItemModel *model); diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/CMakeLists.txt b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/CMakeLists.txt index 815b68e582..2f08bf1b26 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/CMakeLists.txt @@ -1,14 +1,19 @@ -# Generated from qsortfilterproxymodel_recursive.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsortfilterproxymodel_recursive Test: ##################################################################### -qt_internal_add_test(tst_qsortfilterproxymodel_recursive +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsfpm_recursive LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qsfpm_recursive SOURCES tst_qsortfilterproxymodel_recursive.cpp - DEFINES - QT_DISABLE_DEPRECATED_BEFORE=0 - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp index d6a09056ae..c6b24a489a 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, authors Filipe Azevedo <filipe.azevedo@kdab.com> and David Faure <david.faure@kdab.com> -** 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) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, authors Filipe Azevedo <filipe.azevedo@kdab.com> and David Faure <david.faure@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSignalSpy> @@ -144,7 +119,7 @@ static void fillModel(QStandardItemModel &model, const QString &str) QCOMPARE(str.count('['), str.count(']')); QStandardItem *item = nullptr; QString data; - for ( int i = 0 ; i < str.length() ; ++i ) { + for ( int i = 0 ; i < str.size() ; ++i ) { const QChar ch = str.at(i); if ((ch == '[' || ch == ']' || ch == ' ') && !data.isEmpty()) { if (data.endsWith('*')) { diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/CMakeLists.txt b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/CMakeLists.txt index 7c4f60dab4..d82c2118b5 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/CMakeLists.txt @@ -1,18 +1,21 @@ -# Generated from qsortfilterproxymodel_regularexpression.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsortfilterproxymodel_regularexpression Test: ##################################################################### -qt_internal_add_test(tst_qsortfilterproxymodel_regularexpression +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsfpm_regex LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qsfpm_regex SOURCES - ../../../other/qabstractitemmodelutils/dynamictreemodel.cpp ../../../other/qabstractitemmodelutils/dynamictreemodel.h - ../qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp ../qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h tst_qsortfilterproxymodel_regularexpression.cpp INCLUDE_DIRECTORIES ../../../other/qabstractitemmodelutils - ../qsortfilterproxymodel_common - PUBLIC_LIBRARIES - Qt::Gui - Qt::Widgets + LIBRARIES + Qt::TestPrivate ) diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp index adeb0cfe5a..729da48c5e 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp @@ -1,51 +1,22 @@ -/**************************************************************************** -** -** 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 <QTest> +#include <QSignalSpy> #include <QStringListModel> +#include <QSortFilterProxyModel> -#include "tst_qsortfilterproxymodel.h" - -class tst_QSortFilterProxyModelRegularExpression : public tst_QSortFilterProxyModel +class tst_QSortFilterProxyModelRegularExpression : public QObject { Q_OBJECT -public: - tst_QSortFilterProxyModelRegularExpression(); private slots: void tst_invalid(); void tst_caseSensitivity(); + void tst_keepCaseSensitivity_QTBUG_92260(); + void tst_keepPatternOptions_QTBUG_92260(); + void tst_regexCaseSensitivityNotification(); }; -tst_QSortFilterProxyModelRegularExpression::tst_QSortFilterProxyModelRegularExpression() : - tst_QSortFilterProxyModel() -{ -} - void tst_QSortFilterProxyModelRegularExpression::tst_invalid() { const QLatin1String pattern("test"); @@ -74,5 +45,86 @@ void tst_QSortFilterProxyModelRegularExpression::tst_caseSensitivity() QCOMPARE(proxyModel.rowCount(), 2); } +/*! + This test ensures that when a string pattern is passed to setRegularEpxression, + the options are properly reseted but that the case sensitivity is kept as is. + + */ +void tst_QSortFilterProxyModelRegularExpression::tst_keepCaseSensitivity_QTBUG_92260() +{ + const QLatin1String pattern("test"); + QStringListModel model({ "test", "TesT" }); + QSortFilterProxyModel proxyModel; + proxyModel.setSourceModel(&model); + + QRegularExpression patternWithOptions("Dummy", + QRegularExpression::MultilineOption + | QRegularExpression::CaseInsensitiveOption); + + proxyModel.setFilterRegularExpression(patternWithOptions); + QCOMPARE(proxyModel.filterRegularExpression(), patternWithOptions); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseInsensitive); + + proxyModel.setFilterRegularExpression(pattern); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseInsensitive); + QCOMPARE(proxyModel.filterRegularExpression().patternOptions(), + QRegularExpression::CaseInsensitiveOption); + + patternWithOptions.setPatternOptions(QRegularExpression::MultilineOption); + proxyModel.setFilterRegularExpression(patternWithOptions); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseSensitive); + QCOMPARE(proxyModel.filterRegularExpression(), patternWithOptions); + + proxyModel.setFilterRegularExpression(pattern); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseSensitive); + QCOMPARE(proxyModel.filterRegularExpression().patternOptions(), + QRegularExpression::NoPatternOption); +} + +/*! + This test ensures that when the case sensitivity is changed, it does not nuke + the pattern options that were set before. + */ +void tst_QSortFilterProxyModelRegularExpression::tst_keepPatternOptions_QTBUG_92260() +{ + QStringListModel model({ "test", "TesT" }); + QSortFilterProxyModel proxyModel; + proxyModel.setSourceModel(&model); + + QRegularExpression patternWithOptions("Dummy", + QRegularExpression::MultilineOption + | QRegularExpression::CaseInsensitiveOption); + + proxyModel.setFilterRegularExpression(patternWithOptions); + QCOMPARE(proxyModel.filterRegularExpression(), patternWithOptions); + + proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseInsensitive); + QCOMPARE(proxyModel.filterRegularExpression().patternOptions(), + patternWithOptions.patternOptions()); + + proxyModel.setFilterCaseSensitivity(Qt::CaseSensitive); + QCOMPARE(proxyModel.filterCaseSensitivity(), Qt::CaseSensitive); + QCOMPARE(proxyModel.filterRegularExpression().patternOptions(), + QRegularExpression::MultilineOption); +} + +/*! + This test ensures that if the case sensitivity is changed during a call to + setFilterRegularExpression, the notification signal will be emitted +*/ +void tst_QSortFilterProxyModelRegularExpression::tst_regexCaseSensitivityNotification() +{ + QSortFilterProxyModel proxy; + QSignalSpy spy(&proxy, &QSortFilterProxyModel::filterCaseSensitivityChanged); + proxy.setFilterCaseSensitivity(Qt::CaseInsensitive); + QCOMPARE(spy.size(), 1); + QRegularExpression re("regex"); + QVERIFY(!re.patternOptions().testFlag(QRegularExpression::CaseInsensitiveOption)); + proxy.setFilterRegularExpression(re); + QCOMPARE(proxy.filterCaseSensitivity(), Qt::CaseSensitive); + QCOMPARE(spy.size(), 2); +} + QTEST_MAIN(tst_QSortFilterProxyModelRegularExpression) #include "tst_qsortfilterproxymodel_regularexpression.moc" diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qstringlistmodel/CMakeLists.txt index c6123bb1e3..8a00d1cd42 100644 --- a/tests/auto/corelib/itemmodels/qstringlistmodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qstringlistmodel/CMakeLists.txt @@ -1,9 +1,16 @@ -# Generated from qstringlistmodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qstringlistmodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstringlistmodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qstringlistmodel SOURCES qmodellistener.h diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/qmodellistener.h b/tests/auto/corelib/itemmodels/qstringlistmodel/qmodellistener.h index e08a0bdb1f..ecf7214ba4 100644 --- a/tests/auto/corelib/itemmodels/qstringlistmodel/qmodellistener.h +++ b/tests/auto/corelib/itemmodels/qstringlistmodel/qmodellistener.h @@ -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 <QObject> #include <QModelIndex> diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp index 79ad4145a2..8ec2aeabe5 100644 --- a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp +++ b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.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 <QTest> #include <QSignalSpy> @@ -93,6 +68,7 @@ private slots: void itemData(); void setItemData(); + void createPersistentOnLayoutAboutToBeChanged(); }; void tst_QStringListModel::moveRowsInvalid_data() @@ -430,7 +406,7 @@ void tst_QStringListModel::setData_emits_on_change_only() const QModelIndex modelIdx = model.index(0, 0); const QString newStringData = QStringLiteral("test"); QVERIFY(model.setData(modelIdx, newStringData)); - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); const QList<QVariant> spyList = dataChangedSpy.takeFirst(); QCOMPARE(spyList.at(0).value<QModelIndex>(), modelIdx); QCOMPARE(spyList.at(1).value<QModelIndex>(), modelIdx); @@ -447,5 +423,34 @@ void tst_QStringListModel::supportedDragDropActions() QCOMPARE(model.supportedDropActions(), Qt::CopyAction | Qt::MoveAction); } +void tst_QStringListModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466 +{ + QStringListModel model(QStringList{QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3")}); + QList<QPersistentModelIndex> idxList; + QSignalSpy layoutAboutToBeChangedSpy(&model, &QAbstractItemModel::layoutAboutToBeChanged); + QSignalSpy layoutChangedSpy(&model, &QAbstractItemModel::layoutChanged); + connect(&model, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &model](){ + idxList.clear(); + for (int row = 0; row < 3; ++row) + idxList << QPersistentModelIndex(model.index(row, 0)); + }); + connect(&model, &QAbstractItemModel::layoutChanged, this, [&idxList](){ + QCOMPARE(idxList.size(), 3); + QCOMPARE(idxList.at(0).row(), 1); + QCOMPARE(idxList.at(0).column(), 0); + QCOMPARE(idxList.at(0).data().toString(), QStringLiteral("1")); + QCOMPARE(idxList.at(1).row(), 0); + QCOMPARE(idxList.at(1).column(), 0); + QCOMPARE(idxList.at(1).data().toString(), QStringLiteral("0")); + QCOMPARE(idxList.at(2).row(), 2); + QCOMPARE(idxList.at(2).column(), 0); + QCOMPARE(idxList.at(2).data().toString(), QStringLiteral("3")); + }); + model.setData(model.index(1, 0), QStringLiteral("0")); + model.sort(0); + QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); +} + QTEST_MAIN(tst_QStringListModel) #include "tst_qstringlistmodel.moc" diff --git a/tests/auto/corelib/itemmodels/qtransposeproxymodel/CMakeLists.txt b/tests/auto/corelib/itemmodels/qtransposeproxymodel/CMakeLists.txt index 7cc675d7fd..b8ad00ca00 100644 --- a/tests/auto/corelib/itemmodels/qtransposeproxymodel/CMakeLists.txt +++ b/tests/auto/corelib/itemmodels/qtransposeproxymodel/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qtransposeproxymodel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtransposeproxymodel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtransposeproxymodel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtransposeproxymodel SOURCES tst_qtransposeproxymodel.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp b/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp index 8e8d1ec709..127b5c6ba0 100644 --- a/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSignalSpy> @@ -84,6 +48,8 @@ private Q_SLOTS: void setItemData(); void moveRowsBase(); void moveColumnsProxy(); + void sortPersistentIndex(); + void createPersistentOnLayoutAboutToBeChanged(); private: void testTransposed( const QAbstractItemModel *const baseModel, @@ -298,8 +264,8 @@ void tst_QTransposeProxyModel::sort() QVERIFY(layoutAboutToBeChangedSpy.isValid()); QPersistentModelIndex firstIndexBeforeSort = proxyModel.index(0, 0); baseModel.sort(0, Qt::AscendingOrder); - QCOMPARE(layoutChangedSpy.count(), 1); - QCOMPARE(layoutAboutToBeChangedSpy.count(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); + QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); QCOMPARE(layoutChangedSpy.takeFirst().at(1).toInt(), int(QAbstractItemModel::HorizontalSortHint)); QCOMPARE(firstIndexBeforeSort.data().toString(), firstItemBeforeSort); for (int i = 0; i < 100; ++i) @@ -332,8 +298,8 @@ void tst_QTransposeProxyModel::removeColumnBase() QVERIFY(model->removeColumn(1, parent)); QCOMPARE(proxy.rowCount(proxy.mapFromSource(parent)), oldRowCount - 1); QCOMPARE(proxy.index(1, 0, proxy.mapFromSource(parent)).data(), expectedNewVal); - QCOMPARE(rowRemoveSpy.count(), 1); - QCOMPARE(rowAboutToBeRemoveSpy.count(), 1); + QCOMPARE(rowRemoveSpy.size(), 1); + QCOMPARE(rowAboutToBeRemoveSpy.size(), 1); for (const auto &spyArgs : {rowRemoveSpy.takeFirst(), rowAboutToBeRemoveSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent)); @@ -343,6 +309,84 @@ void tst_QTransposeProxyModel::removeColumnBase() delete model; } +void tst_QTransposeProxyModel::sortPersistentIndex() +{ + QStringListModel model(QStringList{QStringLiteral("Alice"), QStringLiteral("Charlie"), QStringLiteral("Bob")}); + QTransposeProxyModel proxy; + new QAbstractItemModelTester(&proxy, &proxy); + proxy.setSourceModel(&model); + QPersistentModelIndex aliceIdx = proxy.index(0, 0); + QPersistentModelIndex bobIdx = proxy.index(0, 2); + QPersistentModelIndex charlieIdx = proxy.index(0, 1); + connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&aliceIdx, &bobIdx, &charlieIdx](){ + QCOMPARE(aliceIdx.row(), 0); + QCOMPARE(aliceIdx.column(), 0); + QCOMPARE(aliceIdx.data().toString(), QStringLiteral("Alice")); + QCOMPARE(bobIdx.row(), 0); + QCOMPARE(bobIdx.column(), 2); + QCOMPARE(bobIdx.data().toString(), QStringLiteral("Bob")); + QCOMPARE(charlieIdx.row(), 0); + QCOMPARE(charlieIdx.column(), 1); + QCOMPARE(charlieIdx.data().toString(), QStringLiteral("Charlie")); + }); + connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&aliceIdx, &bobIdx, &charlieIdx](){ + QCOMPARE(aliceIdx.row(), 0); + QCOMPARE(aliceIdx.column(), 0); + QCOMPARE(aliceIdx.data().toString(), QStringLiteral("Alice")); + QCOMPARE(bobIdx.row(), 0); + QCOMPARE(bobIdx.column(), 1); + QCOMPARE(bobIdx.data().toString(), QStringLiteral("Bob")); + QCOMPARE(charlieIdx.row(), 0); + QCOMPARE(charlieIdx.column(), 2); + QCOMPARE(charlieIdx.data().toString(), QStringLiteral("Charlie")); + }); + model.sort(0); + QCOMPARE(aliceIdx.row(), 0); + QCOMPARE(aliceIdx.column(), 0); + QCOMPARE(aliceIdx.data().toString(), QStringLiteral("Alice")); + QCOMPARE(bobIdx.row(), 0); + QCOMPARE(bobIdx.column(), 1); + QCOMPARE(bobIdx.data().toString(), QStringLiteral("Bob")); + QCOMPARE(charlieIdx.row(), 0); + QCOMPARE(charlieIdx.column(), 2); + QCOMPARE(charlieIdx.data().toString(), QStringLiteral("Charlie")); +} + +void tst_QTransposeProxyModel::createPersistentOnLayoutAboutToBeChanged() // QTBUG-93466 +{ + QStandardItemModel model(3, 1); + for (int row = 0; row < 3; ++row) + model.setData(model.index(row, 0), row, Qt::UserRole); + model.setSortRole(Qt::UserRole); + QTransposeProxyModel proxy; + new QAbstractItemModelTester(&proxy, &proxy); + proxy.setSourceModel(&model); + QList<QPersistentModelIndex> idxList; + QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QAbstractItemModel::layoutAboutToBeChanged); + QSignalSpy layoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged); + connect(&proxy, &QAbstractItemModel::layoutAboutToBeChanged, this, [&idxList, &proxy](){ + idxList.clear(); + for (int row = 0; row < 3; ++row) + idxList << QPersistentModelIndex(proxy.index(0, row)); + }); + connect(&proxy, &QAbstractItemModel::layoutChanged, this, [&idxList](){ + QCOMPARE(idxList.size(), 3); + QCOMPARE(idxList.at(0).row(), 0); + QCOMPARE(idxList.at(0).column(), 1); + QCOMPARE(idxList.at(0).data(Qt::UserRole).toInt(), 0); + QCOMPARE(idxList.at(1).row(), 0); + QCOMPARE(idxList.at(1).column(), 0); + QCOMPARE(idxList.at(1).data(Qt::UserRole).toInt(), -1); + QCOMPARE(idxList.at(2).row(), 0); + QCOMPARE(idxList.at(2).column(), 2); + QCOMPARE(idxList.at(2).data(Qt::UserRole).toInt(), 2); + }); + model.setData(model.index(1, 0), -1, Qt::UserRole); + model.sort(0); + QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); +} + void tst_QTransposeProxyModel::insertColumnBase_data() { QTest::addColumn<QAbstractItemModel *>("model"); @@ -368,8 +412,8 @@ void tst_QTransposeProxyModel::insertColumnBase() QVERIFY(model->insertColumn(1, parent)); QCOMPARE(proxy.rowCount(proxy.mapFromSource(parent)), oldRowCount + 1); QVERIFY(!proxy.index(1, 0, proxy.mapFromSource(parent)).data().isValid()); - QCOMPARE(rowInsertSpy.count(), 1); - QCOMPARE(rowAboutToBeInsertSpy.count(), 1); + QCOMPARE(rowInsertSpy.size(), 1); + QCOMPARE(rowAboutToBeInsertSpy.size(), 1); for (const auto &spyArgs : {rowInsertSpy.takeFirst(), rowAboutToBeInsertSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent)); @@ -406,8 +450,8 @@ void tst_QTransposeProxyModel::removeRowBase() QVERIFY(model->removeRow(1, parent)); QCOMPARE(proxy.columnCount(proxy.mapFromSource(parent)), oldColCount - 1); QCOMPARE(proxy.index(0, 1, proxy.mapFromSource(parent)).data(), expectedNewVal); - QCOMPARE(columnsRemoveSpy.count(), 1); - QCOMPARE(columnsAboutToBeRemoveSpy.count(), 1); + QCOMPARE(columnsRemoveSpy.size(), 1); + QCOMPARE(columnsAboutToBeRemoveSpy.size(), 1); for (const auto &spyArgs : {columnsRemoveSpy.takeFirst(), columnsAboutToBeRemoveSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent)); @@ -444,8 +488,8 @@ void tst_QTransposeProxyModel::insertRowBase() QCOMPARE(proxy.columnCount(proxy.mapFromSource(parent)), oldColCount + 1); QVariant result = proxy.index(0, 1, proxy.mapFromSource(parent)).data(); QVERIFY(result.isNull() || (result.metaType().id() == QMetaType::QString && result.toString().isNull())); - QCOMPARE(columnsInsertSpy.count(), 1); - QCOMPARE(columnsAboutToBeInsertSpy.count(), 1); + QCOMPARE(columnsInsertSpy.size(), 1); + QCOMPARE(columnsAboutToBeInsertSpy.size(), 1); for (const auto &spyArgs : {columnsInsertSpy.takeFirst(), columnsAboutToBeInsertSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent)); @@ -490,10 +534,10 @@ void tst_QTransposeProxyModel::removeColumnProxy() QCOMPARE(model->rowCount(sourceParent), oldRowCount - 1); QCOMPARE(proxy.index(0, 1, proxyParent).data(), expectedNewVal); QCOMPARE(model->index(1, 0, sourceParent).data(), expectedNewVal); - QCOMPARE(columnsRemoveSpy.count(), 1); - QCOMPARE(columnsAboutToBeRemoveSpy.count(), 1); - QCOMPARE(rowsRemoveSpy.count(), 1); - QCOMPARE(rowsAboutToBeRemoveSpy.count(), 1); + QCOMPARE(columnsRemoveSpy.size(), 1); + QCOMPARE(columnsAboutToBeRemoveSpy.size(), 1); + QCOMPARE(rowsRemoveSpy.size(), 1); + QCOMPARE(rowsAboutToBeRemoveSpy.size(), 1); for (const auto &spyArgs : {columnsRemoveSpy.takeFirst(), columnsAboutToBeRemoveSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxyParent); @@ -545,10 +589,10 @@ void tst_QTransposeProxyModel::insertColumnProxy() QVERIFY(result.isNull() || (result.metaType().id() == QMetaType::QString && result.toString().isNull())); result = model->index(1, 0, sourceParent).data(); QVERIFY(result.isNull() || (result.metaType().id() == QMetaType::QString && result.toString().isNull())); - QCOMPARE(columnsInsertSpy.count(), 1); - QCOMPARE(columnsAboutToBeInsertSpy.count(), 1); - QCOMPARE(rowsInsertSpy.count(), 1); - QCOMPARE(rowsAboutToBeInsertSpy.count(), 1); + QCOMPARE(columnsInsertSpy.size(), 1); + QCOMPARE(columnsAboutToBeInsertSpy.size(), 1); + QCOMPARE(rowsInsertSpy.size(), 1); + QCOMPARE(rowsAboutToBeInsertSpy.size(), 1); for (const auto &spyArgs : {columnsInsertSpy.takeFirst(), columnsAboutToBeInsertSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxyParent); @@ -598,10 +642,10 @@ void tst_QTransposeProxyModel::removeRowProxy() QCOMPARE(model->columnCount(sourceParent), oldColCount - 1); QCOMPARE(proxy.index(1, 0, proxyParent).data(), expectedNewVal); QCOMPARE(model->index(0, 1, sourceParent).data(), expectedNewVal); - QCOMPARE(columnsRemoveSpy.count(), 1); - QCOMPARE(columnsAboutToBeRemoveSpy.count(), 1); - QCOMPARE(rowsRemoveSpy.count(), 1); - QCOMPARE(rowsAboutToBeRemoveSpy.count(), 1); + QCOMPARE(columnsRemoveSpy.size(), 1); + QCOMPARE(columnsAboutToBeRemoveSpy.size(), 1); + QCOMPARE(rowsRemoveSpy.size(), 1); + QCOMPARE(rowsAboutToBeRemoveSpy.size(), 1); for (const auto &spyArgs : {columnsRemoveSpy.takeFirst(), columnsAboutToBeRemoveSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), sourceParent); @@ -650,10 +694,10 @@ void tst_QTransposeProxyModel::insertRowProxy() QCOMPARE(model->columnCount(sourceParent), oldColCount + 1); QVERIFY(proxy.index(1, 0, proxyParent).data().isNull()); QVERIFY(model->index(0, 1, sourceParent).data().isNull()); - QCOMPARE(columnsInsertSpy.count(), 1); - QCOMPARE(columnsAboutToBeInsertSpy.count(), 1); - QCOMPARE(rowsInsertSpy.count(), 1); - QCOMPARE(rowsAboutToBeInsertSpy.count(), 1); + QCOMPARE(columnsInsertSpy.size(), 1); + QCOMPARE(columnsAboutToBeInsertSpy.size(), 1); + QCOMPARE(rowsInsertSpy.size(), 1); + QCOMPARE(rowsAboutToBeInsertSpy.size(), 1); for (const auto &spyArgs : {columnsInsertSpy.takeFirst(), columnsAboutToBeInsertSpy.takeFirst()}) { QCOMPARE(spyArgs.at(0).value<QModelIndex>(), sourceParent); @@ -825,8 +869,8 @@ void tst_QTransposeProxyModel::moveRowsBase() QVERIFY(model.moveRows(QModelIndex(), 0, 1, QModelIndex(), 2)); for (int i = 0; i < expectedNewVal.size(); ++i) QCOMPARE(proxy.index(0, i).data(), expectedNewVal.at(i)); - QCOMPARE(columnsMoveSpy.count(), 1); - QCOMPARE(columnsAboutToBeMoveSpy.count(), 1); + QCOMPARE(columnsMoveSpy.size(), 1); + QCOMPARE(columnsAboutToBeMoveSpy.size(), 1); for (const auto &spyArgs : {columnsMoveSpy.takeFirst(), columnsAboutToBeMoveSpy.takeFirst()}) { QVERIFY(!spyArgs.at(0).value<QModelIndex>().isValid()); @@ -857,10 +901,10 @@ void tst_QTransposeProxyModel::moveColumnsProxy() QCOMPARE(proxy.index(0, i).data(), expectedNewVal.at(i)); for (int i = 0; i < expectedNewVal.size(); ++i) QCOMPARE(model.index(i, 0).data(), expectedNewVal.at(i)); - QCOMPARE(columnsMoveSpy.count(), 1); - QCOMPARE(columnsAboutToBeMoveSpy.count(), 1); - QCOMPARE(rowsMoveSpy.count(), 1); - QCOMPARE(rowsAboutToBeMoveSpy.count(), 1); + QCOMPARE(columnsMoveSpy.size(), 1); + QCOMPARE(columnsAboutToBeMoveSpy.size(), 1); + QCOMPARE(rowsMoveSpy.size(), 1); + QCOMPARE(rowsAboutToBeMoveSpy.size(), 1); for (const auto &spyArgs : {columnsMoveSpy.takeFirst(), columnsAboutToBeMoveSpy.takeFirst(), rowsMoveSpy.takeFirst(),rowsAboutToBeMoveSpy.takeFirst()}) { |