summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp83
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h5
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp32
3 files changed, 112 insertions, 8 deletions
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 79a9875073..2c494aeec8 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -177,6 +177,7 @@ public:
QModelIndex last_top_source;
bool filter_recursive;
+ bool accept_children;
bool complete_insert;
bool dynamic_sortfilter;
QRowsRemoval itemsBeingRemoved;
@@ -305,7 +306,8 @@ public:
bool needsReorder(const QVector<int> &source_rows, const QModelIndex &source_parent) const;
bool filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const;
- bool filterRecursiveAcceptsRow(int source_row, const QModelIndex &source_parent) const;
+ bool recursiveChildAcceptsRow(int source_row, const QModelIndex &source_parent) const;
+ bool recursiveParentAcceptsRow(const QModelIndex &source_parent) const;
};
typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
@@ -325,23 +327,49 @@ void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
bool QSortFilterProxyModelPrivate::filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const
{
Q_Q(const QSortFilterProxyModel);
- return filter_recursive
- ? filterRecursiveAcceptsRow(source_row, source_parent)
- : q->filterAcceptsRow(source_row, source_parent);
+
+ if (q->filterAcceptsRow(source_row, source_parent))
+ return true;
+
+ // Go up the tree and accept this row if a parent is accepted
+ if (accept_children && recursiveParentAcceptsRow(source_parent))
+ return true;
+
+ // Go down the tree and accept this row if a child is accepted
+ if (filter_recursive && recursiveChildAcceptsRow(source_row, source_parent))
+ return true;
+
+ return false;
}
-bool QSortFilterProxyModelPrivate::filterRecursiveAcceptsRow(int source_row, const QModelIndex &source_parent) const
+bool QSortFilterProxyModelPrivate::recursiveParentAcceptsRow(const QModelIndex &source_parent) const
{
Q_Q(const QSortFilterProxyModel);
- if (q->filterAcceptsRow(source_row, source_parent))
- return true;
+ if (source_parent.isValid()) {
+ const QModelIndex index = source_parent.parent();
+
+ if (q->filterAcceptsRow(source_parent.row(), index))
+ return true;
+
+ return recursiveParentAcceptsRow(index);
+ }
+
+ return false;
+}
+
+bool QSortFilterProxyModelPrivate::recursiveChildAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+ Q_Q(const QSortFilterProxyModel);
const QModelIndex index = model->index(source_row, 0, source_parent);
const int count = model->rowCount(index);
for (int i = 0; i < count; ++i) {
- if (filterRecursiveAcceptsRow(i, index))
+ if (q->filterAcceptsRow(i, index))
+ return true;
+
+ if (recursiveChildAcceptsRow(i, index))
return true;
}
@@ -1878,6 +1906,7 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent)
d->filter_column = 0;
d->filter_role = Qt::DisplayRole;
d->filter_recursive = false;
+ d->accept_children = false;
d->dynamic_sortfilter = true;
d->complete_insert = false;
connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping()));
@@ -2763,6 +2792,7 @@ void QSortFilterProxyModel::setFilterRole(int role)
The default value is false.
+ \sa autoAcceptChildRows
\sa filterAcceptsRow()
*/
@@ -2789,6 +2819,43 @@ void QSortFilterProxyModel::setRecursiveFilteringEnabled(bool recursive)
emit recursiveFilteringEnabledChanged(recursive);
}
+/*!
+ \since 6.0
+ \property QSortFilterProxyModel::autoAcceptChildRows
+ \brief if true the proxy model will not filter out children of accepted
+ rows, even if they themselves would be filtered out otherwise.
+
+ The default value is false.
+
+ \sa recursiveFilteringEnabled
+ \sa filterAcceptsRow()
+*/
+
+/*!
+ \since 6.0
+ \fn void QSortFilterProxyModel::showMatchesChildrenChanged(bool autoAcceptChildRows)
+ \brief This signals is emitted when the value of the \a autoAcceptChildRows property is changed.
+
+ \sa autoAcceptChildRows
+*/
+bool QSortFilterProxyModel::autoAcceptChildRows() const
+{
+ Q_D(const QSortFilterProxyModel);
+ return d->accept_children;
+}
+
+void QSortFilterProxyModel::setAutoAcceptChildRows(bool accept)
+{
+ Q_D(QSortFilterProxyModel);
+ if (d->accept_children == accept)
+ return;
+
+ d->filter_about_to_be_changed();
+ d->accept_children = accept;
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ emit autoAcceptChildRowsChanged(accept);
+}
+
#if QT_DEPRECATED_SINCE(5, 11)
/*!
\obsolete
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index b7d4e69cb9..647b1616ce 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -72,6 +72,7 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
Q_PROPERTY(int sortRole READ sortRole WRITE setSortRole NOTIFY sortRoleChanged)
Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole NOTIFY filterRoleChanged)
Q_PROPERTY(bool recursiveFilteringEnabled READ isRecursiveFilteringEnabled WRITE setRecursiveFilteringEnabled NOTIFY recursiveFilteringEnabledChanged)
+ Q_PROPERTY(bool autoAcceptChildRows READ autoAcceptChildRows WRITE setAutoAcceptChildRows NOTIFY autoAcceptChildRowsChanged)
public:
explicit QSortFilterProxyModel(QObject *parent = nullptr);
@@ -116,6 +117,9 @@ public:
bool isRecursiveFilteringEnabled() const;
void setRecursiveFilteringEnabled(bool recursive);
+ bool autoAcceptChildRows() const;
+ void setAutoAcceptChildRows(bool accept);
+
public Q_SLOTS:
#if QT_CONFIG(regularexpression)
void setFilterRegularExpression(const QString &pattern);
@@ -190,6 +194,7 @@ Q_SIGNALS:
void sortRoleChanged(int sortRole);
void filterRoleChanged(int filterRole);
void recursiveFilteringEnabledChanged(bool recursiveFilteringEnabled);
+ void autoAcceptChildRowsChanged(bool autoAcceptChildRows);
private:
Q_DECLARE_PRIVATE(QSortFilterProxyModel)
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 dbafedbb5d..35ae7f4a7f 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp
@@ -715,6 +715,38 @@ private Q_SLOTS:
}
+ void testChildrenFiltering_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("noChildrenProxyStr");
+ QTest::addColumn<QString>("childrenProxyStr");
+ QTest::addColumn<QString>("noParentProxyStr");
+
+ QTest::newRow("filter_parent") << "[1*[1.1 1.2[1.2.1]]]" << "[1*]" << "[1*[1.1 1.2[1.2.1]]]" << "[1*[1.1 1.2[1.2.1]]]";
+ QTest::newRow("filter_child") << "[1[1.1 1.2*[1.2.1]]]" << "[1[1.2*]]" << "[1[1.2*[1.2.1]]]" << "";
+
+ }
+
+ void testChildrenFiltering()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, noChildrenProxyStr);
+ QFETCH(QString, childrenProxyStr);
+ QFETCH(QString, noParentProxyStr);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), noChildrenProxyStr);
+
+ proxy.setAutoAcceptChildRows(true);
+ QCOMPARE(treeAsString(proxy), childrenProxyStr);
+
+ proxy.setRecursiveFilteringEnabled(false);
+ QCOMPARE(treeAsString(proxy), noParentProxyStr);
+ }
+
private:
QStandardItem *itemByText(const QStandardItemModel& model, const QString &text) const {
QModelIndexList list = model.match(model.index(0, 0), Qt::DisplayRole, text, 1, Qt::MatchRecursive);