Hi - I am building a simple model-view graphical editor in (Py)Qt, which was implemented once already in TkInter. I am a bit distressed by how complex it has been to implement the model in Qt.
Here is a simplified view of the program and its data: There are multiple Images, and multiple Points marked on each Image. The user selects one of the Images, and then views and edits its Points.
There is a QListView of Image names, annotated to show if an Image has been edited but not yet saved. A separate QListView lists the Points in the current image, displaying their names and locations. The current Image and its Points are edited in a QGraphicsView. A QTreeView might also be used in the future to show the list of Images and Points simultaneously.
The Points are actually held in a PointList class so that edits can be undone.
So the overall nested data structure is:
Image: filename, name, etc.
PointList: edit-in-progress, old-point-values
Point: name, x, y
Point
Point
…
Image
PointList
Point
…
…
Image: filename, name, etc.
PointList: edit-in-progress, old-point-values
Point: name, x, y
Point
Point
…
Image
PointList
Point
…
…
To copy to clipboard, switch view to plain text mode
I have implemented this as a subclass of QAbstractItemModel. It is a facade on my real nested data structure above. The top-level rows of the model are the Images, and each Image row has a set of child rows, one row per Point. I will implement a proxy model as well to present only the currently selected Image and its Points to the appropriate views.
The QAbstractItemModel coding was fairly painful, and is much more complex and fragile than the original data structure. There is a lot of checking whether a QModelIndex has a parent or not and a lot of case statement switching on column numbers and roles. I feel like I am emulating abstract data types in FORTRAN.
Actually, I believe that the pain of coding the model is because I had to flatten my three abstractions (Image, PointList, Point) into a single abstraction, my QAbstractItemModel.
Should I rethink how to do this? As an alternative, I could map my original abstractions onto two or three different nested models. The downside is that I have to connect them together explicitly with signals to make the model/view auto-updating work properly. But nested models is not a paradigm I have seen used much in Qt.
If you have faced a similar problem, I would be interested to hear how you solved it and how satisfied you were with the resulting implementation.
Thanks,
Dan
Bookmarks