Add a property to QSFPM to show children of accepted items

[ChangeLog][QtCore][QSortFilterProxyModel] Add a 'autoAcceptChildRows'
property to always show children rows of accepted rows.

Change-Id: I2402469ece438179d0f19888b9775cc27cf5c749
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Giulio Camuffo 2020-05-19 15:02:22 +02:00
parent 3197932e6f
commit 7db527dbdd
3 changed files with 114 additions and 10 deletions

View File

@ -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;
@ -323,25 +325,51 @@ 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);
}
bool QSortFilterProxyModelPrivate::filterRecursiveAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
Q_Q(const QSortFilterProxyModel);
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::recursiveParentAcceptsRow(const QModelIndex &source_parent) const
{
Q_Q(const QSortFilterProxyModel);
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

View File

@ -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)

View File

@ -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);