summaryrefslogtreecommitdiffstats
path: root/src/testlib/qabstractitemmodeltester.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib/qabstractitemmodeltester.cpp')
-rw-r--r--src/testlib/qabstractitemmodeltester.cpp295
1 files changed, 242 insertions, 53 deletions
diff --git a/src/testlib/qabstractitemmodeltester.cpp b/src/testlib/qabstractitemmodeltester.cpp
index 42bac5afb2..eb52d28d59 100644
--- a/src/testlib/qabstractitemmodeltester.cpp
+++ b/src/testlib/qabstractitemmodeltester.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtTest 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 The Qt Company Ltd.
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractitemmodeltester.h"
#include <private/qobject_p.h>
+#include <private/qabstractitemmodel_p.h>
#include <QtCore/QPointer>
#include <QtCore/QAbstractItemModel>
#include <QtCore/QStack>
@@ -77,10 +42,28 @@ public:
void data();
void runAllTests();
+
void layoutAboutToBeChanged();
void layoutChanged();
+
+ void modelAboutToBeReset();
+ void modelReset();
+
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void columnsInserted(const QModelIndex &parent, int first, int last);
+ void columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
+ const QModelIndex &destinationParent, int destinationColumn);
+ void columnsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination,
+ int column);
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void columnsRemoved(const QModelIndex &parent, int first, int last);
+
void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
void rowsInserted(const QModelIndex &parent, int start, int end);
+ void rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
+ const QModelIndex &destinationParent, int destinationRow);
+ void rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination,
+ int row);
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void rowsRemoved(const QModelIndex &parent, int start, int end);
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
@@ -108,8 +91,22 @@ private:
QStack<Changing> insert;
QStack<Changing> remove;
+ bool useFetchMore = true;
bool fetchingMore;
+ enum class ChangeInFlight {
+ None,
+ ColumnsInserted,
+ ColumnsMoved,
+ ColumnsRemoved,
+ LayoutChanged,
+ ModelReset,
+ RowsInserted,
+ RowsMoved,
+ RowsRemoved
+ };
+ ChangeInFlight changeInFlight = ChangeInFlight::None;
+
QList<QPersistentModelIndex> changing;
};
@@ -184,8 +181,7 @@ private:
This enumeration specifies how QAbstractItemModelTester should report
a failure when it tests a QAbstractItemModel subclass.
- \value QtTest The failures will be reported through
- QtTest's logging mechanism.
+ \value QtTest The failures will be reported as QtTest test failures.
\value Warning The failures will be reported as
warning messages in the \c{qt.modeltest} logging category.
@@ -253,14 +249,45 @@ QAbstractItemModelTester::QAbstractItemModelTester(QAbstractItemModel *model, Fa
connect(model, &QAbstractItemModel::layoutChanged,
this, [d]{ d->layoutChanged(); });
+ // column operations
+ connect(model, &QAbstractItemModel::columnsAboutToBeInserted,
+ this, [d](const QModelIndex &parent, int start, int end) { d->columnsAboutToBeInserted(parent, start, end); });
+ connect(model, &QAbstractItemModel::columnsAboutToBeMoved,
+ this, [d](const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) {
+ d->columnsAboutToBeMoved(sourceParent, sourceStart, sourceEnd, destinationParent, destinationColumn); });
+ connect(model, &QAbstractItemModel::columnsAboutToBeRemoved,
+ this, [d](const QModelIndex &parent, int start, int end) { d->columnsAboutToBeRemoved(parent, start, end); });
+ connect(model, &QAbstractItemModel::columnsInserted,
+ this, [d](const QModelIndex &parent, int start, int end) { d->columnsInserted(parent, start, end); });
+ connect(model, &QAbstractItemModel::columnsMoved,
+ this, [d](const QModelIndex &parent, int start, int end, const QModelIndex &destination, int col) {
+ d->columnsMoved(parent, start, end, destination, col); });
+ connect(model, &QAbstractItemModel::columnsRemoved,
+ this, [d](const QModelIndex &parent, int start, int end) { d->columnsRemoved(parent, start, end); });
+
+ // row operations
connect(model, &QAbstractItemModel::rowsAboutToBeInserted,
this, [d](const QModelIndex &parent, int start, int end) { d->rowsAboutToBeInserted(parent, start, end); });
+ connect(model, &QAbstractItemModel::rowsAboutToBeMoved,
+ this, [d](const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) {
+ d->rowsAboutToBeMoved(sourceParent, sourceStart, sourceEnd, destinationParent, destinationRow); });
connect(model, &QAbstractItemModel::rowsAboutToBeRemoved,
this, [d](const QModelIndex &parent, int start, int end) { d->rowsAboutToBeRemoved(parent, start, end); });
connect(model, &QAbstractItemModel::rowsInserted,
this, [d](const QModelIndex &parent, int start, int end) { d->rowsInserted(parent, start, end); });
+ connect(model, &QAbstractItemModel::rowsMoved,
+ this, [d](const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) {
+ d->rowsMoved(parent, start, end, destination, row); });
connect(model, &QAbstractItemModel::rowsRemoved,
this, [d](const QModelIndex &parent, int start, int end) { d->rowsRemoved(parent, start, end); });
+
+ // reset
+ connect(model, &QAbstractItemModel::modelAboutToBeReset,
+ this, [d]() { d->modelAboutToBeReset(); });
+ connect(model, &QAbstractItemModel::modelReset,
+ this, [d]() { d->modelReset(); });
+
+ // data
connect(model, &QAbstractItemModel::dataChanged,
this, [d](const QModelIndex &topLeft, const QModelIndex &bottomRight) { d->dataChanged(topLeft, bottomRight); });
connect(model, &QAbstractItemModel::headerDataChanged,
@@ -289,6 +316,20 @@ QAbstractItemModelTester::FailureReportingMode QAbstractItemModelTester::failure
return d->failureReportingMode;
}
+/*!
+ If \a value is true, enables dynamic population of the
+ tested model, which is the default.
+ If \a value is false, it disables it.
+
+ \since 6.4
+ \sa QAbstractItemModel::fetchMore()
+*/
+void QAbstractItemModelTester::setUseFetchMore(bool value)
+{
+ Q_D(QAbstractItemModelTester);
+ d->useFetchMore = value;
+}
+
bool QAbstractItemModelTester::verify(bool statement, const char *statementStr, const char *description, const char *file, int line)
{
Q_D(QAbstractItemModelTester);
@@ -323,9 +364,11 @@ void QAbstractItemModelTesterPrivate::nonDestructiveBasicTest()
MODELTESTER_VERIFY(!model->buddy(QModelIndex()).isValid());
model->canFetchMore(QModelIndex());
MODELTESTER_VERIFY(model->columnCount(QModelIndex()) >= 0);
- fetchingMore = true;
- model->fetchMore(QModelIndex());
- fetchingMore = false;
+ if (useFetchMore) {
+ fetchingMore = true;
+ model->fetchMore(QModelIndex());
+ fetchingMore = false;
+ }
Qt::ItemFlags flags = model->flags(QModelIndex());
MODELTESTER_VERIFY(flags == Qt::ItemIsDropEnabled || flags == 0);
model->hasChildren(QModelIndex());
@@ -439,7 +482,7 @@ void QAbstractItemModelTesterPrivate::parent()
// when asked for the parent of an invalid index.
MODELTESTER_VERIFY(!model->parent(QModelIndex()).isValid());
- if (model->rowCount() == 0)
+ if (model->rowCount() == 0 || model->columnCount() == 0)
return;
// Column 0 | Column 1 |
@@ -455,7 +498,7 @@ void QAbstractItemModelTesterPrivate::parent()
// Common error test #2, make sure that a second level index has a parent
// that is the first level index.
- if (model->rowCount(topIndex) > 0) {
+ if (model->rowCount(topIndex) > 0 && model->columnCount(topIndex) > 0) {
QModelIndex childIndex = model->index(0, 0, topIndex);
MODELTESTER_VERIFY(childIndex.isValid());
MODELTESTER_COMPARE(model->parent(childIndex), topIndex);
@@ -503,7 +546,7 @@ void QAbstractItemModelTesterPrivate::checkChildren(const QModelIndex &parent, i
p = p.parent();
// For models that are dynamically populated
- if (model->canFetchMore(parent)) {
+ if (model->canFetchMore(parent) && useFetchMore) {
fetchingMore = true;
model->fetchMore(parent);
fetchingMore = false;
@@ -571,7 +614,7 @@ void QAbstractItemModelTesterPrivate::checkChildren(const QModelIndex &parent, i
// recursively go down the children
if (model->hasChildren(index) && currentDepth < 10)
- checkChildren(index, ++currentDepth);
+ checkChildren(index, currentDepth + 1);
// make sure that after testing the children that the index doesn't change.
QModelIndex newerIndex = model->index(r, c, parent);
@@ -613,14 +656,14 @@ void QAbstractItemModelTesterPrivate::data()
// Check that the alignment is one we know about
QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole);
if (textAlignmentVariant.isValid()) {
- Qt::Alignment alignment = qvariant_cast<Qt::Alignment>(textAlignmentVariant);
+ Qt::Alignment alignment = QtPrivate::legacyFlagValueFromModelData<Qt::Alignment>(textAlignmentVariant);
MODELTESTER_COMPARE(alignment, (alignment & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)));
}
// Check that the "check state" is one we know about.
QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole);
if (checkStateVariant.isValid()) {
- int state = checkStateVariant.toInt();
+ Qt::CheckState state = QtPrivate::legacyEnumValueFromModelData<Qt::CheckState>(checkStateVariant);
MODELTESTER_VERIFY(state == Qt::Unchecked
|| state == Qt::PartiallyChecked
|| state == Qt::Checked);
@@ -632,6 +675,89 @@ void QAbstractItemModelTesterPrivate::data()
return;
}
+void QAbstractItemModelTesterPrivate::columnsAboutToBeInserted(const QModelIndex &parent, int start,
+ int end)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::ColumnsInserted;
+
+ qCDebug(lcModelTest) << "columnsAboutToBeInserted"
+ << "start=" << start << "end=" << end << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent)
+ << "last before insertion=" << model->index(start - 1, 0, parent)
+ << model->data(model->index(start - 1, 0, parent));
+}
+
+void QAbstractItemModelTesterPrivate::columnsInserted(const QModelIndex &parent, int first,
+ int last)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::ColumnsInserted);
+ changeInFlight = ChangeInFlight::None;
+
+ qCDebug(lcModelTest) << "columnsInserted"
+ << "start=" << first << "end=" << last << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent);
+}
+
+void QAbstractItemModelTesterPrivate::columnsAboutToBeMoved(const QModelIndex &sourceParent,
+ int sourceStart, int sourceEnd,
+ const QModelIndex &destinationParent,
+ int destinationColumn)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::ColumnsMoved;
+
+ qCDebug(lcModelTest) << "columnsAboutToBeMoved"
+ << "sourceStart=" << sourceStart << "sourceEnd=" << sourceEnd
+ << "sourceParent=" << sourceParent
+ << "sourceParent data=" << model->data(sourceParent).toString()
+ << "destinationParent=" << destinationParent
+ << "destinationColumn=" << destinationColumn;
+}
+
+void QAbstractItemModelTesterPrivate::columnsMoved(const QModelIndex &sourceParent, int sourceStart,
+ int sourceEnd,
+ const QModelIndex &destinationParent,
+ int destinationColumn)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::ColumnsMoved);
+ changeInFlight = ChangeInFlight::None;
+
+ qCDebug(lcModelTest) << "columnsMoved"
+ << "sourceStart=" << sourceStart << "sourceEnd=" << sourceEnd
+ << "sourceParent=" << sourceParent
+ << "sourceParent data=" << model->data(sourceParent).toString()
+ << "destinationParent=" << destinationParent
+ << "destinationColumn=" << destinationColumn;
+}
+
+void QAbstractItemModelTesterPrivate::columnsAboutToBeRemoved(const QModelIndex &parent, int first,
+ int last)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::ColumnsRemoved;
+
+ qCDebug(lcModelTest) << "columnsAboutToBeRemoved"
+ << "start=" << first << "end=" << last << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent)
+ << "last before removal=" << model->index(first - 1, 0, parent)
+ << model->data(model->index(first - 1, 0, parent));
+}
+
+void QAbstractItemModelTesterPrivate::columnsRemoved(const QModelIndex &parent, int first, int last)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::ColumnsRemoved);
+ changeInFlight = ChangeInFlight::None;
+
+ qCDebug(lcModelTest) << "columnsRemoved"
+ << "start=" << first << "end=" << last << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent);
+}
+
/*
Store what is about to be inserted to make sure it actually happens
@@ -639,6 +765,9 @@ void QAbstractItemModelTesterPrivate::data()
*/
void QAbstractItemModelTesterPrivate::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::RowsInserted;
+
qCDebug(lcModelTest) << "rowsAboutToBeInserted"
<< "start=" << start << "end=" << end << "parent=" << parent
<< "parent data=" << model->data(parent).toString()
@@ -660,6 +789,9 @@ void QAbstractItemModelTesterPrivate::rowsAboutToBeInserted(const QModelIndex &p
*/
void QAbstractItemModelTesterPrivate::rowsInserted(const QModelIndex &parent, int start, int end)
{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::RowsInserted);
+ changeInFlight = ChangeInFlight::None;
+
qCDebug(lcModelTest) << "rowsInserted"
<< "start=" << start << "end=" << end << "parent=" << parent
<< "parent data=" << model->data(parent).toString()
@@ -690,21 +822,70 @@ void QAbstractItemModelTesterPrivate::rowsInserted(const QModelIndex &parent, in
}
}
+void QAbstractItemModelTesterPrivate::rowsAboutToBeMoved(const QModelIndex &sourceParent,
+ int sourceStart, int sourceEnd,
+ const QModelIndex &destinationParent,
+ int destinationRow)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::RowsMoved;
+
+ qCDebug(lcModelTest) << "rowsAboutToBeMoved"
+ << "sourceStart=" << sourceStart << "sourceEnd=" << sourceEnd
+ << "sourceParent=" << sourceParent
+ << "sourceParent data=" << model->data(sourceParent).toString()
+ << "destinationParent=" << destinationParent
+ << "destinationRow=" << destinationRow;
+}
+
+void QAbstractItemModelTesterPrivate::rowsMoved(const QModelIndex &sourceParent, int sourceStart,
+ int sourceEnd, const QModelIndex &destinationParent,
+ int destinationRow)
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::RowsMoved);
+ changeInFlight = ChangeInFlight::None;
+
+ qCDebug(lcModelTest) << "rowsMoved"
+ << "sourceStart=" << sourceStart << "sourceEnd=" << sourceEnd
+ << "sourceParent=" << sourceParent
+ << "sourceParent data=" << model->data(sourceParent).toString()
+ << "destinationParent=" << destinationParent
+ << "destinationRow=" << destinationRow;
+}
+
void QAbstractItemModelTesterPrivate::layoutAboutToBeChanged()
{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::LayoutChanged;
+
for (int i = 0; i < qBound(0, model->rowCount(), 100); ++i)
changing.append(QPersistentModelIndex(model->index(i, 0)));
}
void QAbstractItemModelTesterPrivate::layoutChanged()
{
- for (int i = 0; i < changing.count(); ++i) {
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::LayoutChanged);
+ changeInFlight = ChangeInFlight::None;
+
+ for (int i = 0; i < changing.size(); ++i) {
QPersistentModelIndex p = changing[i];
MODELTESTER_COMPARE(model->index(p.row(), p.column(), p.parent()), QModelIndex(p));
}
changing.clear();
}
+void QAbstractItemModelTesterPrivate::modelAboutToBeReset()
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::ModelReset;
+}
+
+void QAbstractItemModelTesterPrivate::modelReset()
+{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::ModelReset);
+ changeInFlight = ChangeInFlight::None;
+}
+
/*
Store what is about to be inserted to make sure it actually happens
@@ -712,6 +893,9 @@ void QAbstractItemModelTesterPrivate::layoutChanged()
*/
void QAbstractItemModelTesterPrivate::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::None);
+ changeInFlight = ChangeInFlight::RowsRemoved;
+
qCDebug(lcModelTest) << "rowsAboutToBeRemoved"
<< "start=" << start << "end=" << end << "parent=" << parent
<< "parent data=" << model->data(parent).toString()
@@ -721,12 +905,12 @@ void QAbstractItemModelTesterPrivate::rowsAboutToBeRemoved(const QModelIndex &pa
Changing c;
c.parent = parent;
c.oldSize = model->rowCount(parent);
- if (start > 0) {
+ if (start > 0 && model->columnCount(parent) > 0) {
const QModelIndex startIndex = model->index(start - 1, 0, parent);
MODELTESTER_VERIFY(startIndex.isValid());
c.last = model->data(startIndex);
}
- if (end < c.oldSize - 1) {
+ if (end < c.oldSize - 1 && model->columnCount(parent) > 0) {
const QModelIndex endIndex = model->index(end + 1, 0, parent);
MODELTESTER_VERIFY(endIndex.isValid());
c.next = model->data(endIndex);
@@ -742,6 +926,9 @@ void QAbstractItemModelTesterPrivate::rowsAboutToBeRemoved(const QModelIndex &pa
*/
void QAbstractItemModelTesterPrivate::rowsRemoved(const QModelIndex &parent, int start, int end)
{
+ MODELTESTER_COMPARE(changeInFlight, ChangeInFlight::RowsRemoved);
+ changeInFlight = ChangeInFlight::None;
+
qCDebug(lcModelTest) << "rowsRemoved"
<< "start=" << start << "end=" << end << "parent=" << parent
<< "parent data=" << model->data(parent).toString()
@@ -850,3 +1037,5 @@ bool QAbstractItemModelTesterPrivate::compare(const T1 &t1, const T2 &t2,
QT_END_NAMESPACE
+
+#include "moc_qabstractitemmodeltester.cpp"