From 149be782bb82ba2bd32fab5c531be09c354be9b5 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 3 Mar 2025 19:14:59 +0100 Subject: [PATCH] QSortFilterProxyModel: don't call index(row, 0) if there are no columns This is invalid, e.g. it asserts in QConcatenateTablesProxyModel::index() Fixes: QTBUG-134210 Change-Id: I21acad9497d423b0366991296e8dd498d51395ea Reviewed-by: Volker Hilsheimer (cherry picked from commit 93694e99c214a5166fc842f92659e42260230dce) Reviewed-by: Qt Cherry-pick Bot --- .../itemmodels/qsortfilterproxymodel.cpp | 4 +++ .../tst_qconcatenatetablesproxymodel.cpp | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 774dcfd9794..b638f197bc8 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -434,6 +434,10 @@ bool QSortFilterProxyModelPrivate::recursiveChildAcceptsRow(int source_row, cons { Q_Q(const QSortFilterProxyModel); + const int colCount = model->columnCount(source_parent); + if (colCount == 0) // don't call index(row, 0) if there's no such column + return false; + const QModelIndex index = model->index(source_row, 0, source_parent); const int count = model->rowCount(index); diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp index edb1b934f9f..f349cd0e5bb 100644 --- a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp @@ -83,6 +83,7 @@ private Q_SLOTS: void shouldPropagateDropBetweenItemsAtModelBoundary(); void shouldPropagateDropAfterLastRow_data(); void shouldPropagateDropAfterLastRow(); + void addModelWithFilterOnTop(); void qtbug91788(); void qtbug91878(); void createPersistentOnLayoutAboutToBeChanged(); @@ -864,6 +865,39 @@ void tst_QConcatenateTablesProxyModel::shouldPropagateDropAfterLastRow() } +class RefuseRowsProxy : public QSortFilterProxyModel +{ +public: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override + { + Q_UNUSED(source_row) + Q_UNUSED(source_parent) + return false; + } +}; + +void tst_QConcatenateTablesProxyModel::addModelWithFilterOnTop() // QTBUG-134210 +{ + // Given a QSFPM -> QConcatenateTablesProxyModel and a QStandardItemModel + QStandardItemModel sim; + sim.appendRow(new QStandardItem("ITEM")); + + QConcatenateTablesProxyModel concat; + RefuseRowsProxy proxyFilter; + proxyFilter.setSourceModel(&concat); + proxyFilter.setRecursiveFilteringEnabled(true); + + // When adding the QStandardItemModel as source model + concat.addSourceModel(&sim); + + // Then the item should be filtered out + // (without hitting an assert in QConcat::index() nor an infinite recursion in QSFPM) + QCOMPARE(concat.rowCount(), 1); + QCOMPARE(concat.columnCount(), 1); + QCOMPARE(proxyFilter.rowCount(), 0); + QCOMPARE(proxyFilter.columnCount(), 1); +} + void tst_QConcatenateTablesProxyModel::qtbug91788() { QConcatenateTablesProxyModel proxyConcat;