質問

In Qt, I'm writing my own tree model (by subclassing QAbstractItemModel) which wraps around an existing data structure. It should be possible to update the data structure internally (not via the model) as well as via the model (so views can change it). In order to imagine it better: it's a scene graph which should be possible to edit using a scene view (without going via the Qt model) but also using an outliner (QTreeView which uses a Qt model as a proxy around the scene graph).

To avoid confusion we should consider two different scenarios (in the following, I use the "remove" operation as an example):

  1. The user uses the Qt view to remove a node. The view wants to remove a row from the model using QAbstractItemModel::removeRow. This should in turn remove a corresponding node from the underlying data structure, the scene graph. Calls in scenario 1

  2. The user uses the scene view to remove a node. The scene view wants to remove a node from the scene graph. The model which wraps around the scene graph gets notified and in turn wants to notify connected views that a row has just been removed. Calls in scenario 2

While I think I know how to implement 1., I don't know how to implement the notifying part in 2. There is the signal QAbstractItemModel::rowsAboutToBeRemoved() as well as rowsRemoved() which sound like they're my friends. But they are private signals (they say in the header source code: "can only be emitted by QAbstractItemModel"). There also is beginRemoveRows() and endRemoveRows() but according to their documentation, they should be called when the updates happens from the view, i.e. when removeRow has been called. Also, when I tried to use them, the view was screwed up totally.

According to the documentation it seems like it's not intended that the model class can model self-modifying data. Let's take a file system as another example. When using file system watching, which can detect changes in directories, a model should notify a view so the changes in the directory can be displayed live, even if the view was not used to modify the file system. Are such models even possible in Qt?

役に立ちましたか?

解決

You're reading it wrong. The model must signal to its users when it's about to start changing its "geometry". So, no matter what is removing the rows from the model, it must tell the outside world that it happened. The sequence of events when a view removes rows from the model is such:

  1. The view calls model->removeRows().

  2. The model calls beginRemoveRows()

  3. The model actually removes the rows from the internal data.

  4. The model calls endRemoveRows().

If you implement some other interface that will remove the rows without calling model->removeRows(), you have to do exactly the same thing. It doesn't matter if it's a view or some other code that removes rows from the model, the model's behavior must be the same or else nothing will work.

You can architect an adapter class that's inserted between your SceneGraph and the Model. It should hold a pointer to the scenegraph and the model, and translate the operations between the two.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top