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
« 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
9from .items import TreeItem, RootItem
12class HeaderSection(object):
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
21class Header(list):
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
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
46 def attrNameData(self, section, role):
47 try:
48 return self[section].roles[role]
49 except (IndexError, KeyError):
50 return None
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
59 def flags(self, section):
60 try:
61 roles = self[section].roles
62 except IndexError:
63 return None
65 if qt.Qt.EditRole in roles:
66 return qt.Qt.ItemIsEditable
67 return None
69 def delegate(self, section):
70 try:
71 return self[section].delegate
72 except IndexError:
73 return None
76class TreeModel(qt.QAbstractItemModel):
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)
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)
100 # Get the child at the position specified by the row.
101 childItem = parentItem.child(row)
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()
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()
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)
122 def rowCount(self, parent=qt.QModelIndex()):
123 item = self.itemFromIndex(parent)
124 return item.childCount()
126 def columnCount(self, parent=qt.QModelIndex()):
127 return len(self.header)
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)
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
144 def itemFromIndex(self, index):
145 if index.isValid():
146 return index.internalPointer()
147 else:
148 return self.rootItem
150 def indexFromItem(self, item):
151 if item == self.rootItem:
152 return qt.QModelIndex()
153 else:
154 return self.createIndex(item.childPosition(), 0, item)
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)
167 def headerData(self, section, orientation, role):
168 if orientation == qt.Qt.Horizontal:
169 return self.header.data(section, role)
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
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)
183 self.beginInsertRows(parent, row, row + count - 1)
184 result = parentItem.insertRows(row, count)
185 self.endInsertRows()
187 self.dataChanged.emit(topLeft, bottomRight)
189 return result
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)
196 self.beginRemoveRows(parent, row, row + count - 1)
197 result = parentItem.removeRows(row, count)
198 self.endRemoveRows()
200 self.dataChanged.emit(topLeft, bottomRight)
202 return result
204 def insertRow(self, row, item):
205 """Inserts a row at row containing item."""
206 parentItem = item.parentItem
207 parent = self.indexFromItem(parentItem)
209 self.beginInsertRows(parent, row, row)
210 parentItem.childItems.insert(row, item)
211 self.endInsertRows()
213 index = self.index(row, 0, parent)
214 self.dataChanged.emit(index, index)
216 return True
218 def appendRow(self, item):
219 parentItem = item.parentItem
220 self.insertRow(parentItem.childCount(), item)
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
232 index = self.index(row, 0, parent)
233 for index in self.visitModel(index, columns):
234 yield index
236 def setModelData(self, data, parent=qt.QModelIndex()):
237 if not parent.isValid():
238 parentItem = self.rootItem
239 else:
240 parentItem = self.itemFromIndex(parent)
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)