QSortFilterProxyModel: add endFilterChange, deprecate invalidateFilter

This adds the typical end*() call to match the beginFilterChange() call
introduced by 00ce45efe16ff440651746a94c62e0d5c1f6e435. Pairing those
calls is necessary to make sure that the model can keep track of changes
between the old to the new filtering and emit the correct signals.

By deprecating the invalidateFilter() functions, we also make it clear
that existing code needs to be ported to the new API calls to avoid the
potentially incorrect or missing signal emissions.

Introduce a new FilterDirection enum with flag type FilterDirections
to indicate whether a row- or column-filter (or a filter impacting both
directions) changed. Replace the internal Directions enum with that,
it's no longer necessary.

Task-number: QTBUG-115717
Change-Id: I31c43ba846d665ef26c8a013d064421484f006cb
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Volker Hilsheimer 2024-12-22 13:33:18 +01:00
parent 40ad963e1a
commit 4605f0fd81
4 changed files with 173 additions and 110 deletions

View File

@ -17,7 +17,7 @@ void MySortFilterProxyModel::setFilterMinimumDate(QDate date)
{ {
beginFilterChange(); beginFilterChange();
minDate = date; minDate = date;
invalidateRowsFilter(); endFilterChange(QSortFilterProxyModel::Direction::Rows);
} }
//! [1] //! [1]
@ -26,7 +26,7 @@ void MySortFilterProxyModel::setFilterMaximumDate(QDate date)
{ {
beginFilterChange(); beginFilterChange();
maxDate = date; maxDate = date;
invalidateRowsFilter(); endFilterChange(QSortFilterProxyModel::Direction::Rows);
} }
//! [2] //! [2]

View File

