The following questions are about the design of the QAbstractItemModel
and QModelIndex
classes and the interplay between them, as highlighted by the sample of code below:
class Data:
def __init__(self):
self.value = 42
class Model( QAbstractItemModel ):
def __init__( self ):
QAbstractItemModel.__init__(self)
data = Data()
modelIndex = self.createIndex( 1 , 2 , data ) ### 1
self.index( 1 , 2 , QModelIndex() ) ### 2
self.setData( modelIndex , data.value ) ### 3
self.dataChanged.emit( modelIndex , modelIndex )
modelIndex.data() ###4
self.data( modelIndex ) ### 5
QModelIndex
be created. From my reading of the docs the answer is QAbstractItemModel::createIndex() but it seems incomplete because this function does not supply any information about the offset of the ModelIndex from its parent. Rather this is done by QAbstractItemModel::index(). Is there a way to make both functions play together?I am aware that my question links to the C++ API whereas the snippet is in PySide. I have done so because this question cuts across both APIs.
While @eyllanesc's answer is correct I struggled to understand it until I stared long and hard at this article before a pattern emerged. Therefore, I contribute to his answer in what I feel is a more logical way than the order I asked my questions.
In spite of what its name suggests, QAbstractItemModel is better understood as an interface to the model data. Typically the root to the model data is a member of the QAbstractItemModel object, which acts as a wrapper of sorts for the model data. (A different approach would be required, for example, if the data were stored in a SQL database.) QAbstractItemModel also:
Defines the (hierarchical) relationship between the data components.
Provides functions for adding and removing rows and columns of data from the model. (This fact is key to understanding how QModelIndex is used.)
QModelIndex is many things, but most importantly it contains the internal pointer to each data component, in addition to some information about current the position of the data component in the data hierarchy (the position can change). It should now be clear why the the docs state that:
Model indexes should be used immediately and then discarded. You should not rely on indexes to remain valid after calling model functions that change the structure of the model or delete items.
It is for this reason also why member functions of QAbstractItemModel that return a QModelIndex (e.g. QModelIndex::index() and QModelIndex::parent() ) have to create a fresh one everytime, using QAbstractItemModel::createIndex().
Finally, as @eyllanesc said, no implementation of the setter QAbstractItemModel::setData( QModelIndex , value, role ) is mandated unless the data is editable.