custom_model.py (2620B)
1 # loosely based on 2 # http://trevorius.com/scrapbook/uncategorized/pyqt-custom-abstractitemmodel/ 3 4 from PyQt5 import QtCore, QtWidgets 5 6 class CustomNode: 7 8 def __init__(self, model, data): 9 self.model = model 10 self._data = data 11 self._children = [] 12 self._parent = None 13 self._row = 0 14 15 def get_data(self): 16 return self._data 17 18 def get_data_for_role(self, index, role): 19 # define in child class 20 raise NotImplementedError() 21 22 def childCount(self): 23 return len(self._children) 24 25 def child(self, row): 26 if row >= 0 and row < self.childCount(): 27 return self._children[row] 28 29 def parent(self): 30 return self._parent 31 32 def row(self): 33 return self._row 34 35 def addChild(self, child): 36 child._parent = self 37 child._row = len(self._children) 38 self._children.append(child) 39 40 41 42 class CustomModel(QtCore.QAbstractItemModel): 43 44 def __init__(self, parent, columncount): 45 QtCore.QAbstractItemModel.__init__(self, parent) 46 self._root = CustomNode(self, None) 47 self._columncount = columncount 48 49 def rowCount(self, index): 50 if index.isValid(): 51 return index.internalPointer().childCount() 52 return self._root.childCount() 53 54 def columnCount(self, index): 55 return self._columncount 56 57 def addChild(self, node, _parent): 58 if not _parent or not _parent.isValid(): 59 parent = self._root 60 else: 61 parent = _parent.internalPointer() 62 parent.addChild(self, node) 63 64 def index(self, row, column, _parent=None): 65 if not _parent or not _parent.isValid(): 66 parent = self._root 67 else: 68 parent = _parent.internalPointer() 69 70 if not QtCore.QAbstractItemModel.hasIndex(self, row, column, _parent): 71 return QtCore.QModelIndex() 72 73 child = parent.child(row) 74 if child: 75 return QtCore.QAbstractItemModel.createIndex(self, row, column, child) 76 else: 77 return QtCore.QModelIndex() 78 79 def parent(self, index): 80 if index.isValid(): 81 node = index.internalPointer() 82 if node: 83 p = node.parent() 84 if p: 85 return QtCore.QAbstractItemModel.createIndex(self, p.row(), 0, p) 86 else: 87 return QtCore.QModelIndex() 88 return QtCore.QModelIndex() 89 90 def data(self, index, role): 91 if not index.isValid(): 92 return None 93 node = index.internalPointer() 94 return node.get_data_for_role(index, role)