QSortFilterProxyModel: Reset model shows ghost items
-
Hello folks,
I'm experiencing "unexpected behavior" when using
QSortFilterProxyModel
in a Qt 5.15 application.The scenario is this:
- Custom model based on
QAbstractItemModel
QTreeView
as the viewQSortFilterProxy
for sorting
When I remove the
QSortFilterProxy
model from my code, everything works as expected. However, when aQSortFilterProxy
sits between the model and the view, I observe that a resetting the model leads to "ghost items" showing up in the view (more on that below).My procedure is the following:
- Populate the model (using
beginInsertRows()
andendInsertRows()
). beginResetModel()
- Delete all data from the model
endResetModel()
- Re-populate the model with the same data (using
beginInsertRows()
andendInsertRows()
).
After these events, my model does contain the expected data. However, for each item that is expected to be displayed, there is also an "empty item" (eg. one without any text, icon, ...).
The structure of the data (i.e. the hierarchy, parent/children, ...) is also correct. It's just that there are twice as many items and half of them don't have anything showing up.
The expected behavior would be to just see the items correctly populated (with text, icon, ...) just as after initially populating the model in step 1 - without having those "ghost items".I've checked the documentation of
QSortFilterProxyModel
and couldn't find anything specific I'd have to handle myself when resetting the underlying model.Does anybody have a wild guess on what's going on here?
- Custom model based on
-
@Joel-Bodenmann said in QSortFilterProxyModel: Reset model shows ghost items:
wild guess
The signals for clearing out the old model are not getting from source model to proxy or from proxy to view? So the view still sees some old/phantom ones? Check this is happening correctly?
Custom model based on QAbstractItemModel
There is a "model tester" somewhere you should run on your custom model to make sure it behaves correctly in all situations.
-
@JonB said in QSortFilterProxyModel: Reset model shows ghost items:
The signals for clearing out the old model are not getting from source model to proxy or from proxy to view? So the view still sees some old/phantom ones? Check this is happening correctly?
How would I go about checking that? I.e. which technique would I use for something like that?
All I do is:
QSortFilterProxyModel::setSourceModel(my_underlying_model)
QTreeView::setModel(proxy_model)
Edit: I confirmed that the
modelAboutToBeReset()
andmodelReset()
signals are received by theQSortFilterProxyModel
. -
Please provide a minimal, compilable example - a QSortFilterProxyModel only does strange things when you do strange stuff underneath them.
-
@JonB said in QSortFilterProxyModel: Reset model shows ghost items:
There is a "model tester" somewhere you should run on your custom model to make sure it behaves correctly in all situations.
I think that's the one you should follow?
-
This indeed turned out to be a mistake in the implementation of the underlying model.
Thanks guys!
-
@Joel-Bodenmann Could you please share with us the actual issue you had and how you fixed it? Even if you feel like it was a stupid mistake, it way still help someone else ;)
As a side note I am now facing a similar issue with a QTableView in Qt 4.8.3, I just tried to apply the ModelTest to my model and no assert is triggering...
I am also using the reset model paradigm to update my custom model class behind the QSortFilterProxyModel and end up with some empty rows in the QTableView when the new model is loaded.
What is really curious is that it only happens when I have multiple rows selected in the QTableView (all rows are processed and I expect only one of them to be removed at end of processing).
When I select only the row that should dissapear at the end of the process it works just fine.
Also after getting the ghost line if I change the model to a completely different source and then come back the the buggy one, then I have no more ghost line...Any further hint would be appreciated :)
EDIT: Nevermind, my issue was also a stupid mistake: I was simply not calling the function to make the whole reset model stuff when I had multiple lines selected ^^
-
@FPEY said in QSortFilterProxyModel: Reset model shows ghost items:
EDIT: Nevermind, my issue was also a stupid mistake: I was simply not calling the function to make the whole reset model stuff when I had multiple lines selected ^^
Glad to hear that you managed to resolve your issue :)
I'm not exactly sure where the problem I was facing originated from hence I didn't leave any details as I don't want people to be mislead.
This was my first time working withQStandardItemModel
. So far I have always implemented models directly by deriving fromQAbstractItemModel
.When using the
QStandardItemModel
with the proxy model, the proxy's state was not invalidated when rows were inserted or removed (again, I don't know (yet) why).The quick fix without actually understanding the problem was to invoke the
QStandardItemModel::invalidate
slot whenever rows were either inserted or removed:connect(m_model, &model::rowsInserted, m_proxy_model, &QSortFilterProxyModel::invalidate); connect(m_model, &model::rowsRemoved, m_proxy_model, &QSortFilterProxyModel::invalidate);
Where:
m_model
is of typeQStandardItemModel*
m_proxy_model
is of typeQSortFilterProxyModel*