Hi
I’m using a QML ListView which has a C++ class that extends QSortFilterProxyModel as a model. The filter can show all elements from the original model or filter some of them, depending on the value of an attribute. I do this by defining my custom filterAcceptsRow() method.
When the filter’s attribute changes I have to reapply the filter and update the view manually. After some research I found out I can do this by emitting invalidateFilter() or invalidate() signals. Is this right?
Now, Let’s say as an example that the original model is just the first 10K numbers starting with 1. And that the filter, filters multiples of 100, so it shows 100, 200, 300, etc.
Now, suppose that the filter is enabled and the current element at the top of the view is 4700. So I see: 4700, 4800, 4900, 5000, 5100, etc. Now, I change the filter’s attribute so I have to reapply the filter and update the view manually:
If I emit invalidate() signal, the view always moves to the first element. So it shows 1, 2, 3…
If I emit invalidateFilter() signal, the view doesn’t move so I see 4700, 4701, 4702, etc. This is the behavior I want…
BUT sometimes the view is updated wrong, I see: unsorted elements, missing elements and/or blank elements!!!
If I scroll the view and go back to the original position (which forces the view to update again) all elements are shown fine. So, I guess invalidateFilter() works fine but updates the view wrong.
So my question is, How can I update the view correctly when the filter changes? Is this a bug?
I have another question related with the previous one:
If I define my ListView like this:
ListView {
anchors.fill: parent
model: myModel //a qsortproxymodel from c++
delegate: MyDelegate { myObject: object; } //"object" is the name of the role I set at roleNames() to retrieve the object. I don't know how to retrieve the object from qml for Qt::DisplayRole role. Any clue?
clip: true // This is not recommended from a performance point of view, but I don't understand this from the docs, so I enabled it: 'Note: Views do not enable clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set clip: true in order to have the out of view items clipped nicely.' What does this means: "If the view is not clipped by another item..."?
}
If the top element is, let’s say, 400 and I reapply the filter by emitting invalidateFilter() signal, the top element remains 400 but the next elements change. That’s fine.
But if the top element is 100 (the first element when the filter is on) and I reapply the filter by emitting invalidateFilter() signal, the top element changes to 1 (the first element when the filter is off) instead of remain 100. Isn’t it an strange and inconsistent behavior? Is it a bug?
I can ‘fix’ this by setting
highlightRangeMode: ListView.StrictlyEnforceRange
but it has other effects that I don’t want such as the behavior when I scroll to the last element.
Thank you
↧