QSortFilterProxyModel filtering complete signal
Asked Answered
M

3

7

I'm using a custom QSortFilterProxyModel to implement custom filtering for QTableView by overriding filterAcceptsRow(). How can my application be notified when I change the filtering criteria and after filterAcceptsRow() is applied on the whole table?

Basically, I want to get a list of the visible item after filtering is applied, currently I calculate this list by a custom function I've implemented in my model that iterates on the rows and get a list of visible rows. This is inefficient as two calls to this function will yield the same results if no filtering action occurred in between.

Merryman answered 23/4, 2015 at 13:14 Comment(5)
Qt MVC is not designed to work with range of visible items. Models shouldn't know anything about views. Because you may use one model for several views.Litigant
All I need is a notification when the filtering processing is complete.Merryman
There are no such notifications. Because sorting is doing "on fly". When you add a new item - sorting is applied automatically.Litigant
@SaZ. If that were really true, how would the view know when to update itself after the model changes?Hairdo
There are enough documented methods, how model will notify view about changes. Please, read qt documentation: doc.qt.io/qt-5/qabstractitemmodel.html (signals section)Litigant
H
11

All models should emit layoutAboutToBeChanged() and layoutChanged(), before and after they are sorted, filtered, or changed in any other way that could affect the view.

Hairdo answered 23/4, 2015 at 15:48 Comment(2)
I was wrong in previous comment. I think that you are right. Voted up. Last time, when i directly call layoutChanged described there: #16445058Litigant
QSortFilterProxyModel::invalidateFilter() does not send it. It sent earlier when it was invalidate() but not now.Dropsonde
H
10

from my observations (in Qt 4.8), the layout*() signals will fire when sorting the proxy model, but not if you implement filtering. also the docs explicitly refer to the order of items that are meant by these signals, and filtering naturally doesn't change the order but affects rows only.

in this case only the rows*(...) signals (inserted, removed, etc.) will fire, depending on what the filter just did. the downside is, if the filter is applied recursively (usually it is), these signals will fire in masses, so will not be useful to tie to a single resulting action.

to overcome this you could call invalidate() after setting filters (not invalidateFilter btw, since it also won't fire the layout signals).

since this re-applies filtering and sorting (the latter wouldn't be necessary when filtering, but can't be avoided), the layout*()signals will fire after both did end.

but then it would be better to handle the filter string/regExp/whatever on your own instead using the base methods (like setFilterFixedString(...)) to set them, to at least avoid filtering twice - not much overhead anyway if you already re-implemented the filterAcceptsRow(...).

an alternative way would be to emit an own signal when setting sorting or filter, and connecting to it by using Qt::QueuedConnection to make sure it is executed after filtering did end. that's what i finally did (to update a register of the table) and as far i can tell it works like expected.

Hayes answered 23/6, 2015 at 10:33 Comment(1)
This appears to be what is happening for as well. There is no layout*() signal emitted when changing the filter expression.Nyeman
C
1

You can get a "filtering complete signal" by connecting to QAbstractItemModel::rowsRemoved and QAbstractItemModel::rowsInserted emitted by the proxy model and connecting it to your own signal or slot.

connect( filterProxyModel_, &QAbstractItemModel::::rowsRemoved,
        this, &MyWidget::onFilteringDone ) ;
connect( filterProxyModel_, &QAbstractItemModel::::rowsInserted,
        this, &MyWidget::onFilteringDone ) ;

The other signals like layoutChanged or dataChanged are not emitted in case of filtering.

Chickenlivered answered 31/3, 2022 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.