Coverage for /Users/Newville/Codes/xraylarch/larch/qtlib/model.py: 0%

173 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-09 10:08 -0600

1#!/usr/bin/env python 

2# -*- coding: utf-8 -*- 

3"""This module provides a class to implement a tree model for 

4spectroscopy data. 

5""" 

6from __future__ import absolute_import, division 

7from silx.gui import qt 

8 

9from .items import TreeItem, RootItem 

10 

11 

12class HeaderSection(object): 

13 

14 def __init__(self, name, roles, delegate=None, removable=False): 

15 self.name = name 

16 self.roles = roles 

17 self.delegate = delegate 

18 self.removable = removable 

19 

20 

21class Header(list): 

22 

23 def data(self, section, role=qt.Qt.DisplayRole): 

24 if role == qt.Qt.DisplayRole: 

25 try: 

26 return self[section].name 

27 except IndexError: 

28 return None 

29 

30 def setData(self, section, value, role): 

31 if role == qt.Qt.EditRole: 

32 if value is None: 

33 try: 

34 del self[section] 

35 return True 

36 except IndexError: 

37 return False 

38 else: 

39 try: 

40 self[section] = value 

41 except IndexError: 

42 self.append(value) 

43 return True 

44 return False 

45 

46 def attrNameData(self, section, role): 

47 try: 

48 return self[section].roles[role] 

49 except (IndexError, KeyError): 

50 return None 

51 

52 def attrNameSetData(self, section, role): 

53 if role == qt.Qt.EditRole: 

54 try: 

55 return self[section].roles[qt.Qt.DisplayRole] 

56 except (IndexError, KeyError): 

57 return None 

58 

59 def flags(self, section): 

60 try: 

61 roles = self[section].roles 

62 except IndexError: 

63 return None 

64 

65 if qt.Qt.EditRole in roles: 

66 return qt.Qt.ItemIsEditable 

67 return None 

68 

69 def delegate(self, section): 

70 try: 

71 return self[section].delegate 

72 except IndexError: 

73 return None 

74 

75 

76class TreeModel(qt.QAbstractItemModel): 

77 

78 def __init__(self, parent=None): 

79 super(TreeModel, self).__init__(parent=parent) 

80 self.rootItem = RootItem() 

81 self.header = Header() 

82 section = 0 

83 orientation = qt.Qt.Horizontal 

84 value = HeaderSection( 

85 name='Name', roles={ 

86 qt.Qt.DisplayRole: 'name', qt.Qt.EditRole: 'name'}) 

87 self.setHeaderData(section, orientation, value) 

88 

89 def index(self, row, column, parent): 

90 """Return the index of the item in the model specified by the 

91 row, column, and parent index. 

92 """ 

93 # If the item has no parent it is the root item. Otherwise, get 

94 # the parent item from the parent index. 

95 if not parent.isValid(): 

96 parentItem = self.rootItem 

97 else: 

98 parentItem = self.itemFromIndex(parent) 

99 

100 # Get the child at the position specified by the row. 

101 childItem = parentItem.child(row) 

102 

103 # If the child item exists, create an index for it. 

104 if childItem is not None: 

105 return self.createIndex(row, column, childItem) 

106 else: 

107 return qt.QModelIndex() 

108 

109 def parent(self, index): 

110 """Return the index of the parent for a child index.""" 

111 # Use the index of the child to get the child item. 

112 childItem = self.itemFromIndex(index) 

113 # Call the parent() method of the child to get the parent item. 

114 parentItem = childItem.parent() 

115 

116 # If the parent item is not the root item, create an index for it. 

117 if parentItem == self.rootItem: 

118 return qt.QModelIndex() 

119 else: 

120 return self.createIndex(parentItem.childPosition(), 0, parentItem) 

121 

122 def rowCount(self, parent=qt.QModelIndex()): 

123 item = self.itemFromIndex(parent) 

124 return item.childCount() 

125 

126 def columnCount(self, parent=qt.QModelIndex()): 

127 return len(self.header) 

128 

129 def data(self, index, role=qt.Qt.DisplayRole): 

130 item = self.itemFromIndex(index) 

131 section = index.column() 

132 name = self.header.attrNameData(section, role) 