@ -111,12 +111,6 @@ class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate
public: public:
Q_DECLARE_PUBLIC(QSortFilterProxyModel) Q_DECLARE_PUBLIC(QSortFilterProxyModel)
enum class Direction {
Rows = 1,
Columns = 2,
All = Rows | Columns
};
struct Mapping { struct Mapping {
QList<int> source_rows; QList<int> source_rows;
QList<int> source_columns; QList<int> source_columns;
@ -327,6 +321,8 @@ public:
void _q_clearMapping(); void _q_clearMapping();
using Direction = QSortFilterProxyModel::Direction;
using Directions = QSortFilterProxyModel::Directions;
void sort(); void sort();
bool update_source_sort_column(); bool update_source_sort_column();
int find_source_sort_column() const; int find_source_sort_column() const;
@ -334,29 +330,29 @@ public:
const QModelIndex &source_parent) const; const QModelIndex &source_parent) const;
QList<std::pair<int, QList<int>>> proxy_intervals_for_source_items_to_add( QList<std::pair<int, QList<int>>> proxy_intervals_for_source_items_to_add(
const QList<int> &proxy_to_source, const QList<int> &source_items, const QList<int> &proxy_to_source, const QList<int> &source_items,
const QModelIndex &source_parent, Qt::Orientation orient) const; const QModelIndex &source_parent, Direction direction) const;
QList<std::pair<int, int>> proxy_intervals_for_source_items( QList<std::pair<int, int>> proxy_intervals_for_source_items(
const QList<int> &source_to_proxy, const QList<int> &source_items) const; const QList<int> &source_to_proxy, const QList<int> &source_items) const;
void insert_source_items( void insert_source_items(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, QList<int> &source_to_proxy, QList<int> &proxy_to_source,
const QList<int> &source_items, const QModelIndex &source_parent, const QList<int> &source_items, const QModelIndex &source_parent,
Qt::Orientation orient, bool emit_signal = true); Direction direction, bool emit_signal = true);
void remove_source_items( void remove_source_items(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, QList<int> &source_to_proxy, QList<int> &proxy_to_source,
const QList<int> &source_items, const QModelIndex &source_parent, const QList<int> &source_items, const QModelIndex &source_parent,
Qt::Orientation orient, bool emit_signal = true); Direction direction, bool emit_signal = true);
void remove_proxy_interval( void remove_proxy_interval(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, QList<int> &source_to_proxy, QList<int> &proxy_to_source,
int proxy_start, int proxy_end, const QModelIndex &proxy_parent, int proxy_start, int proxy_end, const QModelIndex &proxy_parent,
Qt::Orientation orient, bool emit_signal = true); Direction direction, bool emit_signal = true);
static inline void build_source_to_proxy_mapping( static inline void build_source_to_proxy_mapping(
const QList<int> &proxy_to_source, QList<int> &source_to_proxy, int start = 0); const QList<int> &proxy_to_source, QList<int> &source_to_proxy, int start = 0);
void source_items_inserted(const QModelIndex &source_parent, void source_items_inserted(const QModelIndex &source_parent,
int start, int end, Qt::Orientation orient); int start, int end, Direction direction);
void source_items_about_to_be_removed(const QModelIndex &source_parent, void source_items_about_to_be_removed(const QModelIndex &source_parent,
int start, int end, Qt::Orientation orient); int start, int end, Direction direction);
void source_items_removed(const QModelIndex &source_parent, void source_items_removed(const QModelIndex &source_parent,
int start, int end, Qt::Orientation orient); int start, int end, Direction direction);
void proxy_item_range( void proxy_item_range(
const QList<int> &source_to_proxy, const QList<int> &source_items, const QList<int> &source_to_proxy, const QList<int> &source_items,
int &proxy_low, int &proxy_high) const; int &proxy_low, int &proxy_high) const;
@ -365,13 +361,13 @@ public:
void update_persistent_indexes(const QModelIndexPairList &source_indexes); void update_persistent_indexes(const QModelIndexPairList &source_indexes);
void filter_about_to_be_changed(const QModelIndex &source_parent = QModelIndex()); void filter_about_to_be_changed(const QModelIndex &source_parent = QModelIndex());
void filter_changed(Direction dir, const QModelIndex &source_parent = QModelIndex()); void filter_changed(Directions directions, const QModelIndex &source_parent = QModelIndex());
QSet<int> handle_filter_changed( QSet<int> handle_filter_changed(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, QList<int> &source_to_proxy, QList<int> &proxy_to_source,
const QModelIndex &source_parent, Qt::Orientation orient); const QModelIndex &source_parent, Direction direction);
void updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping, void updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping,
Qt::Orientation orient, int start, int end, int delta_item_count, bool remove); Direction direction, int start, int end, int delta_item_count, bool remove);
void _q_sourceModelDestroyed() override; void _q_sourceModelDestroyed() override;
@ -384,11 +380,6 @@ public:
typedef QHash<QtPrivate::QModelIndexWrapper, QSortFilterProxyModelPrivate::Mapping *> IndexMap; typedef QHash<QtPrivate::QModelIndexWrapper, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
static bool operator&(QSortFilterProxyModelPrivate::Direction a, QSortFilterProxyModelPrivate::Direction b)
{
return int(a) & int(b);
}
void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed() void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
{ {
QAbstractProxyModelPrivate::_q_sourceModelDestroyed(); QAbstractProxyModelPrivate::_q_sourceModelDestroyed();
@ -745,7 +736,7 @@ QList<std::pair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_sou
/*! /*!
\internal \internal
Given source-to-proxy mapping \a src_to_proxy and proxy-to-source mapping Given source-to-proxy mapping \a source_to_proxy and proxy-to-source mapping
\a proxy_to_source, removes \a source_items from this proxy model. \a proxy_to_source, removes \a source_items from this proxy model.
The corresponding proxy items are removed in intervals, so that the proper The corresponding proxy items are removed in intervals, so that the proper
rows/columnsRemoved(start, end) signals will be generated. rows/columnsRemoved(start, end) signals will be generated.
@ -753,7 +744,7 @@ QList<std::pair<int, int>> QSortFilterProxyModelPrivate::proxy_intervals_for_sou
void QSortFilterProxyModelPrivate::remove_source_items( void QSortFilterProxyModelPrivate::remove_source_items(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, QList<int> &source_to_proxy, QList<int> &proxy_to_source,
const QList<int> &source_items, const QModelIndex &source_parent, const QList<int> &source_items, const QModelIndex &source_parent,
Qt::Orientation orient, bool emit_signal) Direction direction, bool emit_signal)
{ {
Q_Q(QSortFilterProxyModel); Q_Q(QSortFilterProxyModel);
QModelIndex proxy_parent = q->mapFromSource(source_parent); QModelIndex proxy_parent = q->mapFromSource(source_parent);
@ -771,7 +762,7 @@ void QSortFilterProxyModelPrivate::remove_source_items(
const int proxy_start = interval.first; const int proxy_start = interval.first;
const int proxy_end = interval.second; const int proxy_end = interval.second;
remove_proxy_interval(source_to_proxy, proxy_to_source, proxy_start, proxy_end, remove_proxy_interval(source_to_proxy, proxy_to_source, proxy_start, proxy_end,
proxy_parent, orient, emit_signal); proxy_parent, direction, emit_signal);
} }
} }
@ -784,11 +775,11 @@ void QSortFilterProxyModelPrivate::remove_source_items(
*/ */
void QSortFilterProxyModelPrivate::remove_proxy_interval( void QSortFilterProxyModelPrivate::remove_proxy_interval(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, int proxy_start, int proxy_end, QList<int> &source_to_proxy, QList<int> &proxy_to_source, int proxy_start, int proxy_end,
const QModelIndex &proxy_parent, Qt::Orientation orient, bool emit_signal) const QModelIndex &proxy_parent, Direction direction, bool emit_signal)
{ {
Q_Q(QSortFilterProxyModel); Q_Q(QSortFilterProxyModel);
if (emit_signal) { if (emit_signal) {
if (orient == Qt::Vertical) if (direction == Direction::Rows)
q->beginRemoveRows(proxy_parent, proxy_start, proxy_end); q->beginRemoveRows(proxy_parent, proxy_start, proxy_end);
else else
q->beginRemoveColumns(proxy_parent, proxy_start, proxy_end); q->beginRemoveColumns(proxy_parent, proxy_start, proxy_end);
@ -802,7 +793,7 @@ void QSortFilterProxyModelPrivate::remove_proxy_interval(
build_source_to_proxy_mapping(proxy_to_source, source_to_proxy, proxy_start); build_source_to_proxy_mapping(proxy_to_source, source_to_proxy, proxy_start);
if (emit_signal) { if (emit_signal) {
if (orient == Qt::Vertical) if (direction == Direction::Rows)
q->endRemoveRows(); q->endRemoveRows();
else else
q->endRemoveColumns(); q->endRemoveColumns();
@ -823,7 +814,7 @@ void QSortFilterProxyModelPrivate::remove_proxy_interval(
*/ */
QList<std::pair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add( QList<std::pair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add(
const QList<int> &proxy_to_source, const QList<int> &source_items, const QList<int> &proxy_to_source, const QList<int> &source_items,
const QModelIndex &source_parent, Qt::Orientation orient) const const QModelIndex &source_parent, Direction direction) const
{ {
Q_Q(const QSortFilterProxyModel); Q_Q(const QSortFilterProxyModel);
QList<std::pair<int, QList<int>>> proxy_intervals; QList<std::pair<int, QList<int>>> proxy_intervals;
@ -833,7 +824,7 @@ QList<std::pair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_
int proxy_low = 0; int proxy_low = 0;
int proxy_item = 0; int proxy_item = 0;
int source_items_index = 0; int source_items_index = 0;
bool compare = (orient == Qt::Vertical && source_sort_column >= 0 && dynamic_sortfilter); bool compare = (direction == Direction::Rows && source_sort_column >= 0 && dynamic_sortfilter);
while (source_items_index < source_items.size()) { while (source_items_index < source_items.size()) {
QList<int> source_items_in_interval; QList<int> source_items_in_interval;
int first_new_source_item = source_items.at(source_items_index); int first_new_source_item = source_items.at(source_items_index);
@ -897,7 +888,7 @@ QList<std::pair<int, QList<int>>> QSortFilterProxyModelPrivate::proxy_intervals_
void QSortFilterProxyModelPrivate::insert_source_items( void QSortFilterProxyModelPrivate::insert_source_items(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, QList<int> &source_to_proxy, QList<int> &proxy_to_source,
const QList<int> &source_items, const QModelIndex &source_parent, const QList<int> &source_items, const QModelIndex &source_parent,
Qt::Orientation orient, bool emit_signal) Direction direction, bool emit_signal)
{ {
Q_Q(QSortFilterProxyModel); Q_Q(QSortFilterProxyModel);
QModelIndex proxy_parent = q->mapFromSource(source_parent); QModelIndex proxy_parent = q->mapFromSource(source_parent);
@ -905,7 +896,7 @@ void QSortFilterProxyModelPrivate::insert_source_items(
return; // nothing to do (source_parent is not mapped) return; // nothing to do (source_parent is not mapped)
const auto proxy_intervals = proxy_intervals_for_source_items_to_add( const auto proxy_intervals = proxy_intervals_for_source_items_to_add(
proxy_to_source, source_items, source_parent, orient); proxy_to_source, source_items, source_parent, direction);
const auto end = proxy_intervals.rend(); const auto end = proxy_intervals.rend();
for (auto it = proxy_intervals.rbegin(); it != end; ++it) { for (auto it = proxy_intervals.rbegin(); it != end; ++it) {
@ -915,7 +906,7 @@ void QSortFilterProxyModelPrivate::insert_source_items(
const int proxy_end = proxy_start + source_items.size() - 1; const int proxy_end = proxy_start + source_items.size() - 1;
if (emit_signal) { if (emit_signal) {
if (orient == Qt::Vertical) if (direction == Direction::Rows)
q->beginInsertRows(proxy_parent, proxy_start, proxy_end); q->beginInsertRows(proxy_parent, proxy_start, proxy_end);
else else
q->beginInsertColumns(proxy_parent, proxy_start, proxy_end); q->beginInsertColumns(proxy_parent, proxy_start, proxy_end);
@ -928,7 +919,7 @@ void QSortFilterProxyModelPrivate::insert_source_items(
build_source_to_proxy_mapping(proxy_to_source, source_to_proxy, proxy_start); build_source_to_proxy_mapping(proxy_to_source, source_to_proxy, proxy_start);
if (emit_signal) { if (emit_signal) {
if (orient == Qt::Vertical) if (direction == Direction::Rows)
q->endInsertRows(); q->endInsertRows();
else else
q->endInsertColumns(); q->endInsertColumns();
@ -949,7 +940,7 @@ void QSortFilterProxyModelPrivate::insert_source_items(
signals will be generated. signals will be generated.
*/ */
void QSortFilterProxyModelPrivate::source_items_inserted( void QSortFilterProxyModelPrivate::source_items_inserted(
const QModelIndex &source_parent, int start, int end, Qt::Orientation orient) const QModelIndex &source_parent, int start, int end, Direction direction)
{ {
Q_Q(QSortFilterProxyModel); Q_Q(QSortFilterProxyModel);
if ((start < 0) || (end < 0)) if ((start < 0) || (end < 0))
@ -973,13 +964,13 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
} }
Mapping *m = it.value(); Mapping *m = it.value();
QList<int> &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; QList<int> &source_to_proxy = (direction == Direction::Rows) ? m->proxy_rows : m->proxy_columns;
QList<int> &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns; QList<int> &proxy_to_source = (direction == Direction::Rows) ? m->source_rows : m->source_columns;
int delta_item_count = end - start + 1; int delta_item_count = end - start + 1;
int old_item_count = source_to_proxy.size(); int old_item_count = source_to_proxy.size();
updateChildrenMapping(source_parent, m, orient, start, end, delta_item_count, false); updateChildrenMapping(source_parent, m, direction, start, end, delta_item_count, false);
// Expand source-to-proxy mapping to account for new items // Expand source-to-proxy mapping to account for new items
if (start < 0 || start > source_to_proxy.size()) { if (start < 0 || start > source_to_proxy.size()) {
@ -1003,7 +994,7 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
// Figure out which items to add to mapping based on filter // Figure out which items to add to mapping based on filter
QList<int> source_items; QList<int> source_items;
for (int i = start; i <= end; ++i) { for (int i = start; i <= end; ++i) {
if ((orient == Qt::Vertical) if ((direction == Direction::Rows)
? filterAcceptsRowInternal(i, source_parent) ? filterAcceptsRowInternal(i, source_parent)
: q->filterAcceptsColumn(i, source_parent)) { : q->filterAcceptsColumn(i, source_parent)) {
source_items.append(i); source_items.append(i);
@ -1015,21 +1006,21 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
// If it was new rows make sure to create mappings for columns so that a // If it was new rows make sure to create mappings for columns so that a
// valid mapping can be retrieved later and vice-versa. // valid mapping can be retrieved later and vice-versa.
QList<int> &orthogonal_proxy_to_source = (orient == Qt::Horizontal) ? m->source_rows : m->source_columns; QList<int> &orthogonal_proxy_to_source = (direction == Direction::Columns) ? m->source_rows : m->source_columns;
QList<int> &orthogonal_source_to_proxy = (orient == Qt::Horizontal) ? m->proxy_rows : m->proxy_columns; QList<int> &orthogonal_source_to_proxy = (direction == Direction::Columns) ? m->proxy_rows : m->proxy_columns;
if (orthogonal_source_to_proxy.isEmpty()) { if (orthogonal_source_to_proxy.isEmpty()) {
const int ortho_end = (orient == Qt::Horizontal) ? model->rowCount(source_parent) : model->columnCount(source_parent); const int ortho_end = (direction == Direction::Columns) ? model->rowCount(source_parent) : model->columnCount(source_parent);
orthogonal_source_to_proxy.resize(ortho_end); orthogonal_source_to_proxy.resize(ortho_end);
for (int ortho_item = 0; ortho_item < ortho_end; ++ortho_item) { for (int ortho_item = 0; ortho_item < ortho_end; ++ortho_item) {
if ((orient == Qt::Horizontal) ? filterAcceptsRowInternal(ortho_item, source_parent) if ((direction == Direction::Columns) ? filterAcceptsRowInternal(ortho_item, source_parent)
: q->filterAcceptsColumn(ortho_item, source_parent)) { : q->filterAcceptsColumn(ortho_item, source_parent)) {
orthogonal_proxy_to_source.append(ortho_item); orthogonal_proxy_to_source.append(ortho_item);
} }
} }
if (orient == Qt::Horizontal) { if (direction == Direction::Columns) {
// We're reacting to columnsInserted, but we've just inserted new rows. Sort them. // We're reacting to columnsInserted, but we've just inserted new rows. Sort them.
sort_source_rows(orthogonal_proxy_to_source, source_parent); sort_source_rows(orthogonal_proxy_to_source, source_parent);
} }
@ -1038,9 +1029,9 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
} }
// Sort and insert the items // Sort and insert the items
if (orient == Qt::Vertical) // Only sort rows if (direction == Direction::Rows) // Only sort rows
sort_source_rows(source_items, source_parent); sort_source_rows(source_items, source_parent);
insert_source_items(source_to_proxy, proxy_to_source, source_items, source_parent, orient); insert_source_items(source_to_proxy, proxy_to_source, source_items, source_parent, direction);
} }
/*! /*!
@ -1050,7 +1041,7 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
(columnsAboutToBeRemoved(), rowsAboutToBeRemoved()). (columnsAboutToBeRemoved(), rowsAboutToBeRemoved()).
*/ */
void QSortFilterProxyModelPrivate::source_items_about_to_be_removed( void QSortFilterProxyModelPrivate::source_items_about_to_be_removed(
const QModelIndex &source_parent, int start, int end, Qt::Orientation orient) const QModelIndex &source_parent, int start, int end, Direction direction)
{ {
if ((start < 0) || (end < 0)) if ((start < 0) || (end < 0))
return; return;
@ -1061,8 +1052,8 @@ void QSortFilterProxyModelPrivate::source_items_about_to_be_removed(
} }
Mapping *m = it.value(); Mapping *m = it.value();
QList<int> &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; QList<int> &source_to_proxy = (direction == Direction::Rows) ? m->proxy_rows : m->proxy_columns;
QList<int> &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns; QList<int> &proxy_to_source = (direction == Direction::Rows) ? m->source_rows : m->source_columns;
// figure out which items to remove // figure out which items to remove
QList<int> source_items_to_remove; QList<int> source_items_to_remove;
@ -1074,7 +1065,7 @@ void QSortFilterProxyModelPrivate::source_items_about_to_be_removed(
} }
remove_source_items(source_to_proxy, proxy_to_source, source_items_to_remove, remove_source_items(source_to_proxy, proxy_to_source, source_items_to_remove,
source_parent, orient); source_parent, direction);
} }
/*! /*!
@ -1083,7 +1074,7 @@ void QSortFilterProxyModelPrivate::source_items_about_to_be_removed(
Handles source model items removal (columnsRemoved(), rowsRemoved()). Handles source model items removal (columnsRemoved(), rowsRemoved()).
*/ */
void QSortFilterProxyModelPrivate::source_items_removed( void QSortFilterProxyModelPrivate::source_items_removed(
const QModelIndex &source_parent, int start, int end, Qt::Orientation orient) const QModelIndex &source_parent, int start, int end, Direction direction)
{ {
if ((start < 0) || (end < 0)) if ((start < 0) || (end < 0))
return; return;
@ -1094,8 +1085,8 @@ void QSortFilterProxyModelPrivate::source_items_removed(
} }
Mapping *m = it.value(); Mapping *m = it.value();
QList<int> &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; QList<int> &source_to_proxy = (direction == Direction::Rows) ? m->proxy_rows : m->proxy_columns;
QList<int> &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns; QList<int> &proxy_to_source = (direction == Direction::Rows) ? m->source_rows : m->source_columns;
if (end >= source_to_proxy.size()) if (end >= source_to_proxy.size())
end = source_to_proxy.size() - 1; end = source_to_proxy.size() - 1;
@ -1125,7 +1116,7 @@ void QSortFilterProxyModelPrivate::source_items_removed(
} }
build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); build_source_to_proxy_mapping(proxy_to_source, source_to_proxy);
updateChildrenMapping(source_parent, m, orient, start, end, delta_item_count, true); updateChildrenMapping(source_parent, m, direction, start, end, delta_item_count, true);
} }
@ -1135,14 +1126,14 @@ void QSortFilterProxyModelPrivate::source_items_removed(
updates the mapping of the children when inserting or removing items updates the mapping of the children when inserting or removing items
*/ */
void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping, void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping,
Qt::Orientation orient, int start, int end, int delta_item_count, bool remove) Direction direction, int start, int end, int delta_item_count, bool remove)
{ {
// see if any mapped children should be (re)moved // see if any mapped children should be (re)moved
QList<std::pair<QModelIndex, Mapping *>> moved_source_index_mappings; QList<std::pair<QModelIndex, Mapping *>> moved_source_index_mappings;
auto it2 = parent_mapping->mapped_children.begin(); auto it2 = parent_mapping->mapped_children.begin();
for ( ; it2 != parent_mapping->mapped_children.end();) { for ( ; it2 != parent_mapping->mapped_children.end();) {
const QModelIndex source_child_index = *it2; const QModelIndex source_child_index = *it2;
const int pos = (orient == Qt::Vertical) const int pos = (direction == Direction::Rows)
? source_child_index.row() ? source_child_index.row()
: source_child_index.column(); : source_child_index.column();
if (pos < start) { if (pos < start) {
@ -1156,7 +1147,7 @@ void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &sour
// below the removed items -- recompute the index // below the removed items -- recompute the index
QModelIndex new_index; QModelIndex new_index;
const int newpos = remove ? pos - delta_item_count : pos + delta_item_count; const int newpos = remove ? pos - delta_item_count : pos + delta_item_count;
if (orient == Qt::Vertical) { if (direction == Direction::Rows) {
new_index = model->index(newpos, new_index = model->index(newpos,
source_child_index.column(), source_child_index.column(),
source_parent); source_parent);
@ -1280,14 +1271,21 @@ void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex
Updates the proxy model (adds/removes rows) based on the Updates the proxy model (adds/removes rows) based on the
new filter. new filter.
*/ */
void QSortFilterProxyModelPrivate::filter_changed(Direction dir, const QModelIndex &source_parent) void QSortFilterProxyModelPrivate::filter_changed(Directions directions,
const QModelIndex &source_parent)
{ {
IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
if (it == source_index_mapping.constEnd()) if (it == source_index_mapping.constEnd())
return; return;
Mapping *m = it.value(); Mapping *m = it.value();
const QSet<int> rows_removed = (dir & Direction::Rows) ? handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical) : QSet<int>(); const QSet<int> rows_removed = (directions & Direction::Rows)
const QSet<int> columns_removed = (dir & Direction::Columns) ? handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal) : QSet<int>(); ? handle_filter_changed(m->proxy_rows, m->source_rows, source_parent,
Direction::Rows)
: QSet<int>();
const QSet<int> columns_removed = (directions & Direction::Columns)
? handle_filter_changed(m->proxy_columns, m->source_columns, source_parent,
Direction::Columns)
: QSet<int>();
// We need to iterate over a copy of m->mapped_children because otherwise it may be changed by other code, invalidating // We need to iterate over a copy of m->mapped_children because otherwise it may be changed by other code, invalidating
// the iterator it2. // the iterator it2.
@ -1301,7 +1299,7 @@ void QSortFilterProxyModelPrivate::filter_changed(Direction dir, const QModelInd
indexesToRemove.push_back(i); indexesToRemove.push_back(i);
remove_from_mapping(source_child_index); remove_from_mapping(source_child_index);
} else { } else {
filter_changed(dir, source_child_index); filter_changed(directions, source_child_index);
} }
} }
QList<int>::const_iterator removeIt = indexesToRemove.constEnd(); QList<int>::const_iterator removeIt = indexesToRemove.constEnd();
@ -1324,14 +1322,14 @@ void QSortFilterProxyModelPrivate::filter_changed(Direction dir, const QModelInd
*/ */
QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed( QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
QList<int> &source_to_proxy, QList<int> &proxy_to_source, QList<int> &source_to_proxy, QList<int> &proxy_to_source,
const QModelIndex &source_parent, Qt::Orientation orient) const QModelIndex &source_parent, Direction direction)
{ {
Q_Q(QSortFilterProxyModel); Q_Q(QSortFilterProxyModel);
// Figure out which mapped items to remove // Figure out which mapped items to remove
QList<int> source_items_remove; QList<int> source_items_remove;
for (int i = 0; i < proxy_to_source.size(); ++i) { for (int i = 0; i < proxy_to_source.size(); ++i) {
const int source_item = proxy_to_source.at(i); const int source_item = proxy_to_source.at(i);
if ((orient == Qt::Vertical) if ((direction == Direction::Rows)
? !filterAcceptsRowInternal(source_item, source_parent) ? !filterAcceptsRowInternal(source_item, source_parent)
: !q->filterAcceptsColumn(source_item, source_parent)) { : !q->filterAcceptsColumn(source_item, source_parent)) {
// This source item does not satisfy the filter, so it must be removed // This source item does not satisfy the filter, so it must be removed
@ -1343,7 +1341,7 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
int source_count = source_to_proxy.size(); int source_count = source_to_proxy.size();
for (int source_item = 0; source_item < source_count; ++source_item) { for (int source_item = 0; source_item < source_count; ++source_item) {
if (source_to_proxy.at(source_item) == -1) { if (source_to_proxy.at(source_item) == -1) {
if ((orient == Qt::Vertical) if ((direction == Direction::Rows)
? filterAcceptsRowInternal(source_item, source_parent) ? filterAcceptsRowInternal(source_item, source_parent)
: q->filterAcceptsColumn(source_item, source_parent)) { : q->filterAcceptsColumn(source_item, source_parent)) {
// This source item satisfies the filter, so it must be added // This source item satisfies the filter, so it must be added
@ -1354,11 +1352,11 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
if (!source_items_remove.isEmpty() || !source_items_insert.isEmpty()) { if (!source_items_remove.isEmpty() || !source_items_insert.isEmpty()) {
// Do item removal and insertion // Do item removal and insertion
remove_source_items(source_to_proxy, proxy_to_source, remove_source_items(source_to_proxy, proxy_to_source,
source_items_remove, source_parent, orient); source_items_remove, source_parent, direction);
if (orient == Qt::Vertical) if (direction == Direction::Rows)
sort_source_rows(source_items_insert, source_parent); sort_source_rows(source_items_insert, source_parent);
insert_source_items(source_to_proxy, proxy_to_source, insert_source_items(source_to_proxy, proxy_to_source,
source_items_insert, source_parent, orient); source_items_insert, source_parent, direction);
} }
return qListToSet(source_items_remove); return qListToSet(source_items_remove);
} }
@ -1465,7 +1463,7 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
if (!source_rows_remove.isEmpty()) { if (!source_rows_remove.isEmpty()) {
remove_source_items(m->proxy_rows, m->source_rows, remove_source_items(m->proxy_rows, m->source_rows,
source_rows_remove, source_parent, Qt::Vertical); source_rows_remove, source_parent, Direction::Rows);
QSet<int> source_rows_remove_set = qListToSet(source_rows_remove); QSet<int> source_rows_remove_set = qListToSet(source_rows_remove);
QList<QModelIndex>::iterator childIt = m->mapped_children.end(); QList<QModelIndex>::iterator childIt = m->mapped_children.end();
while (childIt != m->mapped_children.begin()) { while (childIt != m->mapped_children.begin()) {
@ -1486,10 +1484,10 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint); emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
QModelIndexPairList source_indexes = store_persistent_indexes(); QModelIndexPairList source_indexes = store_persistent_indexes();
remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort, remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
source_parent, Qt::Vertical, false); source_parent, Direction::Rows, false);
sort_source_rows(source_rows_resort, source_parent); sort_source_rows(source_rows_resort, source_parent);
insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort, insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
source_parent, Qt::Vertical, false); source_parent, Direction::Rows, false);
update_persistent_indexes(source_indexes); update_persistent_indexes(source_indexes);
emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint); emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
} }
@ -1529,7 +1527,7 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
if (!source_rows_insert.isEmpty()) { if (!source_rows_insert.isEmpty()) {
sort_source_rows(source_rows_insert, source_parent); sort_source_rows(source_rows_insert, source_parent);
insert_source_items(m->proxy_rows, m->source_rows, insert_source_items(m->proxy_rows, m->source_rows,
source_rows_insert, source_parent, Qt::Vertical); source_rows_insert, source_parent, Direction::Rows);
} }
} }
} }
@ -1682,7 +1680,7 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsInserted(
if (!filter_recursive || complete_insert) { if (!filter_recursive || complete_insert) {
if (filter_recursive) if (filter_recursive)
complete_insert = false; complete_insert = false;
source_items_inserted(source_parent, start, end, Qt::Vertical); source_items_inserted(source_parent, start, end, Direction::Rows);
if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column. if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column.
sort(); // now it should succeed so we need to make sure to sort again sort(); // now it should succeed so we need to make sure to sort again
return; return;
@ -1711,14 +1709,14 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(
{ {
itemsBeingRemoved = QRowsRemoval(source_parent, start, end); itemsBeingRemoved = QRowsRemoval(source_parent, start, end);
source_items_about_to_be_removed(source_parent, start, end, source_items_about_to_be_removed(source_parent, start, end,
Qt::Vertical); Direction::Rows);
} }
void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved( void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved(
const QModelIndex &source_parent, int start, int end) const QModelIndex &source_parent, int start, int end)
{ {
itemsBeingRemoved = QRowsRemoval(); itemsBeingRemoved = QRowsRemoval();
source_items_removed(source_parent, start, end, Qt::Vertical); source_items_removed(source_parent, start, end, Direction::Rows);
if (filter_recursive) { if (filter_recursive) {
// Find out if removing this visible row means that some ascendant // Find out if removing this visible row means that some ascendant
@ -1783,7 +1781,7 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsInserted(
const QModelIndex &source_parent, int start, int end) const QModelIndex &source_parent, int start, int end)
{ {
Q_Q(const QSortFilterProxyModel); Q_Q(const QSortFilterProxyModel);
source_items_inserted(source_parent, start, end, Qt::Horizontal); source_items_inserted(source_parent, start, end, Direction::Columns);
if (source_parent.isValid()) if (source_parent.isValid())
return; //we sort according to the root column only return; //we sort according to the root column only
@ -1803,14 +1801,14 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved(
const QModelIndex &source_parent, int start, int end) const QModelIndex &source_parent, int start, int end)
{ {
source_items_about_to_be_removed(source_parent, start, end, source_items_about_to_be_removed(source_parent, start, end,
Qt::Horizontal); Direction::Columns);
} }
void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved( void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
const QModelIndex &source_parent, int start, int end) const QModelIndex &source_parent, int start, int end)
{ {
Q_Q(const QSortFilterProxyModel); Q_Q(const QSortFilterProxyModel);
source_items_removed(source_parent, start, end, Qt::Horizontal); source_items_removed(source_parent, start, end, Direction::Columns);
if (source_parent.isValid()) if (source_parent.isValid())
return; //we sort according to the root column only return; //we sort according to the root column only
@ -1981,11 +1979,11 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved(
example.) example.)
If you are working with large amounts of filtering and have to invoke If you are working with large amounts of filtering and have to invoke
invalidateFilter() repeatedly, using beginResetModel() / endResetModel() may beginFilterChange() / endFilterChange() repeatedly, using beginResetModel()
be more efficient, depending on the implementation of your model. However, / endResetModel() may be more efficient, depending on the implementation of
beginResetModel() / endResetModel() returns the your model. However, beginResetModel() / endResetModel() returns the proxy
proxy model to its original state, losing selection information, and will model to its original state, losing selection information, and will cause
cause the proxy model to be repopulated. the proxy model to be repopulated.
\section1 Subclassing \section1 Subclassing
@ -2593,7 +2591,7 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression
d->filter_regularexpression.setValueBypassingBindings(regularExpression); d->filter_regularexpression.setValueBypassingBindings(regularExpression);
if (cs != updatedCs) if (cs != updatedCs)
d->filter_casesensitive.setValueBypassingBindings(updatedCs); d->filter_casesensitive.setValueBypassingBindings(updatedCs);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
// Do not change the evaluation logic, but notify only if the regular // Do not change the evaluation logic, but notify only if the regular
// expression has actually changed. // expression has actually changed.
if (regExpChanged) if (regExpChanged)
@ -2628,7 +2626,7 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column)
d->filter_about_to_be_changed(); d->filter_about_to_be_changed();
const auto oldColumn = d->filter_column.valueBypassingBindings(); const auto oldColumn = d->filter_column.valueBypassingBindings();
d->filter_column.setValueBypassingBindings(column); d->filter_column.setValueBypassingBindings(column);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
if (oldColumn != column) if (oldColumn != column)
d->filter_column.notify(); d->filter_column.notify();
} }
@ -2685,7 +2683,7 @@ void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
QRegularExpression re = d->filter_regularexpression; QRegularExpression re = d->filter_regularexpression;
re.setPatternOptions(options); re.setPatternOptions(options);
d->filter_regularexpression.setValueBypassingBindings(re); d->filter_regularexpression.setValueBypassingBindings(re);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
d->filter_regularexpression.notify(); d->filter_regularexpression.notify();
d->filter_casesensitive.notify(); d->filter_casesensitive.notify();
} }
@ -2800,7 +2798,7 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern)
d->filter_regularexpression.removeBindingUnlessInWrapper(); d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed(); d->filter_about_to_be_changed();
d->set_filter_pattern(pattern); d->set_filter_pattern(pattern);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
d->filter_regularexpression.notify(); d->filter_regularexpression.notify();
} }
@ -2824,7 +2822,7 @@ void QSortFilterProxyModel::setFilterWildcard(const QString &pattern)
d->filter_about_to_be_changed(); d->filter_about_to_be_changed();
d->set_filter_pattern(QRegularExpression::wildcardToRegularExpression( d->set_filter_pattern(QRegularExpression::wildcardToRegularExpression(
pattern, QRegularExpression::UnanchoredWildcardConversion)); pattern, QRegularExpression::UnanchoredWildcardConversion));
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
d->filter_regularexpression.notify(); d->filter_regularexpression.notify();
} }
@ -2847,7 +2845,7 @@ void QSortFilterProxyModel::setFilterFixedString(const QString &pattern)
d->filter_regularexpression.removeBindingUnlessInWrapper(); d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed(); d->filter_about_to_be_changed();
d->set_filter_pattern(QRegularExpression::escape(pattern)); d->set_filter_pattern(QRegularExpression::escape(pattern));
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
d->filter_regularexpression.notify(); d->filter_regularexpression.notify();
} }
@ -2967,7 +2965,7 @@ void QSortFilterProxyModel::setFilterRole(int role)
return; return;
d->filter_about_to_be_changed(); d->filter_about_to_be_changed();
d->filter_role.setValueBypassingBindings(role); d->filter_role.setValueBypassingBindings(role);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
d->filter_role.notify(); // also emits a signal d->filter_role.notify(); // also emits a signal
} }
@ -3009,7 +3007,7 @@ void QSortFilterProxyModel::setRecursiveFilteringEnabled(bool recursive)
return; return;
d->filter_about_to_be_changed(); d->filter_about_to_be_changed();
d->filter_recursive.setValueBypassingBindings(recursive); d->filter_recursive.setValueBypassingBindings(recursive);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
d->filter_recursive.notify(); // also emits a signal d->filter_recursive.notify(); // also emits a signal
} }
@ -3054,7 +3052,7 @@ void QSortFilterProxyModel::setAutoAcceptChildRows(bool accept)
d->filter_about_to_be_changed(); d->filter_about_to_be_changed();
d->accept_children.setValueBypassingBindings(accept); d->accept_children.setValueBypassingBindings(accept);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
d->accept_children.notify(); // also emits a signal d->accept_children.notify(); // also emits a signal
} }
@ -3069,7 +3067,7 @@ QBindable<bool> QSortFilterProxyModel::bindableAutoAcceptChildRows()
Invalidates the current sorting and filtering. Invalidates the current sorting and filtering.
\sa invalidateFilter() \sa beginFilterChange(), endFilterChange()
*/ */
void QSortFilterProxyModel::invalidate() void QSortFilterProxyModel::invalidate()
{ {
@ -3089,7 +3087,11 @@ void QSortFilterProxyModel::invalidate()
\snippet ../widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 2 \snippet ../widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 2
\sa invalidateFilter(), invalidateColumnsFilter(), invalidateRowsFilter() Once the filter has been changed, call endFilterChange() with Direction::Rows
for row-filters, Direction::Columns for column-filters, or Direction::Columns|Direction::Rows
if both rows and columns are filtered.
\sa endFilterChange()
*/ */
void QSortFilterProxyModel::beginFilterChange() void QSortFilterProxyModel::beginFilterChange()
@ -3098,8 +3100,10 @@ void QSortFilterProxyModel::beginFilterChange()
d->create_mapping({}); d->create_mapping({});
} }
#if QT_DEPRECATED_SINCE(6, 13)
/*! /*!
\since 4.3 \since 4.3
\deprecated [6.13] use beginFilterChange() and endFilterChange() instead.
Invalidates the current filtering. Invalidates the current filtering.
@ -3116,11 +3120,12 @@ void QSortFilterProxyModel::beginFilterChange()
void QSortFilterProxyModel::invalidateFilter() void QSortFilterProxyModel::invalidateFilter()
{ {
Q_D(QSortFilterProxyModel); Q_D(QSortFilterProxyModel);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::All); d->filter_changed(Direction::Columns|Direction::Rows);
} }
/*! /*!
\since 6.0 \since 6.0
\deprecated [6.13] use beginFilterChange() and endFilterChange(Direction::Rows) instead.
Invalidates the current filtering for the columns. Invalidates the current filtering for the columns.
@ -3138,11 +3143,12 @@ void QSortFilterProxyModel::invalidateFilter()
void QSortFilterProxyModel::invalidateColumnsFilter() void QSortFilterProxyModel::invalidateColumnsFilter()
{ {
Q_D(QSortFilterProxyModel); Q_D(QSortFilterProxyModel);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Columns); d->filter_changed(Direction::Columns);
} }
/*! /*!
\since 6.0 \since 6.0
\deprecated [6.13] use beginFilterChange() and endFilterChange(Direction::Columns) instead.
Invalidates the current filtering for the rows. Invalidates the current filtering for the rows.
@ -3160,7 +3166,44 @@ void QSortFilterProxyModel::invalidateColumnsFilter()
void QSortFilterProxyModel::invalidateRowsFilter() void QSortFilterProxyModel::invalidateRowsFilter()
{ {
Q_D(QSortFilterProxyModel); Q_D(QSortFilterProxyModel);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); d->filter_changed(Direction::Rows);
}
#endif // QT_DEPRECATED_SINCE(6, 10)
/*!
\enum QSortFilterProxyModel::Direction
\since 6.10
This enum is used to specify the direction to which a custom filter applies
when the filter parameters are changed.
\value Rows The filter applies to \l{filterAcceptsRow()}{rows}
\value Columns The filter applies to \l{filterAcceptsColumn()}{columns}
\value Both The filter applies to both rows and columns
\sa beginFilterChange(), endFilterChange()
*/
/*!
\since 6.10
Invalidates the current filtering after the filter parameter has changed.
This function should be called if you implement custom filtering (e.g.
filterAcceptsRow()), and your filter parameters have changed. The \a directions
parameter specifies whether the custom filter impacts rows, columns, or both.
Call beginFilterChange() when the filter parameter is about to change, and
follow with a call to this function once the filter parameters have been
changed. Call with \a directions set to Direction::Rows for row-filters
(i.e. filterAcceptsRow() is implemented), Direction::Columns for
column-filters (i.e. filterAcceptsColumn() is implemented),
or \c{Direction::Both} if both filter functions are implemented.
*/
void QSortFilterProxyModel::endFilterChange(QSortFilterProxyModel::Directions directions)
{
Q_D(QSortFilterProxyModel);
d->filter_changed(directions);
} }
/*! /*!

View File

@ -101,6 +101,13 @@ public:
void setAutoAcceptChildRows(bool accept); void setAutoAcceptChildRows(bool accept);
QBindable<bool> bindableAutoAcceptChildRows(); QBindable<bool> bindableAutoAcceptChildRows();
enum class Direction {
Rows = 0x01,
Columns = 0x02,
Both = Rows | Columns,
};
Q_DECLARE_FLAGS(Directions, Direction)
public Q_SLOTS: public Q_SLOTS:
void setFilterRegularExpression(const QString &pattern); void setFilterRegularExpression(const QString &pattern);
void setFilterRegularExpression(const QRegularExpression &regularExpression); void setFilterRegularExpression(const QRegularExpression &regularExpression);
@ -114,9 +121,15 @@ protected:
virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
void beginFilterChange(); void beginFilterChange();
void endFilterChange(Directions directions = Direction::Both);
#if QT_DEPRECATED_SINCE(6, 13)
QT_DEPRECATED_VERSION_X_6_13("Use begin/endFilterChange() instead")
void invalidateFilter(); void invalidateFilter();
QT_DEPRECATED_VERSION_X_6_13("Use begin/endFilterChange(QSortFilterProxyModel::Direction::Rows) instead")
void invalidateRowsFilter(); void invalidateRowsFilter();
QT_DEPRECATED_VERSION_X_6_13("Use begin/endFilterChange(QSortFilterProxyModel::Direction::Columns) instead")
void invalidateColumnsFilter(); void invalidateColumnsFilter();
#endif
public: public:
using QObject::parent; using QObject::parent;
@ -175,6 +188,8 @@ private:
Q_DISABLE_COPY(QSortFilterProxyModel) Q_DISABLE_COPY(QSortFilterProxyModel)
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(QSortFilterProxyModel::Directions)
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QSORTFILTERPROXYMODEL_H #endif // QSORTFILTERPROXYMODEL_H

View File

@ -3635,7 +3635,7 @@ void tst_QSortFilterProxyModel::resetInvalidate()
endResetModel(); endResetModel();
break; break;
case 2: invalidate(); break; case 2: invalidate(); break;
case 3: invalidateFilter(); break; case 3: endFilterChange(); break;
} }
} }
}; };
@ -4090,7 +4090,7 @@ public slots:
void setMode(bool on) void setMode(bool on)
{ {
mode = on; mode = on;
invalidateFilter(); endFilterChange();
} }
protected: protected:
@ -4148,7 +4148,7 @@ public slots:
void setMode(bool on) void setMode(bool on)
{ {
mode = on; mode = on;
invalidateFilter(); endFilterChange();
} }
protected: protected:
@ -5163,7 +5163,8 @@ class SortFilterProxyModel final : public QSortFilterProxyModel
Q_OBJECT Q_OBJECT
public: public:
using QSortFilterProxyModel::QSortFilterProxyModel; using QSortFilterProxyModel::QSortFilterProxyModel;
using QSortFilterProxyModel::invalidateFilter; using QSortFilterProxyModel::beginFilterChange;
using QSortFilterProxyModel::endFilterChange;
void setSourceModel(QAbstractItemModel *m) override void setSourceModel(QAbstractItemModel *m) override
{ {
@ -5209,15 +5210,17 @@ void tst_QSortFilterProxyModel::checkFilteredIndexes()
s.setSourceModel(&m); s.setSourceModel(&m);
s.sort(0); s.sort(0);
s.invalidateFilter(); s.endFilterChange();
checkIndexes(s); checkIndexes(s);
s.beginFilterChange();
s.m_filteredRows = 5; // every 5th row is filtered s.m_filteredRows = 5; // every 5th row is filtered
s.invalidateFilter(); s.endFilterChange();
checkIndexes(s); checkIndexes(s);
s.beginFilterChange();
s.m_filteredRows = 3; // every 3rd row is filtered s.m_filteredRows = 3; // every 3rd row is filtered
s.invalidateFilter(); s.endFilterChange();
checkIndexes(s); checkIndexes(s);
} }
@ -5252,6 +5255,8 @@ void tst_QSortFilterProxyModel::invalidateColumnsOrRowsFilter()
using QSortFilterProxyModel::invalidateFilter; using QSortFilterProxyModel::invalidateFilter;
using QSortFilterProxyModel::invalidateRowsFilter; using QSortFilterProxyModel::invalidateRowsFilter;
using QSortFilterProxyModel::invalidateColumnsFilter; using QSortFilterProxyModel::invalidateColumnsFilter;
using QSortFilterProxyModel::beginFilterChange;
using QSortFilterProxyModel::endFilterChange;
}; };
QStandardItemModel model(10, 4); QStandardItemModel model(10, 4);
for (int i = 0; i < model.rowCount(); ++i) { for (int i = 0; i < model.rowCount(); ++i) {
@ -5271,19 +5276,19 @@ void tst_QSortFilterProxyModel::invalidateColumnsOrRowsFilter()
QCOMPARE(proxy.columnFiltered, 44); // 4 parents + 4 * 10 children QCOMPARE(proxy.columnFiltered, 44); // 4 parents + 4 * 10 children
proxy.rowFiltered = proxy.columnFiltered = 0; proxy.rowFiltered = proxy.columnFiltered = 0;
proxy.invalidateFilter(); proxy.endFilterChange();
QCOMPARE(proxy.rowFiltered, 20); QCOMPARE(proxy.rowFiltered, 20);
QCOMPARE(proxy.columnFiltered, 44); QCOMPARE(proxy.columnFiltered, 44);
proxy.rowFiltered = proxy.columnFiltered = 0; proxy.rowFiltered = proxy.columnFiltered = 0;
proxy.invalidateRowsFilter(); proxy.endFilterChange(QSortFilterProxyModel::Direction::Rows);
QCOMPARE(proxy.rowFiltered, 20); QCOMPARE(proxy.rowFiltered, 20);
QCOMPARE(proxy.columnFiltered, 0); QCOMPARE(proxy.columnFiltered, 0);
proxy.rowFiltered = proxy.columnFiltered = 0; proxy.rowFiltered = proxy.columnFiltered = 0;
proxy.invalidateColumnsFilter(); proxy.endFilterChange(QSortFilterProxyModel::Direction::Columns);
QCOMPARE(proxy.rowFiltered, 0); QCOMPARE(proxy.rowFiltered, 0);
QCOMPARE(proxy.columnFiltered, 44); QCOMPARE(proxy.columnFiltered, 44);
@ -5291,12 +5296,12 @@ void tst_QSortFilterProxyModel::invalidateColumnsOrRowsFilter()
QCOMPARE(proxy.rowCount(), 10); QCOMPARE(proxy.rowCount(), 10);
proxy.rejectA1 = true; proxy.rejectA1 = true;
proxy.rowFiltered = proxy.columnFiltered = 0; proxy.rowFiltered = proxy.columnFiltered = 0;
proxy.invalidateRowsFilter(); proxy.endFilterChange(QSortFilterProxyModel::Direction::Rows);
QCOMPARE(proxy.rowCount(), 9); QCOMPARE(proxy.rowCount(), 9);
QCOMPARE(proxy.rowFiltered, 19); // it will not check the child row of A1 QCOMPARE(proxy.rowFiltered, 19); // it will not check the child row of A1
proxy.rowFiltered = proxy.columnFiltered = 0; proxy.rowFiltered = proxy.columnFiltered = 0;
proxy.setRecursiveFilteringEnabled(true); // this triggers invalidateRowsFilter() proxy.setRecursiveFilteringEnabled(true); // this triggers endFilterChange(QSortFilterProxyModel::Direction::Rows)
QCOMPARE(proxy.rowCount(), 10); QCOMPARE(proxy.rowCount(), 10);
QCOMPARE(proxy.rowFiltered, 20); QCOMPARE(proxy.rowFiltered, 20);
} }
@ -5512,7 +5517,7 @@ void tst_QSortFilterProxyModel::filterChangeEmitsModelChangedSignals()
beginFilterChange(); beginFilterChange();
m_matchString = s; m_matchString = s;
invalidateFilter(); endFilterChange();
} }
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override