Hi
I'm building an application for scientific analyses. The underlying data is with Objects with relations to each other. One example is the "Experiment" class. This class has the following structure (almost, but with slightly different names):
Experiment
|-- Name (string)
|-- Researcher (string)
|-- Date (date)
|-- Solvents (list of 'Solvent' objects)
|-- Name (string)|-- CAS (string)|-- MVol (float)|-- Spheres (list of 'Sphere' objects)
|-- Name (string)|-- Center (float)|-- Radius (float)
What I would like to do is to create a very general QAbstractItemModel, which contains all the experiments existing in the database.
I then want to be able to use this QAbstractItemModel, together with ProxyModels in order to display a given experiment with various different views.
For example, I want the Name, Researcher and Date to be mapped to a simple form widget, such that the user can change these values. The "Spheres" is a list of spheres that I want to present in a "ListView" and the "Solvents" I want to present in a "TableView".
Selection of experiments
The user will in general press a button, which provides them with a ListView of all possible experiments, and can then select the one to open.
When the user "opens" an experiment, a TableView, ListView and Form widget is updated with the data belonging to this experiment (as per above). Some various operations will then be possible for the user.
The AbstractItemModel
I am trying to create the AbstractItemModel which is going to be the top level model for all the experiments, but I am having trouble understanding how to implement it. One of the problems I have is that the "Solvents" are NOT belonging to a given experiment, but instead shared amongst many experiments (one Solvent may be shared amongst many experiments). So I am unsure of how to implement the "parent" function for the model, given that I cannot know who is the parent for a given Solvent (since the Solvent doesn't really have a parent).
Testing with TreeView
I was trying to test with a TreeView, to see if I could generate a list of all the Experiments, and the "unfold" them to view the "Spheres" and "Solvents" associated with each Experiment, but to no avail...
Here is my first try. Note that I just implemented the parent function as returning an invalid QModelIndex. I'm unsure how to proceed, or if I have started going down a wrong path.
Code:
colName = { 'Experiments': ['Name','Researcher','Date','Solvents','Spheres'], 'Solvents': ['Name','dD','dH','dP','MVol','Score'], 'Spheres': ['Name','dD','dH','dP','R'] } def __init__(self,parent=None): self.Experiments = DM.LoadExperiments() def colIndex(self,level,colName): return self.colName[level].index(colName) def headerData(self,section,orientation,role = Qt.DisplayRole): if role == Qt.DisplayRole: if orientation == Qt.Horizontal: return self.colName['Experiments'][section] if not parent.isValid(): # Top level experiment return self.createIndex(row,col,self.Experiments[row]) Experiment = parent.internalPointer() if parent.column() == self.colIndex('Experiments','Solvents'): return self.createIndex(row,col,Experiment['Solvents'][row]) elif parent.column() == self.colIndex('Experiments','Sphers'): return self.createIndex(row,col,Experiment['Spheres'][row]) def parent(self,index): if not parent.isValid(): return len(self.Experiments) elif parent.column() == self.colIndex('Experiments','Solvents'): return len(self.Experiments[parent.row()]['Solvents']) elif parent.column() == self.colIndex('Experiments','Spheres'): return len(self.Experiments[parent.row()]['Spheres']) return 0 if not parent.isValid(): return len(self.colName['Experiments']) elif parent.column() == self.colIndex('Experiments','Solvents'): return len(self.colName['Solvents']) elif parent.column() == self.colIndex('Experiments','Sphers'): return len(self.colName['Spheres']) return 0 def data(self,index,role=Qt.DisplayRole): if role == Qt.DisplayRole: row, col = index.row(), index.column() if not index.parent().isValid(): # Then it is an experiment colName = self.colName['Experiments'][col] return self.Experiments[row][colName] else: pCol, pRow = index.parent().column(), index.parent().row() # If we are looking at a solvent if pCol == self.colIndex('Experiments','Solvents'): colName = self.colName['Solvents'][col] return self.Experiments[pRow]['Solvents'][row][colName] # If we are looking at a sphere elif pCol == self.colIndex('Experiments','Spheres'): colName = self.colName['Spheres'][col] return self.Experiments[pRow]['Spheres'][row][colName]