133 return item.data(section, name, role) 

134 

135 def setData(self, index, value, role=qt.Qt.EditRole): 

136 item = self.itemFromIndex(index) 

137 section = index.column() 

138 name = self.header.attrNameSetData(section, role) 

139 if item.setData(section, name, value, role): 

140 self.dataChanged.emit(index, index) 

141 return True 

142 return False 

143 

144 def itemFromIndex(self, index): 

145 if index.isValid(): 

146 return index.internalPointer() 

147 else: 

148 return self.rootItem 

149 

150 def indexFromItem(self, item): 

151 if item == self.rootItem: 

152 return qt.QModelIndex() 

153 else: 

154 return self.createIndex(item.childPosition(), 0, item) 

155 

156 def flags(self, index): 

157 section = index.column() 

158 item = self.itemFromIndex(index) 

159 flags = self.header.flags(section) 

160 name = self.header.attrNameData(section, qt.Qt.DisplayRole) 

161 data = item.data(section, name, qt.Qt.DisplayRole) 

162 if flags is not None and data is not None: 

163 return flags | item.flags(section) 

164 else: 

165 return item.flags(section) 

166 

167 def headerData(self, section, orientation, role): 

168 if orientation == qt.Qt.Horizontal: 

169 return self.header.data(section, role) 

170 

171 def setHeaderData(self, section, orientation, value, role=qt.Qt.EditRole): 

172 if orientation == qt.Qt.Horizontal: 

173 if self.header.setData(section, value, role): 

174 self.headerDataChanged.emit(orientation, section, section) 

175 return True 

176 return False 

177 

178 def insertRows(self, row, count, parent=qt.QModelIndex()): 

179 parentItem = self.itemFromIndex(parent) 

180 topLeft = self.index(row, 0, parent) 

181 bottomRight = self.index(row + count - 1, 0, parent) 

182 

183 self.beginInsertRows(parent, row, row + count - 1) 

184 result = parentItem.insertRows(row, count) 

185 self.endInsertRows() 

186 

187 self.dataChanged.emit(topLeft, bottomRight) 

188 

189 return result 

190 

191 def removeRows(self, row, count, parent=qt.QModelIndex()): 

192 parentItem = self.itemFromIndex(parent) 

193 topLeft = self.index(row, 0, parent) 

194 bottomRight = self.index(row + count - 1, 0, parent) 

195 

196 self.beginRemoveRows(parent, row, row + count - 1) 

197 result = parentItem.removeRows(row, count) 

198 self.endRemoveRows() 

199 

200 self.dataChanged.emit(topLeft, bottomRight) 

201 

202 return result 

203 

204 def insertRow(self, row, item): 

205 """Inserts a row at row containing item.""" 

206 parentItem = item.parentItem 

207 parent = self.indexFromItem(parentItem) 

208 

209 self.beginInsertRows(parent, row, row) 

210 parentItem.childItems.insert(row, item) 

211 self.endInsertRows() 

212 

213 index = self.index(row, 0, parent) 

214 self.dataChanged.emit(index, index) 

215 

216 return True 

217 

218 def appendRow(self, item): 

219 parentItem = item.parentItem 

220 self.insertRow(parentItem.childCount(), item) 

221 

222 def visitModel(self, parent=qt.QModelIndex(), columns=False): 

223 for row in range(self.rowCount(parent)): 

224 if columns: 

225 for column in range(self.columnCount(parent)): 

226 index = self.index(row, column, parent) 

227 yield index 

228 else: 

229 index = self.index(row, 0, parent) 

230 yield index 

231 

232 index = self.index(row, 0, parent) 

233 for index in self.visitModel(index, columns): 

234 yield index 

235 

236 def setModelData(self, data, parent=qt.QModelIndex()): 

237 if not parent.isValid(): 

238 parentItem = self.rootItem 

239 else: 

240 parentItem = self.itemFromIndex(parent) 

241 

242 for name in data: 

243 item = TreeItem(name=name, parentItem=parentItem) 

244 self.appendRow(item) 

245 if data is not None and isinstance(data[name], dict): 

246 index = self.indexFromItem(item) 

247 self.setModelData(data=data[name], parent=index)