eric7/E5Gui/E5TreeWidget.py

branch
eric7
changeset 8356
68ec9c3d4de5
parent 8355
8a7677a63c8d
child 8357
a081458cc57b
equal deleted inserted replaced
8355:8a7677a63c8d 8356:68ec9c3d4de5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing specialized tree views.
8 """
9
10 import enum
11
12 from PyQt6.QtCore import pyqtSignal, Qt
13 from PyQt6.QtWidgets import QTreeWidget, QTreeWidgetItem, QAbstractItemView
14
15
16 class E5TreeWidgetItemsState(enum.Enum):
17 """
18 Class defining the items expansion state.
19 """
20 COLLAPSED = 0
21 EXPANDED = 1
22
23
24 class E5TreeWidget(QTreeWidget):
25 """
26 Class implementing an extended tree widget.
27
28 @signal itemControlClicked(QTreeWidgetItem) emitted after a Ctrl-Click
29 on an item
30 @signal itemMiddleButtonClicked(QTreeWidgetItem) emitted after a click
31 of the middle button on an item
32 """
33 itemControlClicked = pyqtSignal(QTreeWidgetItem)
34 itemMiddleButtonClicked = pyqtSignal(QTreeWidgetItem)
35
36 def __init__(self, parent=None):
37 """
38 Constructor
39
40 @param parent reference to the parent widget (QWidget)
41 """
42 super().__init__(parent)
43
44 self.__refreshAllItemsNeeded = True
45 self.__allTreeItems = []
46 self.__showMode = E5TreeWidgetItemsState.COLLAPSED
47
48 self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
49
50 self.itemChanged.connect(self.__scheduleRefresh)
51
52 def setDefaultItemShowMode(self, mode):
53 """
54 Public method to set the default item show mode.
55
56 @param mode default mode
57 @type E5TreeWidgetItemsState
58 """
59 self.__showMode = mode
60
61 def allItems(self):
62 """
63 Public method to get a list of all items.
64
65 @return list of all items (list of QTreeWidgetItem)
66 """
67 if self.__refreshAllItemsNeeded:
68 self.__allTreeItems = []
69 self.__iterateAllItems(None)
70 self.__refreshAllItemsNeeded = False
71
72 return self.__allTreeItems
73
74 def appendToParentItem(self, parent, item):
75 """
76 Public method to append an item to a parent item.
77
78 @param parent text of the parent item (string) or
79 the parent item (QTreeWidgetItem)
80 @param item item to be appended (QTreeWidgetItem)
81 @return flag indicating success (boolean)
82 @exception RuntimeError raised to indicate an illegal type for
83 the parent
84 """
85 if not isinstance(parent, (QTreeWidgetItem, str)):
86 raise RuntimeError("illegal type for parent")
87
88 if isinstance(parent, QTreeWidgetItem):
89 if parent is None or parent.treeWidget() != self:
90 return False
91 parentItem = parent
92 else:
93 lst = self.findItems(parent, Qt.MatchFlag.MatchExactly)
94 if not lst:
95 return False
96 parentItem = lst[0]
97 if parentItem is None:
98 return False
99
100 self.__allTreeItems.append(item)
101 parentItem.addChild(item)
102 return True
103
104 def prependToParentItem(self, parent, item):
105 """
106 Public method to prepend an item to a parent item.
107
108 @param parent text of the parent item (string) or
109 the parent item (QTreeWidgetItem)
110 @param item item to be prepended (QTreeWidgetItem)
111 @return flag indicating success (boolean)
112 @exception RuntimeError raised to indicate an illegal type for
113 the parent
114 """
115 if not isinstance(parent, (QTreeWidgetItem, str)):
116 raise RuntimeError("illegal type for parent")
117
118 if isinstance(parent, QTreeWidgetItem):
119 if parent is None or parent.treeWidget() != self:
120 return False
121 parentItem = parent
122 else:
123 lst = self.findItems(parent, Qt.MatchFlag.MatchExactly)
124 if not lst:
125 return False
126 parentItem = lst[0]
127 if parentItem is None:
128 return False
129
130 self.__allTreeItems.append(item)
131 parentItem.insertChild(0, item)
132 return True
133
134 def addTopLevelItem(self, item):
135 """
136 Public method to add a top level item.
137
138 @param item item to be added as a top level item (QTreeWidgetItem)
139 """
140 self.__allTreeItems.append(item)
141 super().addTopLevelItem(item)
142
143 def addTopLevelItems(self, items):
144 """
145 Public method to add a list of top level items.
146
147 @param items items to be added as top level items
148 (list of QTreeWidgetItem)
149 """
150 self.__allTreeItems.extend(items)
151 super().addTopLevelItems(items)
152
153 def insertTopLevelItem(self, index, item):
154 """
155 Public method to insert a top level item.
156
157 @param index index for the insertion (integer)
158 @param item item to be inserted as a top level item (QTreeWidgetItem)
159 """
160 self.__allTreeItems.append(item)
161 super().insertTopLevelItem(index, item)
162
163 def insertTopLevelItems(self, index, items):
164 """
165 Public method to insert a list of top level items.
166
167 @param index index for the insertion (integer)
168 @param items items to be inserted as top level items
169 (list of QTreeWidgetItem)
170 """
171 self.__allTreeItems.extend(items)
172 super().insertTopLevelItems(index, items)
173
174 def deleteItem(self, item):
175 """
176 Public method to delete an item.
177
178 @param item item to be deleted (QTreeWidgetItem)
179 """
180 if item in self.__allTreeItems:
181 self.__allTreeItems.remove(item)
182
183 self.__refreshAllItemsNeeded = True
184
185 del item
186
187 def deleteItems(self, items):
188 """
189 Public method to delete a list of items.
190
191 @param items items to be deleted (list of QTreeWidgetItem)
192 """
193 for item in items:
194 self.deleteItem(item)
195
196 def filterString(self, filterStr):
197 """
198 Public slot to set a new filter.
199
200 @param filterStr filter to be set (string)
201 """
202 self.expandAll()
203 allItems = self.allItems()
204
205 if filterStr:
206 lFilter = filterStr.lower()
207 for itm in allItems:
208 itm.setHidden(lFilter not in itm.text(0).lower())
209 itm.setExpanded(True)
210 for index in range(self.topLevelItemCount()):
211 self.topLevelItem(index).setHidden(False)
212
213 firstItm = self.topLevelItem(0)
214 belowItm = self.itemBelow(firstItm)
215 topLvlIndex = 0
216 while firstItm:
217 if lFilter in firstItm.text(0).lower():
218 firstItm.setHidden(False)
219 elif (
220 not firstItm.parent() and
221 (not belowItm or not belowItm.parent())
222 ):
223 firstItm.setHidden(True)
224 elif not belowItm:
225 break
226
227 topLvlIndex += 1
228 firstItm = self.topLevelItem(topLvlIndex)
229 belowItm = self.itemBelow(firstItm)
230 else:
231 for itm in allItems:
232 itm.setHidden(False)
233 for index in range(self.topLevelItemCount()):
234 self.topLevelItem(index).setHidden(False)
235 if self.__showMode == E5TreeWidgetItemsState.COLLAPSED:
236 self.collapseAll()
237
238 def clear(self):
239 """
240 Public slot to clear the tree.
241 """
242 self.__allTreeItems = []
243 super().clear()
244
245 def __scheduleRefresh(self):
246 """
247 Private slot to schedule a refresh of the tree.
248 """
249 self.__refreshAllItemsNeeded = True
250
251 def mousePressEvent(self, evt):
252 """
253 Protected method handling mouse press events.
254
255 @param evt mouse press event (QMouseEvent)
256 """
257 if (
258 evt.modifiers() == Qt.KeyboardModifier.ControlModifier and
259 evt.buttons() == Qt.MouseButton.LeftButton
260 ):
261 self.itemControlClicked.emit(self.itemAt(evt.position().toPoint()))
262 return
263 elif evt.buttons() == Qt.MouseButton.MiddleButton:
264 self.itemMiddleButtonClicked.emit(self.itemAt(evt.position().toPoint()))
265 return
266 else:
267 super().mousePressEvent(evt)
268
269 def __iterateAllItems(self, parent):
270 """
271 Private method to iterate over the child items of the parent.
272
273 @param parent parent item to iterate (QTreeWidgetItem)
274 """
275 count = parent.childCount() if parent else self.topLevelItemCount()
276
277 for index in range(count):
278 itm = parent.child(index) if parent else self.topLevelItem(index)
279
280 if itm.childCount() == 0:
281 self.__allTreeItems.append(itm)
282
283 self.__iterateAllItems(itm)

eric ide

mercurial