Implementing a QAbstractItemModel that reacts to external changes
-
I'm writing a QAbstractItemModel for a tree view that represents a hierarchy of QObjects.
I'm storing the pointer to the QObject as the internal pointer in the model indexes.Sometimes the objects are added/removed from the hierarchy (always outside the view / item model) and I want the model to notify the view about the change.
The problem I'm having is that functions like beginRemoveRows etc say that they need to be called before the removal has happened and functions like endRemoveRows should happen after the data has been removed.
Since I'm reacting to changes happening outside the model this isn't possible as I can be notified of the change having already happened in the storage.
I tried just calling the begin/end functions but doing that causes the model to call parent() passing indexes with objects which have already been deleted.Is there any way around this issue?
-
Unfortunately it's a common problem when integrating with external data source.
If you have a way to modify that storage the cleanest way is to provide some sort of callback before you modify the storage - that's how Qt model is designed to work.If you can't do that there are layers of increasing ugliness that you can try.
In the past I've dealt with this problem in different ways depending on what I had to work with.
In one case I had an internal structure in the model that held info about the integrity of the objects and carefully checked it before every access in the model.
In another case I could modify the objects themselves to send anaboutToBeDestroyed()
signal.
Yet another time I had to wrap all the calls that modified the 3rd party storage with my own functions that emitted appropriate signals.I realize it's sort of a hand wave, but it's hard to suggest a specific solution that will work in your case without knowing more details about what you have access to.
-
Hi and welcome to devnet,
Can you explain a bit more how these changes happen ? What kind of data structure are you using ?
One way would be for the data structure to have an API that you can use in your model to keep things in sync.
-
@adomanim
beginModelReset()
is just likebeginInsertRows()
in the sense that the data needs to still be valid at the point where it is called, so calling it after the change already occurred is the same error as callingbeginInsertRows()
. Some views might handle it fine, just like some views might handlebeginInsertRows()
on modified data fine, but you should never rely on that, as it breaks the API contract.
destroyed()
is called from QObject's destructor meaning it's often unsuitable if you need to access anything from the derived class (destructors of the derived already executed). It could be useful though if you use it like you said - as a key in some sort of map used for validation. Unfortunately that's often only part of the puzzle. -
@Chris-Kawa The post before you was made by a spammer; it has been deleted.