PDA

View Full Version : Data structure reference in Model/View Framework



jimc1200
11th September 2009, 10:20
In QAbstractItemModel there's a way to associate an outside data structure using QModelIndex::internalPointer (). I was wondering if there's a way to reference the other way around from the data structure. Let's say the structure was modified and I need to insert new child nodes on the parent node in the model, how do I find out which part in the model corresponds to my data structure so that I would know the parent model index where to insert? I would like to use the beginInsertRows to add new children nodes but I don't know parent model index. What's the best way to do this? As I understand using reset() is costly since it would recreate the model again.

gdiepen
11th September 2009, 11:19
I had a similar kind of question recently. In my case the underlying data changes and I must inform the model. This indeed required to create the QModelIndex for a given item in my underlying data.

From the replies I got in the thread (http://www.qtcentre.org/forum/f-qt-programming-2/t-some-unclarities-about-qabstractitemmodel-and-dynamic-underlying-data-23403.html), I was able to finally have everything up and running. The proof that I have it working can be seen in the small screencast (http://www.guidodiepen.nl/2009/09/viewing-registry-keys-only-from-within-synce-kpm/) on my website.

Hope the info in the thread I started is helpful.

Guido Diepen

jimc1200
11th September 2009, 22:43
Guido,

Thanks for pointing me to the other thread. It looks like I exactly have the same application structure from what you described. The underlying data is updated outside the model (ex. by a thread) and would need to update the model for any modifications. In the editable tree model example it shows how you could access the underlying info given a model index. However I didn't see any code that does the vice versa, ie. given a node in the underlying structure/data you can derive the corresponding model index.
Can you elaborate on how you did this in your application? Did you have to traverse your underlying structure and derive the model index?

Thank you.:

gdiepen
12th September 2009, 09:14
Guido,

Thanks for pointing me to the other thread. It looks like I exactly have the same application structure from what you described. The underlying data is updated outside the model (ex. by a thread) and would need to update the model for any modifications. In the editable tree model example it shows how you could access the underlying info given a model index. However I didn't see any code that does the vice versa, ie. given a node in the underlying structure/data you can derive the corresponding model index.
Can you elaborate on how you did this in your application? Did you have to traverse your underlying structure and derive the model index?

Thank you.:

Interesting, I had exactly the same idea as you are stating at the moment. The nice thing is that for creating the QModelIndex that refers to a given element, you do not need to have a reference to its parent QModelIndex. I thought this in the beginning also, but this is not the case.

The way I see it right now is that a QModelIndex is purely a way of pointing to a given element, however, it does not know anything about its parent or whatever. The way a QModelIndex gets the parent information is by calling the QAbstractItemModel::parent(QModelIndex) function.

To create a QModelIndex for a given element, you need to know its parent item (note: note index, but underlying item object). The reason why you need this is that the QModelIndex you are generating contains a row-number, which denotes the index of this item you have in the list of child-items of its parent.

I am working with PyQt4 at the moment, but the idea is still the same, so hopefully the code snippets below help.


I have a row function, which returns the number the registrykey has in the list of child-keys of its parent:


def row(self):
"""Return the row number of this key in the list of its parent"""
if self.parent:
return self.parent.keys.index(self)

return -1


Using the information I get from the above, I get a QModelIndex for the registrykey key by calling the createIndex method of the model with this row-number, the column number 0 (i don't care about column in my model), and the key object itself, which can later be obtained by calling the internalPointer() method on the QModelIndex


self.registry_key_model.createIndex( key.row(), 0, key )


Please note that you also have to implement the index( row, column, parent) function, where parent is a QModelIndex.

This means you first have to get the real item that the parent qmodelindex corresponds to. In my case I can do so by using the internalPointer() method.
When you have the parent item, you can determine the actual child-item by using the row/column values. After that, you can create a QModelIndex for this particular item again with the createIndex() method as shown above.

Hopefully the above helps you to understand the usage of the QModelIndex stuff. I know that it took me some time to understand, but I think that right now I pretty much understand it completely :)

Guido Diepen

jimc1200
14th September 2009, 21:23
Thank you Guido for your explanations and providing some code snippets (I'm using c++ but I can easily relate it to your python code).