src/eric7/UI/BrowserModel.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9297
c1c808e65211
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
11 import fnmatch 11 import fnmatch
12 import json 12 import json
13 import contextlib 13 import contextlib
14 14
15 from PyQt6.QtCore import ( 15 from PyQt6.QtCore import (
16 QDir, QModelIndex, QAbstractItemModel, QFileSystemWatcher, Qt, QProcess, 16 QDir,
17 QCoreApplication 17 QModelIndex,
18 QAbstractItemModel,
19 QFileSystemWatcher,
20 Qt,
21 QProcess,
22 QCoreApplication,
18 ) 23 )
19 from PyQt6.QtGui import QImageReader, QFont 24 from PyQt6.QtGui import QImageReader, QFont
20 from PyQt6.QtWidgets import QApplication 25 from PyQt6.QtWidgets import QApplication
21 26
22 import UI.PixmapCache 27 import UI.PixmapCache
38 43
39 class BrowserModel(QAbstractItemModel): 44 class BrowserModel(QAbstractItemModel):
40 """ 45 """
41 Class implementing the browser model. 46 Class implementing the browser model.
42 """ 47 """
48
43 def __init__(self, parent=None, nopopulate=False): 49 def __init__(self, parent=None, nopopulate=False):
44 """ 50 """
45 Constructor 51 Constructor
46 52
47 @param parent reference to parent object (QObject) 53 @param parent reference to parent object (QObject)
48 @param nopopulate flag indicating to not populate the model 54 @param nopopulate flag indicating to not populate the model
49 (boolean) 55 (boolean)
50 """ 56 """
51 super().__init__(parent) 57 super().__init__(parent)
52 58
53 self.progDir = None 59 self.progDir = None
54 60
55 self.__sysPathInterpreter = "" 61 self.__sysPathInterpreter = ""
56 self.__sysPathItem = None 62 self.__sysPathItem = None
57 63
58 if not nopopulate: 64 if not nopopulate:
59 self.watchedItems = {} 65 self.watchedItems = {}
60 self.watchedFileItems = {} 66 self.watchedFileItems = {}
61 self.watcher = QFileSystemWatcher(self) 67 self.watcher = QFileSystemWatcher(self)
62 self.watcher.directoryChanged.connect(self.directoryChanged) 68 self.watcher.directoryChanged.connect(self.directoryChanged)
63 self.watcher.fileChanged.connect(self.fileChanged) 69 self.watcher.fileChanged.connect(self.fileChanged)
64 70
65 rootData = QCoreApplication.translate("BrowserModel", "Name") 71 rootData = QCoreApplication.translate("BrowserModel", "Name")
66 self.rootItem = BrowserItem(None, rootData) 72 self.rootItem = BrowserItem(None, rootData)
67 73
68 self.__populateModel() 74 self.__populateModel()
69 75
70 def columnCount(self, parent=None): 76 def columnCount(self, parent=None):
71 """ 77 """
72 Public method to get the number of columns. 78 Public method to get the number of columns.
73 79
74 @param parent index of parent item (QModelIndex) 80 @param parent index of parent item (QModelIndex)
75 @return number of columns (integer) 81 @return number of columns (integer)
76 """ 82 """
77 if parent is None: 83 if parent is None:
78 parent = QModelIndex() 84 parent = QModelIndex()
79 85
80 item = (parent.internalPointer() if parent.isValid() 86 item = parent.internalPointer() if parent.isValid() else self.rootItem
81 else self.rootItem) 87
82
83 return item.columnCount() + 1 88 return item.columnCount() + 1
84 89
85 def data(self, index, role): 90 def data(self, index, role):
86 """ 91 """
87 Public method to get data of an item. 92 Public method to get data of an item.
88 93
89 @param index index of the data to retrieve (QModelIndex) 94 @param index index of the data to retrieve (QModelIndex)
90 @param role role of data (Qt.ItemDataRole) 95 @param role role of data (Qt.ItemDataRole)
91 @return requested data 96 @return requested data
92 """ 97 """
93 if not index.isValid(): 98 if not index.isValid():
94 return None 99 return None
95 100
96 if role == Qt.ItemDataRole.DisplayRole: 101 if role == Qt.ItemDataRole.DisplayRole:
97 item = index.internalPointer() 102 item = index.internalPointer()
98 if index.column() < item.columnCount(): 103 if index.column() < item.columnCount():
99 return item.data(index.column()) 104 return item.data(index.column())
100 elif ( 105 elif (
101 index.column() == item.columnCount() and 106 index.column() == item.columnCount()
102 index.column() < self.columnCount(self.parent(index)) 107 and index.column() < self.columnCount(self.parent(index))
103 ): 108 ):
104 # This is for the case where an item under a multi-column 109 # This is for the case where an item under a multi-column
105 # parent doesn't have a value for all the columns 110 # parent doesn't have a value for all the columns
106 return "" 111 return ""
107 elif role == Qt.ItemDataRole.DecorationRole: 112 elif role == Qt.ItemDataRole.DecorationRole:
111 item = index.internalPointer() 116 item = index.internalPointer()
112 if item.isSymlink(): 117 if item.isSymlink():
113 font = QFont(QApplication.font("QTreeView")) 118 font = QFont(QApplication.font("QTreeView"))
114 font.setItalic(True) 119 font.setItalic(True)
115 return font 120 return font
116 121
117 return None 122 return None
118 123
119 def flags(self, index): 124 def flags(self, index):
120 """ 125 """
121 Public method to get the item flags. 126 Public method to get the item flags.
122 127
123 @param index index of the data to retrieve (QModelIndex) 128 @param index index of the data to retrieve (QModelIndex)
124 @return requested flags (Qt.ItemFlags) 129 @return requested flags (Qt.ItemFlags)
125 """ 130 """
126 if not index.isValid(): 131 if not index.isValid():
127 return Qt.ItemFlag.ItemIsEnabled 132 return Qt.ItemFlag.ItemIsEnabled
128 133
129 return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable 134 return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable
130 135
131 def headerData(self, section, orientation, 136 def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole):
132 role=Qt.ItemDataRole.DisplayRole):
133 """ 137 """
134 Public method to get the header data. 138 Public method to get the header data.
135 139
136 @param section number of section to get data for (integer) 140 @param section number of section to get data for (integer)
137 @param orientation header orientation (Qt.Orientation) 141 @param orientation header orientation (Qt.Orientation)
138 @param role role of data (Qt.ItemDataRole) 142 @param role role of data (Qt.ItemDataRole)
139 @return requested header data 143 @return requested header data
140 """ 144 """
141 if ( 145 if (
142 orientation == Qt.Orientation.Horizontal and 146 orientation == Qt.Orientation.Horizontal
143 role == Qt.ItemDataRole.DisplayRole 147 and role == Qt.ItemDataRole.DisplayRole
144 ): 148 ):
145 if section >= self.rootItem.columnCount(): 149 if section >= self.rootItem.columnCount():
146 return "" 150 return ""
147 else: 151 else:
148 return self.rootItem.data(section) 152 return self.rootItem.data(section)
149 153
150 return None 154 return None
151 155
152 def index(self, row, column, parent=None): 156 def index(self, row, column, parent=None):
153 """ 157 """
154 Public method to create an index. 158 Public method to create an index.
155 159
156 @param row row number of the new index (integer) 160 @param row row number of the new index (integer)
157 @param column column number of the new index (integer) 161 @param column column number of the new index (integer)
158 @param parent index of parent item (QModelIndex) 162 @param parent index of parent item (QModelIndex)
159 @return index object (QModelIndex) 163 @return index object (QModelIndex)
160 """ 164 """
161 if parent is None: 165 if parent is None:
162 parent = QModelIndex() 166 parent = QModelIndex()
163 167
164 # The model/view framework considers negative values out-of-bounds, 168 # The model/view framework considers negative values out-of-bounds,
165 # however in python they work when indexing into lists. So make sure 169 # however in python they work when indexing into lists. So make sure
166 # we return an invalid index for out-of-bounds row/col 170 # we return an invalid index for out-of-bounds row/col
167 if ( 171 if (
168 row < 0 or 172 row < 0
169 column < 0 or 173 or column < 0
170 row >= self.rowCount(parent) or 174 or row >= self.rowCount(parent)
171 column >= self.columnCount(parent) 175 or column >= self.columnCount(parent)
172 ): 176 ):
173 return QModelIndex() 177 return QModelIndex()
174 178
175 parentItem = ( 179 parentItem = parent.internalPointer() if parent.isValid() else self.rootItem
176 parent.internalPointer() 180
177 if parent.isValid() else
178 self.rootItem
179 )
180
181 try: 181 try:
182 if not parentItem.isPopulated(): 182 if not parentItem.isPopulated():
183 self.populateItem(parentItem) 183 self.populateItem(parentItem)
184 childItem = parentItem.child(row) 184 childItem = parentItem.child(row)
185 except IndexError: 185 except IndexError:
186 childItem = None 186 childItem = None
187 if childItem: 187 if childItem:
188 return self.createIndex(row, column, childItem) 188 return self.createIndex(row, column, childItem)
189 else: 189 else:
190 return QModelIndex() 190 return QModelIndex()
191 191
192 def parent(self, index): 192 def parent(self, index):
193 """ 193 """
194 Public method to get the index of the parent object. 194 Public method to get the index of the parent object.
195 195
196 @param index index of the item (QModelIndex) 196 @param index index of the item (QModelIndex)
197 @return index of parent item (QModelIndex) 197 @return index of parent item (QModelIndex)
198 """ 198 """
199 if not index.isValid(): 199 if not index.isValid():
200 return QModelIndex() 200 return QModelIndex()
201 201
202 childItem = index.internalPointer() 202 childItem = index.internalPointer()
203 parentItem = childItem.parent() 203 parentItem = childItem.parent()
204 204
205 if parentItem is None or parentItem == self.rootItem: 205 if parentItem is None or parentItem == self.rootItem:
206 return QModelIndex() 206 return QModelIndex()
207 207
208 return self.createIndex(parentItem.row(), 0, parentItem) 208 return self.createIndex(parentItem.row(), 0, parentItem)
209 209
210 def rowCount(self, parent=None): 210 def rowCount(self, parent=None):
211 """ 211 """
212 Public method to get the number of rows. 212 Public method to get the number of rows.
213 213
214 @param parent index of parent item (QModelIndex) 214 @param parent index of parent item (QModelIndex)
215 @return number of rows (integer) 215 @return number of rows (integer)
216 """ 216 """
217 if parent is None: 217 if parent is None:
218 parent = QModelIndex() 218 parent = QModelIndex()
219 219
220 # Only the first column should have children 220 # Only the first column should have children
221 if parent.column() > 0: 221 if parent.column() > 0:
222 return 0 222 return 0
223 223
224 if not parent.isValid(): 224 if not parent.isValid():
225 parentItem = self.rootItem 225 parentItem = self.rootItem
226 else: 226 else:
227 parentItem = parent.internalPointer() 227 parentItem = parent.internalPointer()
228 if not parentItem.isPopulated(): # lazy population 228 if not parentItem.isPopulated(): # lazy population
229 self.populateItem(parentItem) 229 self.populateItem(parentItem)
230 230
231 return parentItem.childCount() 231 return parentItem.childCount()
232 232
233 def hasChildren(self, parent=None): 233 def hasChildren(self, parent=None):
234 """ 234 """
235 Public method to check for the presence of child items. 235 Public method to check for the presence of child items.
236 236
237 We always return True for normal items in order to do lazy 237 We always return True for normal items in order to do lazy
238 population of the tree. 238 population of the tree.
239 239
240 @param parent index of parent item (QModelIndex) 240 @param parent index of parent item (QModelIndex)
241 @return flag indicating the presence of child items (boolean) 241 @return flag indicating the presence of child items (boolean)
242 """ 242 """
243 if parent is None: 243 if parent is None:
244 parent = QModelIndex() 244 parent = QModelIndex()
245 245
246 # Only the first column should have children 246 # Only the first column should have children
247 if parent.column() > 0: 247 if parent.column() > 0:
248 return 0 248 return 0
249 249
250 if not parent.isValid(): 250 if not parent.isValid():
251 return self.rootItem.childCount() > 0 251 return self.rootItem.childCount() > 0
252 252
253 if parent.internalPointer().isLazyPopulated(): 253 if parent.internalPointer().isLazyPopulated():
254 return True 254 return True
255 else: 255 else:
256 return parent.internalPointer().childCount() > 0 256 return parent.internalPointer().childCount() > 0
257 257
260 Public method to clear the model. 260 Public method to clear the model.
261 """ 261 """
262 self.beginResetModel() 262 self.beginResetModel()
263 self.rootItem.removeChildren() 263 self.rootItem.removeChildren()
264 self.endResetModel() 264 self.endResetModel()
265 265
266 def item(self, index): 266 def item(self, index):
267 """ 267 """
268 Public method to get a reference to an item. 268 Public method to get a reference to an item.
269 269
270 @param index index of the data to retrieve (QModelIndex) 270 @param index index of the data to retrieve (QModelIndex)
271 @return requested item reference (BrowserItem) 271 @return requested item reference (BrowserItem)
272 """ 272 """
273 if not index.isValid(): 273 if not index.isValid():
274 return None 274 return None
275 275
276 return index.internalPointer() 276 return index.internalPointer()
277 277
278 def _addWatchedItem(self, itm): 278 def _addWatchedItem(self, itm):
279 """ 279 """
280 Protected method to watch an item. 280 Protected method to watch an item.
281 281
282 @param itm item to be watched (BrowserDirectoryItem) 282 @param itm item to be watched (BrowserDirectoryItem)
283 """ 283 """
284 if isinstance(itm, BrowserDirectoryItem): 284 if isinstance(itm, BrowserDirectoryItem):
285 dirName = itm.dirName() 285 dirName = itm.dirName()
286 if ( 286 if (
287 dirName != "" and 287 dirName != ""
288 not dirName.startswith("//") and 288 and not dirName.startswith("//")
289 not dirName.startswith("\\\\") 289 and not dirName.startswith("\\\\")
290 ): 290 ):
291 if dirName not in self.watcher.directories(): 291 if dirName not in self.watcher.directories():
292 self.watcher.addPath(dirName) 292 self.watcher.addPath(dirName)
293 if dirName in self.watchedItems: 293 if dirName in self.watchedItems:
294 if itm not in self.watchedItems[dirName]: 294 if itm not in self.watchedItems[dirName]:
295 self.watchedItems[dirName].append(itm) 295 self.watchedItems[dirName].append(itm)
296 else: 296 else:
297 self.watchedItems[dirName] = [itm] 297 self.watchedItems[dirName] = [itm]
298 298
299 def _removeWatchedItem(self, itm): 299 def _removeWatchedItem(self, itm):
300 """ 300 """
301 Protected method to remove a watched item. 301 Protected method to remove a watched item.
302 302
303 @param itm item to be removed (BrowserDirectoryItem) 303 @param itm item to be removed (BrowserDirectoryItem)
304 """ 304 """
305 if isinstance(itm, BrowserDirectoryItem): 305 if isinstance(itm, BrowserDirectoryItem):
306 dirName = itm.dirName() 306 dirName = itm.dirName()
307 if dirName in self.watchedItems: 307 if dirName in self.watchedItems:
308 if itm in self.watchedItems[dirName]: 308 if itm in self.watchedItems[dirName]:
309 self.watchedItems[dirName].remove(itm) 309 self.watchedItems[dirName].remove(itm)
310 if len(self.watchedItems[dirName]) == 0: 310 if len(self.watchedItems[dirName]) == 0:
311 del self.watchedItems[dirName] 311 del self.watchedItems[dirName]
312 self.watcher.removePath(dirName) 312 self.watcher.removePath(dirName)
313 313
314 def directoryChanged(self, path): 314 def directoryChanged(self, path):
315 """ 315 """
316 Public slot to handle the directoryChanged signal of the watcher. 316 Public slot to handle the directoryChanged signal of the watcher.
317 317
318 @param path path of the directory (string) 318 @param path path of the directory (string)
319 """ 319 """
320 if path not in self.watchedItems: 320 if path not in self.watchedItems:
321 # just ignore the situation we don't have a reference to the item 321 # just ignore the situation we don't have a reference to the item
322 return 322 return
323 323
324 dirFilter = QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot 324 dirFilter = QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot
325 325
326 for itm in self.watchedItems[path]: 326 for itm in self.watchedItems[path]:
327 oldCnt = itm.childCount() 327 oldCnt = itm.childCount()
328 328
329 qdir = QDir(itm.dirName()) 329 qdir = QDir(itm.dirName())
330 330
331 entryInfoList = qdir.entryInfoList(dirFilter) 331 entryInfoList = qdir.entryInfoList(dirFilter)
332 332
333 # step 1: check for new entries 333 # step 1: check for new entries
334 children = itm.children() 334 children = itm.children()
335 for f in entryInfoList: 335 for f in entryInfoList:
336 fpath = Utilities.toNativeSeparators(f.absoluteFilePath()) 336 fpath = Utilities.toNativeSeparators(f.absoluteFilePath())
337 childFound = False 337 childFound = False
340 childFound = True 340 childFound = True
341 children.remove(child) 341 children.remove(child)
342 break 342 break
343 if childFound: 343 if childFound:
344 continue 344 continue
345 345
346 cnt = itm.childCount() 346 cnt = itm.childCount()
347 self.beginInsertRows( 347 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt)
348 self.createIndex(itm.row(), 0, itm), cnt, cnt)
349 node = ( 348 node = (
350 BrowserDirectoryItem( 349 BrowserDirectoryItem(
351 itm, 350 itm, Utilities.toNativeSeparators(f.absoluteFilePath()), False
352 Utilities.toNativeSeparators(f.absoluteFilePath()), 351 )
353 False) 352 if f.isDir()
354 if f.isDir() else 353 else BrowserFileItem(
355 BrowserFileItem( 354 itm, Utilities.toNativeSeparators(f.absoluteFilePath())
356 itm, 355 )
357 Utilities.toNativeSeparators(f.absoluteFilePath()))
358 ) 356 )
359 self._addItem(node, itm) 357 self._addItem(node, itm)
360 self.endInsertRows() 358 self.endInsertRows()
361 359
362 # step 2: check for removed entries 360 # step 2: check for removed entries
363 if len(entryInfoList) != itm.childCount(): 361 if len(entryInfoList) != itm.childCount():
364 for row in range(oldCnt - 1, -1, -1): 362 for row in range(oldCnt - 1, -1, -1):
365 child = itm.child(row) 363 child = itm.child(row)
366 childname = Utilities.fromNativeSeparators(child.name()) 364 childname = Utilities.fromNativeSeparators(child.name())
370 entryFound = True 368 entryFound = True
371 entryInfoList.remove(f) 369 entryInfoList.remove(f)
372 break 370 break
373 if entryFound: 371 if entryFound:
374 continue 372 continue
375 373
376 self._removeWatchedItem(child) 374 self._removeWatchedItem(child)
377 self.beginRemoveRows( 375 self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row)
378 self.createIndex(itm.row(), 0, itm), row, row)
379 itm.removeChild(child) 376 itm.removeChild(child)
380 self.endRemoveRows() 377 self.endRemoveRows()
381 378
382 def __populateModel(self): 379 def __populateModel(self):
383 """ 380 """
384 Private method to populate the browser model. 381 Private method to populate the browser model.
385 """ 382 """
386 self.toplevelDirs = [] 383 self.toplevelDirs = []
387 tdp = Preferences.getSettings().value('BrowserModel/ToplevelDirs') 384 tdp = Preferences.getSettings().value("BrowserModel/ToplevelDirs")
388 if tdp: 385 if tdp:
389 self.toplevelDirs = tdp 386 self.toplevelDirs = tdp
390 else: 387 else:
391 self.toplevelDirs.append( 388 self.toplevelDirs.append(Utilities.toNativeSeparators(QDir.homePath()))
392 Utilities.toNativeSeparators(QDir.homePath()))
393 for d in QDir.drives(): 389 for d in QDir.drives():
394 self.toplevelDirs.append(Utilities.toNativeSeparators( 390 self.toplevelDirs.append(
395 d.absoluteFilePath())) 391 Utilities.toNativeSeparators(d.absoluteFilePath())
396 392 )
393
397 for d in self.toplevelDirs: 394 for d in self.toplevelDirs:
398 itm = BrowserDirectoryItem(self.rootItem, d) 395 itm = BrowserDirectoryItem(self.rootItem, d)
399 self._addItem(itm, self.rootItem) 396 self._addItem(itm, self.rootItem)
400 397
401 def interpreterChanged(self, interpreter): 398 def interpreterChanged(self, interpreter):
402 """ 399 """
403 Public method to handle a change of the debug client's interpreter. 400 Public method to handle a change of the debug client's interpreter.
404 401
405 @param interpreter interpreter of the debug client (string) 402 @param interpreter interpreter of the debug client (string)
406 """ 403 """
407 if interpreter and "python" in interpreter.lower(): 404 if interpreter and "python" in interpreter.lower():
408 if interpreter.endswith("w.exe"): 405 if interpreter.endswith("w.exe"):
409 interpreter = interpreter.replace("w.exe", ".exe") 406 interpreter = interpreter.replace("w.exe", ".exe")
410 if self.__sysPathInterpreter != interpreter: 407 if self.__sysPathInterpreter != interpreter:
411 self.__sysPathInterpreter = interpreter 408 self.__sysPathInterpreter = interpreter
412 # step 1: remove sys.path entry 409 # step 1: remove sys.path entry
413 if self.__sysPathItem is not None: 410 if self.__sysPathItem is not None:
414 self.beginRemoveRows( 411 self.beginRemoveRows(
415 QModelIndex(), self.__sysPathItem.row(), 412 QModelIndex(),
416 self.__sysPathItem.row()) 413 self.__sysPathItem.row(),
414 self.__sysPathItem.row(),
415 )
417 self.rootItem.removeChild(self.__sysPathItem) 416 self.rootItem.removeChild(self.__sysPathItem)
418 self.endRemoveRows() 417 self.endRemoveRows()
419 self.__sysPathItem = None 418 self.__sysPathItem = None
420 419
421 if self.__sysPathInterpreter: 420 if self.__sysPathInterpreter:
422 # step 2: add a new one 421 # step 2: add a new one
423 self.__sysPathItem = BrowserSysPathItem(self.rootItem) 422 self.__sysPathItem = BrowserSysPathItem(self.rootItem)
424 self.addItem(self.__sysPathItem) 423 self.addItem(self.__sysPathItem)
425 else: 424 else:
426 # remove sys.path entry 425 # remove sys.path entry
427 if self.__sysPathItem is not None: 426 if self.__sysPathItem is not None:
428 self.beginRemoveRows( 427 self.beginRemoveRows(
429 QModelIndex(), self.__sysPathItem.row(), 428 QModelIndex(), self.__sysPathItem.row(), self.__sysPathItem.row()
430 self.__sysPathItem.row()) 429 )
431 self.rootItem.removeChild(self.__sysPathItem) 430 self.rootItem.removeChild(self.__sysPathItem)
432 self.endRemoveRows() 431 self.endRemoveRows()
433 self.__sysPathItem = None 432 self.__sysPathItem = None
434 self.__sysPathInterpreter = "" 433 self.__sysPathInterpreter = ""
435 434
436 def programChange(self, dirname): 435 def programChange(self, dirname):
437 """ 436 """
438 Public method to change the entry for the directory of file being 437 Public method to change the entry for the directory of file being
439 debugged. 438 debugged.
440 439
441 @param dirname name of the directory containing the file (string) 440 @param dirname name of the directory containing the file (string)
442 """ 441 """
443 if self.progDir: 442 if self.progDir:
444 if dirname == self.progDir.dirName(): 443 if dirname == self.progDir.dirName():
445 return 444 return
446 445
447 # remove old entry 446 # remove old entry
448 self._removeWatchedItem(self.progDir) 447 self._removeWatchedItem(self.progDir)
449 self.beginRemoveRows( 448 self.beginRemoveRows(QModelIndex(), self.progDir.row(), self.progDir.row())
450 QModelIndex(), self.progDir.row(), self.progDir.row())
451 self.rootItem.removeChild(self.progDir) 449 self.rootItem.removeChild(self.progDir)
452 self.endRemoveRows() 450 self.endRemoveRows()
453 self.progDir = None 451 self.progDir = None
454 452
455 itm = BrowserDirectoryItem(self.rootItem, dirname) 453 itm = BrowserDirectoryItem(self.rootItem, dirname)
456 self.addItem(itm) 454 self.addItem(itm)
457 self.progDir = itm 455 self.progDir = itm
458 456
459 def addTopLevelDir(self, dirname): 457 def addTopLevelDir(self, dirname):
460 """ 458 """
461 Public method to add a new toplevel directory. 459 Public method to add a new toplevel directory.
462 460
463 @param dirname name of the new toplevel directory (string) 461 @param dirname name of the new toplevel directory (string)
464 """ 462 """
465 if dirname not in self.toplevelDirs: 463 if dirname not in self.toplevelDirs:
466 itm = BrowserDirectoryItem(self.rootItem, dirname) 464 itm = BrowserDirectoryItem(self.rootItem, dirname)
467 self.addItem(itm) 465 self.addItem(itm)
468 self.toplevelDirs.append(itm.dirName()) 466 self.toplevelDirs.append(itm.dirName())
469 467
470 def removeToplevelDir(self, index): 468 def removeToplevelDir(self, index):
471 """ 469 """
472 Public method to remove a toplevel directory. 470 Public method to remove a toplevel directory.
473 471
474 @param index index of the toplevel directory to be removed 472 @param index index of the toplevel directory to be removed
475 (QModelIndex) 473 (QModelIndex)
476 """ 474 """
477 if not index.isValid(): 475 if not index.isValid():
478 return 476 return
479 477
480 item = index.internalPointer() 478 item = index.internalPointer()
481 self.beginRemoveRows(index.parent(), index.row(), index.row()) 479 self.beginRemoveRows(index.parent(), index.row(), index.row())
482 self.rootItem.removeChild(item) 480 self.rootItem.removeChild(item)
483 self.endRemoveRows() 481 self.endRemoveRows()
484 482
485 self.toplevelDirs.remove(item.dirName()) 483 self.toplevelDirs.remove(item.dirName())
486 self._removeWatchedItem(item) 484 self._removeWatchedItem(item)
487 485
488 def saveToplevelDirs(self): 486 def saveToplevelDirs(self):
489 """ 487 """
490 Public slot to save the toplevel directories. 488 Public slot to save the toplevel directories.
491 """ 489 """
492 Preferences.getSettings().setValue( 490 Preferences.getSettings().setValue(
493 'BrowserModel/ToplevelDirs', self.toplevelDirs) 491 "BrowserModel/ToplevelDirs", self.toplevelDirs
494 492 )
493
495 def _addItem(self, itm, parentItem): 494 def _addItem(self, itm, parentItem):
496 """ 495 """
497 Protected slot to add an item. 496 Protected slot to add an item.
498 497
499 @param itm reference to item to add (BrowserItem) 498 @param itm reference to item to add (BrowserItem)
500 @param parentItem reference to item to add to (BrowserItem) 499 @param parentItem reference to item to add to (BrowserItem)
501 """ 500 """
502 parentItem.appendChild(itm) 501 parentItem.appendChild(itm)
503 502
504 def addItem(self, itm, parent=None): 503 def addItem(self, itm, parent=None):
505 """ 504 """
506 Public slot to add an item. 505 Public slot to add an item.
507 506
508 @param itm item to add (BrowserItem) 507 @param itm item to add (BrowserItem)
509 @param parent index of parent item (QModelIndex) 508 @param parent index of parent item (QModelIndex)
510 """ 509 """
511 if parent is None: 510 if parent is None:
512 parent = QModelIndex() 511 parent = QModelIndex()
513 512
514 parentItem = ( 513 parentItem = parent.internalPointer() if parent.isValid() else self.rootItem
515 parent.internalPointer() 514
516 if parent.isValid() else
517 self.rootItem
518 )
519
520 cnt = parentItem.childCount() 515 cnt = parentItem.childCount()
521 self.beginInsertRows(parent, cnt, cnt) 516 self.beginInsertRows(parent, cnt, cnt)
522 self._addItem(itm, parentItem) 517 self._addItem(itm, parentItem)
523 self.endInsertRows() 518 self.endInsertRows()
524 519
525 def populateItem(self, parentItem, repopulate=False): 520 def populateItem(self, parentItem, repopulate=False):
526 """ 521 """
527 Public method to populate an item's subtree. 522 Public method to populate an item's subtree.
528 523
529 @param parentItem reference to the item to be populated 524 @param parentItem reference to the item to be populated
530 @param repopulate flag indicating a repopulation (boolean) 525 @param repopulate flag indicating a repopulation (boolean)
531 """ 526 """
532 if parentItem.type() == BrowserItemDirectory: 527 if parentItem.type() == BrowserItemDirectory:
533 self.populateDirectoryItem(parentItem, repopulate) 528 self.populateDirectoryItem(parentItem, repopulate)
543 self.populateClassAttributesItem(parentItem, repopulate) 538 self.populateClassAttributesItem(parentItem, repopulate)
544 539
545 def populateDirectoryItem(self, parentItem, repopulate=False): 540 def populateDirectoryItem(self, parentItem, repopulate=False):
546 """ 541 """
547 Public method to populate a directory item's subtree. 542 Public method to populate a directory item's subtree.
548 543
549 @param parentItem reference to the directory item to be populated 544 @param parentItem reference to the directory item to be populated
550 @param repopulate flag indicating a repopulation (boolean) 545 @param repopulate flag indicating a repopulation (boolean)
551 """ 546 """
552 self._addWatchedItem(parentItem) 547 self._addWatchedItem(parentItem)
553 548
554 qdir = QDir(parentItem.dirName()) 549 qdir = QDir(parentItem.dirName())
555 550
556 dirFilter = (QDir.Filter.AllEntries | 551 dirFilter = QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot
557 QDir.Filter.NoDotAndDotDot)
558 entryInfoList = qdir.entryInfoList(dirFilter) 552 entryInfoList = qdir.entryInfoList(dirFilter)
559 if len(entryInfoList) > 0: 553 if len(entryInfoList) > 0:
560 if repopulate: 554 if repopulate:
561 self.beginInsertRows( 555 self.beginInsertRows(
562 self.createIndex(parentItem.row(), 0, parentItem), 556 self.createIndex(parentItem.row(), 0, parentItem),
563 0, len(entryInfoList) - 1) 557 0,
558 len(entryInfoList) - 1,
559 )
564 for f in entryInfoList: 560 for f in entryInfoList:
565 if f.isDir(): 561 if f.isDir():
566 node = BrowserDirectoryItem( 562 node = BrowserDirectoryItem(
567 parentItem, 563 parentItem,
568 Utilities.toNativeSeparators(f.absoluteFilePath()), 564 Utilities.toNativeSeparators(f.absoluteFilePath()),
569 False) 565 False,
566 )
570 else: 567 else:
571 fileFilters = Preferences.getUI( 568 fileFilters = Preferences.getUI("BrowsersFileFilters").split(";")
572 "BrowsersFileFilters").split(";")
573 if fileFilters: 569 if fileFilters:
574 fn = f.fileName() 570 fn = f.fileName()
575 if any(fnmatch.fnmatch(fn, ff.strip()) 571 if any(fnmatch.fnmatch(fn, ff.strip()) for ff in fileFilters):
576 for ff in fileFilters):
577 continue 572 continue
578 node = BrowserFileItem( 573 node = BrowserFileItem(
579 parentItem, 574 parentItem, Utilities.toNativeSeparators(f.absoluteFilePath())
580 Utilities.toNativeSeparators(f.absoluteFilePath())) 575 )
581 self._addItem(node, parentItem) 576 self._addItem(node, parentItem)
582 if repopulate: 577 if repopulate:
583 self.endInsertRows() 578 self.endInsertRows()
584 579
585 def populateSysPathItem(self, parentItem, repopulate=False): 580 def populateSysPathItem(self, parentItem, repopulate=False):
586 """ 581 """
587 Public method to populate a sys.path item's subtree. 582 Public method to populate a sys.path item's subtree.
588 583
589 @param parentItem reference to the sys.path item to be populated 584 @param parentItem reference to the sys.path item to be populated
590 @param repopulate flag indicating a repopulation (boolean) 585 @param repopulate flag indicating a repopulation (boolean)
591 """ 586 """
592 if self.__sysPathInterpreter: 587 if self.__sysPathInterpreter:
593 script = "import sys, json; print(json.dumps(sys.path))" 588 script = "import sys, json; print(json.dumps(sys.path))"
594 proc = QProcess() 589 proc = QProcess()
595 proc.start(self.__sysPathInterpreter, ["-c", script]) 590 proc.start(self.__sysPathInterpreter, ["-c", script])
596 finished = proc.waitForFinished(3000) 591 finished = proc.waitForFinished(3000)
597 if finished: 592 if finished:
598 procOutput = str(proc.readAllStandardOutput(), 593 procOutput = str(
599 Preferences.getSystem("IOEncoding"), 594 proc.readAllStandardOutput(),
600 'replace') 595 Preferences.getSystem("IOEncoding"),
596 "replace",
597 )
601 syspath = [p for p in json.loads(procOutput) if p] 598 syspath = [p for p in json.loads(procOutput) if p]
602 if len(syspath) > 0: 599 if len(syspath) > 0:
603 if repopulate: 600 if repopulate:
604 self.beginInsertRows( 601 self.beginInsertRows(
605 self.createIndex(parentItem.row(), 0, parentItem), 602 self.createIndex(parentItem.row(), 0, parentItem),
606 0, len(syspath) - 1) 603 0,
604 len(syspath) - 1,
605 )
607 for p in syspath: 606 for p in syspath:
608 node = ( 607 node = (
609 BrowserDirectoryItem(parentItem, p) 608 BrowserDirectoryItem(parentItem, p)
610 if os.path.isdir(p) else 609 if os.path.isdir(p)
611 BrowserFileItem(parentItem, p) 610 else BrowserFileItem(parentItem, p)
612 ) 611 )
613 self._addItem(node, parentItem) 612 self._addItem(node, parentItem)
614 if repopulate: 613 if repopulate:
615 self.endInsertRows() 614 self.endInsertRows()
616 else: 615 else:
617 proc.kill() 616 proc.kill()
618 617
619 def populateFileItem(self, parentItem, repopulate=False): 618 def populateFileItem(self, parentItem, repopulate=False):
620 """ 619 """
621 Public method to populate a file item's subtree. 620 Public method to populate a file item's subtree.
622 621
623 @param parentItem reference to the file item to be populated 622 @param parentItem reference to the file item to be populated
624 @param repopulate flag indicating a repopulation (boolean) 623 @param repopulate flag indicating a repopulation (boolean)
625 """ 624 """
626 import Utilities.ClassBrowsers 625 import Utilities.ClassBrowsers
626
627 moduleName = parentItem.moduleName() 627 moduleName = parentItem.moduleName()
628 fileName = parentItem.fileName() 628 fileName = parentItem.fileName()
629 try: 629 try:
630 dictionary = Utilities.ClassBrowsers.readmodule( 630 dictionary = Utilities.ClassBrowsers.readmodule(
631 moduleName, [parentItem.dirName()], 631 moduleName,
632 parentItem.isPython3File() or parentItem.isCythonFile()) 632 [parentItem.dirName()],
633 parentItem.isPython3File() or parentItem.isCythonFile(),
634 )
633 except ImportError: 635 except ImportError:
634 return 636 return
635 637
636 keys = list(dictionary.keys()) 638 keys = list(dictionary.keys())
637 if len(keys) > 0: 639 if len(keys) > 0:
638 if repopulate: 640 if repopulate:
639 last = len(keys) - 1 641 last = len(keys) - 1
640 if ( 642 if "@@Coding@@" in keys and not Preferences.getUI("BrowserShowCoding"):
641 "@@Coding@@" in keys and
642 not Preferences.getUI("BrowserShowCoding")
643 ):
644 last -= 1 643 last -= 1
645 self.beginInsertRows( 644 self.beginInsertRows(
646 self.createIndex(parentItem.row(), 0, parentItem), 645 self.createIndex(parentItem.row(), 0, parentItem), 0, last
647 0, last) 646 )
648 647
649 for key in keys: 648 for key in keys:
650 if key.startswith("@@"): 649 if key.startswith("@@"):
651 # special treatment done later 650 # special treatment done later
652 continue 651 continue
653 cl = dictionary[key] 652 cl = dictionary[key]
656 node = BrowserClassItem(parentItem, cl, fileName) 655 node = BrowserClassItem(parentItem, cl, fileName)
657 self._addItem(node, parentItem) 656 self._addItem(node, parentItem)
658 if "@@Coding@@" in keys and Preferences.getUI("BrowserShowCoding"): 657 if "@@Coding@@" in keys and Preferences.getUI("BrowserShowCoding"):
659 node = BrowserCodingItem( 658 node = BrowserCodingItem(
660 parentItem, 659 parentItem,
661 QCoreApplication.translate("BrowserModel", "Coding: {0}") 660 QCoreApplication.translate("BrowserModel", "Coding: {0}").format(
662 .format(dictionary["@@Coding@@"].coding), 661 dictionary["@@Coding@@"].coding
663 dictionary["@@Coding@@"].linenumber) 662 ),
663 dictionary["@@Coding@@"].linenumber,
664 )
664 self._addItem(node, parentItem) 665 self._addItem(node, parentItem)
665 if "@@Globals@@" in keys: 666 if "@@Globals@@" in keys:
666 node = BrowserGlobalsItem( 667 node = BrowserGlobalsItem(
667 parentItem, 668 parentItem,
668 dictionary["@@Globals@@"].globals, 669 dictionary["@@Globals@@"].globals,
669 QCoreApplication.translate("BrowserModel", "Globals")) 670 QCoreApplication.translate("BrowserModel", "Globals"),
671 )
670 self._addItem(node, parentItem) 672 self._addItem(node, parentItem)
671 if "@@Import@@" in keys or "@@ImportFrom@@" in keys: 673 if "@@Import@@" in keys or "@@ImportFrom@@" in keys:
672 node = BrowserImportsItem( 674 node = BrowserImportsItem(
673 parentItem, 675 parentItem, QCoreApplication.translate("BrowserModel", "Imports")
674 QCoreApplication.translate("BrowserModel", "Imports")) 676 )
675 self._addItem(node, parentItem) 677 self._addItem(node, parentItem)
676 if "@@Import@@" in keys: 678 if "@@Import@@" in keys:
677 for importedModule in ( 679 for importedModule in (
678 dictionary["@@Import@@"].getImports().values() 680 dictionary["@@Import@@"].getImports().values()
679 ): 681 ):
680 m_node = BrowserImportItem( 682 m_node = BrowserImportItem(
681 node, 683 node,
682 importedModule.importedModuleName, 684 importedModule.importedModuleName,
683 importedModule.file, 685 importedModule.file,
684 importedModule.linenos) 686 importedModule.linenos,
687 )
685 self._addItem(m_node, node) 688 self._addItem(m_node, node)
686 for importedName, linenos in ( 689 for (
687 importedModule.importedNames.items() 690 importedName,
688 ): 691 linenos,
692 ) in importedModule.importedNames.items():
689 mn_node = BrowserImportItem( 693 mn_node = BrowserImportItem(
690 m_node, 694 m_node,
691 importedName, 695 importedName,
692 importedModule.file, 696 importedModule.file,
693 linenos, 697 linenos,
694 isModule=False) 698 isModule=False,
699 )
695 self._addItem(mn_node, m_node) 700 self._addItem(mn_node, m_node)
696 701
697 if repopulate: 702 if repopulate:
698 self.endInsertRows() 703 self.endInsertRows()
699 704
700 parentItem._populated = True 705 parentItem._populated = True
701 if ( 706 if (
702 parentItem.type_ == BrowserItemFile and 707 parentItem.type_ == BrowserItemFile
703 fileName not in self.watchedFileItems 708 and fileName not in self.watchedFileItems
704 ): 709 ):
705 # watch the file only in the file browser not the project viewer 710 # watch the file only in the file browser not the project viewer
706 self.watcher.addPath(fileName) 711 self.watcher.addPath(fileName)
707 self.watchedFileItems[fileName] = parentItem 712 self.watchedFileItems[fileName] = parentItem
708 713
709 def repopulateFileItem(self, itm): 714 def repopulateFileItem(self, itm):
710 """ 715 """
711 Public method to repopulate a file item. 716 Public method to repopulate a file item.
712 717
713 @param itm reference to the item to be repopulated 718 @param itm reference to the item to be repopulated
714 @type BrowserFileItem 719 @type BrowserFileItem
715 """ 720 """
716 if isinstance(itm, BrowserFileItem) and itm.isLazyPopulated(): 721 if isinstance(itm, BrowserFileItem) and itm.isLazyPopulated():
717 if not itm.isPopulated(): 722 if not itm.isPopulated():
718 # item is not populated yet, nothing to do 723 # item is not populated yet, nothing to do
719 return 724 return
720 725
721 if itm.childCount(): 726 if itm.childCount():
722 index = self.createIndex(itm.row(), 0, itm) 727 index = self.createIndex(itm.row(), 0, itm)
723 self.beginRemoveRows(index, 0, itm.childCount() - 1) 728 self.beginRemoveRows(index, 0, itm.childCount() - 1)
724 itm.removeChildren() 729 itm.removeChildren()
725 self.endRemoveRows() 730 self.endRemoveRows()
726 731
727 self.populateFileItem(itm, True) 732 self.populateFileItem(itm, True)
728 733
729 def fileChanged(self, fileName): 734 def fileChanged(self, fileName):
730 """ 735 """
731 Public method to react upon file changes. 736 Public method to react upon file changes.
732 737
733 @param fileName path of the changed file 738 @param fileName path of the changed file
734 @type str 739 @type str
735 """ 740 """
736 if fileName in self.watchedFileItems: 741 if fileName in self.watchedFileItems:
737 if os.path.exists(fileName): 742 if os.path.exists(fileName):
742 del self.watchedFileItems[fileName] 747 del self.watchedFileItems[fileName]
743 748
744 def populateClassItem(self, parentItem, repopulate=False): 749 def populateClassItem(self, parentItem, repopulate=False):
745 """ 750 """
746 Public method to populate a class item's subtree. 751 Public method to populate a class item's subtree.
747 752
748 @param parentItem reference to the class item to be populated 753 @param parentItem reference to the class item to be populated
749 @param repopulate flag indicating a repopulation (boolean) 754 @param repopulate flag indicating a repopulation (boolean)
750 """ 755 """
751 cl = parentItem.classObject() 756 cl = parentItem.classObject()
752 file_ = parentItem.fileName() 757 file_ = parentItem.fileName()
753 758
754 if cl is None: 759 if cl is None:
755 return 760 return
756 761
757 # build sorted list of names 762 # build sorted list of names
758 keys = [] 763 keys = []
759 for name in list(cl.classes.keys()): 764 for name in list(cl.classes.keys()):
760 keys.append((name, 'c')) 765 keys.append((name, "c"))
761 for name in list(cl.methods.keys()): 766 for name in list(cl.methods.keys()):
762 keys.append((name, 'm')) 767 keys.append((name, "m"))
763 768
764 if len(cl.attributes): 769 if len(cl.attributes):
765 node = BrowserClassAttributesItem( 770 node = BrowserClassAttributesItem(
766 parentItem, cl.attributes, 771 parentItem,
767 QCoreApplication.translate("BrowserModel", "Attributes")) 772 cl.attributes,
773 QCoreApplication.translate("BrowserModel", "Attributes"),
774 )
768 if repopulate: 775 if repopulate:
769 self.addItem( 776 self.addItem(node, self.createIndex(parentItem.row(), 0, parentItem))
770 node, self.createIndex(parentItem.row(), 0, parentItem))
771 else: 777 else:
772 self._addItem(node, parentItem) 778 self._addItem(node, parentItem)
773 779
774 if len(cl.globals): 780 if len(cl.globals):
775 node = BrowserClassAttributesItem( 781 node = BrowserClassAttributesItem(
776 parentItem, cl.globals, 782 parentItem,
783 cl.globals,
777 QCoreApplication.translate("BrowserModel", "Class Attributes"), 784 QCoreApplication.translate("BrowserModel", "Class Attributes"),
778 True) 785 True,
786 )
779 if repopulate: 787 if repopulate:
780 self.addItem( 788 self.addItem(node, self.createIndex(parentItem.row(), 0, parentItem))
781 node, self.createIndex(parentItem.row(), 0, parentItem))
782 else: 789 else:
783 self._addItem(node, parentItem) 790 self._addItem(node, parentItem)
784 791
785 if len(keys) > 0: 792 if len(keys) > 0:
786 if repopulate: 793 if repopulate:
787 self.beginInsertRows( 794 self.beginInsertRows(
788 self.createIndex(parentItem.row(), 0, parentItem), 795 self.createIndex(parentItem.row(), 0, parentItem), 0, len(keys) - 1
789 0, len(keys) - 1) 796 )
790 for key, kind in keys: 797 for key, kind in keys:
791 if kind == 'c': 798 if kind == "c":
792 node = BrowserClassItem(parentItem, cl.classes[key], file_) 799 node = BrowserClassItem(parentItem, cl.classes[key], file_)
793 elif kind == 'm': 800 elif kind == "m":
794 node = BrowserMethodItem(parentItem, cl.methods[key], 801 node = BrowserMethodItem(parentItem, cl.methods[key], file_)
795 file_)
796 self._addItem(node, parentItem) 802 self._addItem(node, parentItem)
797 if repopulate: 803 if repopulate:
798 self.endInsertRows() 804 self.endInsertRows()
799 805
800 def populateMethodItem(self, parentItem, repopulate=False): 806 def populateMethodItem(self, parentItem, repopulate=False):
801 """ 807 """
802 Public method to populate a method item's subtree. 808 Public method to populate a method item's subtree.
803 809
804 @param parentItem reference to the method item to be populated 810 @param parentItem reference to the method item to be populated
805 @param repopulate flag indicating a repopulation (boolean) 811 @param repopulate flag indicating a repopulation (boolean)
806 """ 812 """
807 fn = parentItem.functionObject() 813 fn = parentItem.functionObject()
808 file_ = parentItem.fileName() 814 file_ = parentItem.fileName()
809 815
810 if fn is None: 816 if fn is None:
811 return 817 return
812 818
813 # build sorted list of names 819 # build sorted list of names
814 keys = [] 820 keys = []
815 for name in list(fn.classes.keys()): 821 for name in list(fn.classes.keys()):
816 keys.append((name, 'c')) 822 keys.append((name, "c"))
817 for name in list(fn.methods.keys()): 823 for name in list(fn.methods.keys()):
818 keys.append((name, 'm')) 824 keys.append((name, "m"))
819 825
820 if len(keys) > 0: 826 if len(keys) > 0:
821 if repopulate: 827 if repopulate:
822 self.beginInsertRows( 828 self.beginInsertRows(
823 self.createIndex(parentItem.row(), 0, parentItem), 829 self.createIndex(parentItem.row(), 0, parentItem), 0, len(keys) - 1
824 0, len(keys) - 1) 830 )
825 for key, kind in keys: 831 for key, kind in keys:
826 if kind == 'c': 832 if kind == "c":
827 node = BrowserClassItem(parentItem, fn.classes[key], file_) 833 node = BrowserClassItem(parentItem, fn.classes[key], file_)
828 elif kind == 'm': 834 elif kind == "m":
829 node = BrowserMethodItem(parentItem, fn.methods[key], 835 node = BrowserMethodItem(parentItem, fn.methods[key], file_)
830 file_)
831 self._addItem(node, parentItem) 836 self._addItem(node, parentItem)
832 if repopulate: 837 if repopulate:
833 self.endInsertRows() 838 self.endInsertRows()
834 839
835 def populateClassAttributesItem(self, parentItem, repopulate=False): 840 def populateClassAttributesItem(self, parentItem, repopulate=False):
836 """ 841 """
837 Public method to populate a class attributes item's subtree. 842 Public method to populate a class attributes item's subtree.
838 843
839 @param parentItem reference to the class attributes item to be 844 @param parentItem reference to the class attributes item to be
840 populated 845 populated
841 @param repopulate flag indicating a repopulation (boolean) 846 @param repopulate flag indicating a repopulation (boolean)
842 """ 847 """
843 classAttributes = parentItem.isClassAttributes() 848 classAttributes = parentItem.isClassAttributes()
844 attributes = parentItem.attributes() 849 attributes = parentItem.attributes()
845 if not attributes: 850 if not attributes:
846 return 851 return
847 852
848 keys = list(attributes.keys()) 853 keys = list(attributes.keys())
849 if len(keys) > 0: 854 if len(keys) > 0:
850 if repopulate: 855 if repopulate:
851 self.beginInsertRows( 856 self.beginInsertRows(
852 self.createIndex(parentItem.row(), 0, parentItem), 857 self.createIndex(parentItem.row(), 0, parentItem), 0, len(keys) - 1
853 0, len(keys) - 1) 858 )
854 for key in keys: 859 for key in keys:
855 node = BrowserClassAttributeItem(parentItem, attributes[key], 860 node = BrowserClassAttributeItem(
856 classAttributes) 861 parentItem, attributes[key], classAttributes
862 )
857 self._addItem(node, parentItem) 863 self._addItem(node, parentItem)
858 if repopulate: 864 if repopulate:
859 self.endInsertRows() 865 self.endInsertRows()
860 866
861 867
862 class BrowserItem: 868 class BrowserItem:
863 """ 869 """
864 Class implementing the data structure for browser items. 870 Class implementing the data structure for browser items.
865 """ 871 """
872
866 def __init__(self, parent, data): 873 def __init__(self, parent, data):
867 """ 874 """
868 Constructor 875 Constructor
869 876
870 @param parent reference to the parent item 877 @param parent reference to the parent item
871 @param data single data of the item 878 @param data single data of the item
872 """ 879 """
873 self.childItems = [] 880 self.childItems = []
874 881
875 self.parentItem = parent 882 self.parentItem = parent
876 self.itemData = [data] 883 self.itemData = [data]
877 self.type_ = BrowserItemRoot 884 self.type_ = BrowserItemRoot
878 self.icon = UI.PixmapCache.getIcon("empty") 885 self.icon = UI.PixmapCache.getIcon("empty")
879 self._populated = True 886 self._populated = True
880 self._lazyPopulation = False 887 self._lazyPopulation = False
881 self.symlink = False 888 self.symlink = False
882 889
883 def appendChild(self, child): 890 def appendChild(self, child):
884 """ 891 """
885 Public method to add a child to this item. 892 Public method to add a child to this item.
886 893
887 @param child reference to the child item to add (BrowserItem) 894 @param child reference to the child item to add (BrowserItem)
888 """ 895 """
889 self.childItems.append(child) 896 self.childItems.append(child)
890 self._populated = True 897 self._populated = True
891 898
892 def removeChild(self, child): 899 def removeChild(self, child):
893 """ 900 """
894 Public method to remove a child. 901 Public method to remove a child.
895 902
896 @param child reference to the child to remove (BrowserItem) 903 @param child reference to the child to remove (BrowserItem)
897 """ 904 """
898 self.childItems.remove(child) 905 self.childItems.remove(child)
899 906
900 def removeChildren(self): 907 def removeChildren(self):
901 """ 908 """
902 Public method to remove all children. 909 Public method to remove all children.
903 """ 910 """
904 self.childItems = [] 911 self.childItems = []
905 912
906 def child(self, row): 913 def child(self, row):
907 """ 914 """
908 Public method to get a child id. 915 Public method to get a child id.
909 916
910 @param row number of child to get the id of (integer) 917 @param row number of child to get the id of (integer)
911 @return reference to the child item (BrowserItem) 918 @return reference to the child item (BrowserItem)
912 """ 919 """
913 return self.childItems[row] 920 return self.childItems[row]
914 921
915 def children(self): 922 def children(self):
916 """ 923 """
917 Public method to get the ids of all child items. 924 Public method to get the ids of all child items.
918 925
919 @return references to all child items (list of BrowserItem) 926 @return references to all child items (list of BrowserItem)
920 """ 927 """
921 return self.childItems[:] 928 return self.childItems[:]
922 929
923 def childCount(self): 930 def childCount(self):
924 """ 931 """
925 Public method to get the number of available child items. 932 Public method to get the number of available child items.
926 933
927 @return number of child items (integer) 934 @return number of child items (integer)
928 """ 935 """
929 return len(self.childItems) 936 return len(self.childItems)
930 937
931 def columnCount(self): 938 def columnCount(self):
932 """ 939 """
933 Public method to get the number of available data items. 940 Public method to get the number of available data items.
934 941
935 @return number of data items (integer) 942 @return number of data items (integer)
936 """ 943 """
937 return len(self.itemData) 944 return len(self.itemData)
938 945
939 def data(self, column): 946 def data(self, column):
940 """ 947 """
941 Public method to get a specific data item. 948 Public method to get a specific data item.
942 949
943 @param column number of the requested data item (integer) 950 @param column number of the requested data item (integer)
944 @return stored data item 951 @return stored data item
945 """ 952 """
946 try: 953 try:
947 return self.itemData[column] 954 return self.itemData[column]
948 except IndexError: 955 except IndexError:
949 return "" 956 return ""
950 957
951 def parent(self): 958 def parent(self):
952 """ 959 """
953 Public method to get the reference to the parent item. 960 Public method to get the reference to the parent item.
954 961
955 @return reference to the parent item 962 @return reference to the parent item
956 """ 963 """
957 return self.parentItem 964 return self.parentItem
958 965
959 def row(self): 966 def row(self):
960 """ 967 """
961 Public method to get the row number of this item. 968 Public method to get the row number of this item.
962 969
963 @return row number (integer) 970 @return row number (integer)
964 """ 971 """
965 try: 972 try:
966 return self.parentItem.childItems.index(self) 973 return self.parentItem.childItems.index(self)
967 except ValueError: 974 except ValueError:
968 return 0 975 return 0
969 976
970 def type(self): 977 def type(self):
971 """ 978 """
972 Public method to get the item type. 979 Public method to get the item type.
973 980
974 @return type of the item 981 @return type of the item
975 """ 982 """
976 return self.type_ 983 return self.type_
977 984
978 def isPublic(self): 985 def isPublic(self):
979 """ 986 """
980 Public method returning the public visibility status. 987 Public method returning the public visibility status.
981 988
982 @return flag indicating public visibility (boolean) 989 @return flag indicating public visibility (boolean)
983 """ 990 """
984 return True 991 return True
985 992
986 def getIcon(self): 993 def getIcon(self):
987 """ 994 """
988 Public method to get the items icon. 995 Public method to get the items icon.
989 996
990 @return the icon (QIcon) 997 @return the icon (QIcon)
991 """ 998 """
992 return self.icon 999 return self.icon
993 1000
994 def isPopulated(self): 1001 def isPopulated(self):
995 """ 1002 """
996 Public method to chek, if this item is populated. 1003 Public method to chek, if this item is populated.
997 1004
998 @return population status (boolean) 1005 @return population status (boolean)
999 """ 1006 """
1000 return self._populated 1007 return self._populated
1001 1008
1002 def isLazyPopulated(self): 1009 def isLazyPopulated(self):
1003 """ 1010 """
1004 Public method to check, if this item should be populated lazyly. 1011 Public method to check, if this item should be populated lazyly.
1005 1012
1006 @return lazy population flag (boolean) 1013 @return lazy population flag (boolean)
1007 """ 1014 """
1008 return self._lazyPopulation 1015 return self._lazyPopulation
1009 1016
1010 def lessThan(self, other, column, order): 1017 def lessThan(self, other, column, order):
1011 """ 1018 """
1012 Public method to check, if the item is less than the other one. 1019 Public method to check, if the item is less than the other one.
1013 1020
1014 @param other reference to item to compare against (BrowserItem) 1021 @param other reference to item to compare against (BrowserItem)
1015 @param column column number to use for the comparison (integer) 1022 @param column column number to use for the comparison (integer)
1016 @param order sort order (Qt.SortOrder) (for special sorting) 1023 @param order sort order (Qt.SortOrder) (for special sorting)
1017 @return true, if this item is less than other (boolean) 1024 @return true, if this item is less than other (boolean)
1018 """ 1025 """
1019 try: 1026 try:
1020 return self.itemData[column] < other.itemData[column] 1027 return self.itemData[column] < other.itemData[column]
1021 except IndexError: 1028 except IndexError:
1022 return False 1029 return False
1023 1030
1024 def isSymlink(self): 1031 def isSymlink(self):
1025 """ 1032 """
1026 Public method to check, if the items is a symbolic link. 1033 Public method to check, if the items is a symbolic link.
1027 1034
1028 @return flag indicating a symbolic link (boolean) 1035 @return flag indicating a symbolic link (boolean)
1029 """ 1036 """
1030 return self.symlink 1037 return self.symlink
1031 1038
1032 1039
1033 class BrowserDirectoryItem(BrowserItem): 1040 class BrowserDirectoryItem(BrowserItem):
1034 """ 1041 """
1035 Class implementing the data structure for browser directory items. 1042 Class implementing the data structure for browser directory items.
1036 """ 1043 """
1044
1037 def __init__(self, parent, dinfo, full=True): 1045 def __init__(self, parent, dinfo, full=True):
1038 """ 1046 """
1039 Constructor 1047 Constructor
1040 1048
1041 @param parent parent item 1049 @param parent parent item
1042 @param dinfo dinfo is the string for the directory (string) 1050 @param dinfo dinfo is the string for the directory (string)
1043 @param full flag indicating full pathname should be displayed (boolean) 1051 @param full flag indicating full pathname should be displayed (boolean)
1044 """ 1052 """
1045 self._dirName = os.path.abspath(dinfo) 1053 self._dirName = os.path.abspath(dinfo)
1046 dn = self._dirName if full else os.path.basename(self._dirName) 1054 dn = self._dirName if full else os.path.basename(self._dirName)
1047 BrowserItem.__init__(self, parent, dn) 1055 BrowserItem.__init__(self, parent, dn)
1048 1056
1049 self.type_ = BrowserItemDirectory 1057 self.type_ = BrowserItemDirectory
1050 if ( 1058 if (
1051 not Utilities.isDrive(self._dirName) and 1059 not Utilities.isDrive(self._dirName)
1052 os.path.lexists(self._dirName) and 1060 and os.path.lexists(self._dirName)
1053 os.path.islink(self._dirName) 1061 and os.path.islink(self._dirName)
1054 ): 1062 ):
1055 self.symlink = True 1063 self.symlink = True
1056 self.icon = UI.PixmapCache.getSymlinkIcon("dirClosed") 1064 self.icon = UI.PixmapCache.getSymlinkIcon("dirClosed")
1057 else: 1065 else:
1058 self.icon = UI.PixmapCache.getIcon("dirClosed") 1066 self.icon = UI.PixmapCache.getIcon("dirClosed")
1060 self._lazyPopulation = True 1068 self._lazyPopulation = True
1061 1069
1062 def setName(self, dinfo, full=True): 1070 def setName(self, dinfo, full=True):
1063 """ 1071 """
1064 Public method to set the directory name. 1072 Public method to set the directory name.
1065 1073
1066 @param dinfo dinfo is the string for the directory (string) 1074 @param dinfo dinfo is the string for the directory (string)
1067 @param full flag indicating full pathname should be displayed (boolean) 1075 @param full flag indicating full pathname should be displayed (boolean)
1068 """ 1076 """
1069 self._dirName = os.path.abspath(dinfo) 1077 self._dirName = os.path.abspath(dinfo)
1070 dn = self._dirName if full else os.path.basename(self._dirName) 1078 dn = self._dirName if full else os.path.basename(self._dirName)
1071 self.itemData[0] = dn 1079 self.itemData[0] = dn
1072 1080
1073 def dirName(self): 1081 def dirName(self):
1074 """ 1082 """
1075 Public method returning the directory name. 1083 Public method returning the directory name.
1076 1084
1077 @return directory name (string) 1085 @return directory name (string)
1078 """ 1086 """
1079 return self._dirName 1087 return self._dirName
1080 1088
1081 def name(self): 1089 def name(self):
1082 """ 1090 """
1083 Public method to return the name of the item. 1091 Public method to return the name of the item.
1084 1092
1085 @return name of the item (string) 1093 @return name of the item (string)
1086 """ 1094 """
1087 return self._dirName 1095 return self._dirName
1088 1096
1089 def lessThan(self, other, column, order): 1097 def lessThan(self, other, column, order):
1090 """ 1098 """
1091 Public method to check, if the item is less than the other one. 1099 Public method to check, if the item is less than the other one.
1092 1100
1093 @param other reference to item to compare against (BrowserItem) 1101 @param other reference to item to compare against (BrowserItem)
1094 @param column column number to use for the comparison (integer) 1102 @param column column number to use for the comparison (integer)
1095 @param order sort order (Qt.SortOrder) (for special sorting) 1103 @param order sort order (Qt.SortOrder) (for special sorting)
1096 @return true, if this item is less than other (boolean) 1104 @return true, if this item is less than other (boolean)
1097 """ 1105 """
1098 if ( 1106 if issubclass(other.__class__, BrowserFileItem) and Preferences.getUI(
1099 issubclass(other.__class__, BrowserFileItem) and 1107 "BrowsersListFoldersFirst"
1100 Preferences.getUI("BrowsersListFoldersFirst")
1101 ): 1108 ):
1102 return order == Qt.SortOrder.AscendingOrder 1109 return order == Qt.SortOrder.AscendingOrder
1103 1110
1104 return BrowserItem.lessThan(self, other, column, order) 1111 return BrowserItem.lessThan(self, other, column, order)
1105 1112
1106 1113
1107 class BrowserSysPathItem(BrowserItem): 1114 class BrowserSysPathItem(BrowserItem):
1108 """ 1115 """
1109 Class implementing the data structure for browser sys.path items. 1116 Class implementing the data structure for browser sys.path items.
1110 """ 1117 """
1118
1111 def __init__(self, parent): 1119 def __init__(self, parent):
1112 """ 1120 """
1113 Constructor 1121 Constructor
1114 1122
1115 @param parent parent item 1123 @param parent parent item
1116 """ 1124 """
1117 BrowserItem.__init__(self, parent, "sys.path") 1125 BrowserItem.__init__(self, parent, "sys.path")
1118 1126
1119 self.type_ = BrowserItemSysPath 1127 self.type_ = BrowserItemSysPath
1120 self.icon = UI.PixmapCache.getIcon("filePython") 1128 self.icon = UI.PixmapCache.getIcon("filePython")
1121 self._populated = False 1129 self._populated = False
1122 self._lazyPopulation = True 1130 self._lazyPopulation = True
1123 1131
1124 def name(self): 1132 def name(self):
1125 """ 1133 """
1126 Public method to return the name of the item. 1134 Public method to return the name of the item.
1127 1135
1128 @return name of the item (string) 1136 @return name of the item (string)
1129 """ 1137 """
1130 return "sys.path" 1138 return "sys.path"
1131 1139
1132 1140
1133 class BrowserFileItem(BrowserItem): 1141 class BrowserFileItem(BrowserItem):
1134 """ 1142 """
1135 Class implementing the data structure for browser file items. 1143 Class implementing the data structure for browser file items.
1136 """ 1144 """
1145
1137 def __init__(self, parent, finfo, full=True, sourceLanguage=""): 1146 def __init__(self, parent, finfo, full=True, sourceLanguage=""):
1138 """ 1147 """
1139 Constructor 1148 Constructor
1140 1149
1141 @param parent parent item 1150 @param parent parent item
1142 @param finfo the string for the file (string) 1151 @param finfo the string for the file (string)
1143 @param full flag indicating full pathname should be displayed (boolean) 1152 @param full flag indicating full pathname should be displayed (boolean)
1144 @param sourceLanguage source code language of the project (string) 1153 @param sourceLanguage source code language of the project (string)
1145 """ 1154 """
1146 BrowserItem.__init__(self, parent, os.path.basename(finfo)) 1155 BrowserItem.__init__(self, parent, os.path.basename(finfo))
1147 1156
1148 self.type_ = BrowserItemFile 1157 self.type_ = BrowserItemFile
1149 self.fileext = os.path.splitext(finfo)[1].lower() 1158 self.fileext = os.path.splitext(finfo)[1].lower()
1150 self._filename = os.path.abspath(finfo) 1159 self._filename = os.path.abspath(finfo)
1151 self._dirName = os.path.dirname(finfo) 1160 self._dirName = os.path.dirname(finfo)
1152 self.sourceLanguage = sourceLanguage 1161 self.sourceLanguage = sourceLanguage
1153 1162
1154 self._moduleName = '' 1163 self._moduleName = ""
1155 1164
1156 pixName = "" 1165 pixName = ""
1157 if self.isPython3File(): 1166 if self.isPython3File():
1158 pixName = "filePython" 1167 pixName = "filePython"
1159 self._populated = False 1168 self._populated = False
1160 self._lazyPopulation = True 1169 self._lazyPopulation = True
1170 self._lazyPopulation = True 1179 self._lazyPopulation = True
1171 self._moduleName = os.path.basename(finfo) 1180 self._moduleName = os.path.basename(finfo)
1172 elif self.isDesignerFile(): 1181 elif self.isDesignerFile():
1173 pixName = "fileDesigner" 1182 pixName = "fileDesigner"
1174 elif self.isLinguistFile(): 1183 elif self.isLinguistFile():
1175 if self.fileext == '.ts': 1184 if self.fileext == ".ts":
1176 pixName = "fileLinguist" 1185 pixName = "fileLinguist"
1177 else: 1186 else:
1178 pixName = "fileLinguist2" 1187 pixName = "fileLinguist2"
1179 elif self.isResourcesFile(): 1188 elif self.isResourcesFile():
1180 pixName = "fileResource" 1189 pixName = "fileResource"
1205 self._moduleName = os.path.basename(finfo) 1214 self._moduleName = os.path.basename(finfo)
1206 elif self.isEricGraphicsFile(): 1215 elif self.isEricGraphicsFile():
1207 pixName = "fileUML" 1216 pixName = "fileUML"
1208 else: 1217 else:
1209 pixName = "fileMisc" 1218 pixName = "fileMisc"
1210 1219
1211 if os.path.lexists(self._filename) and os.path.islink(self._filename): 1220 if os.path.lexists(self._filename) and os.path.islink(self._filename):
1212 self.symlink = True 1221 self.symlink = True
1213 self.icon = UI.PixmapCache.getSymlinkIcon(pixName) 1222 self.icon = UI.PixmapCache.getSymlinkIcon(pixName)
1214 else: 1223 else:
1215 self.icon = UI.PixmapCache.getIcon(pixName) 1224 self.icon = UI.PixmapCache.getIcon(pixName)
1216 1225
1217 def setName(self, finfo, full=True): 1226 def setName(self, finfo, full=True):
1218 """ 1227 """
1219 Public method to set the directory name. 1228 Public method to set the directory name.
1220 1229
1221 @param finfo the string for the file (string) 1230 @param finfo the string for the file (string)
1222 @param full flag indicating full pathname should be displayed (boolean) 1231 @param full flag indicating full pathname should be displayed (boolean)
1223 """ 1232 """
1224 self._filename = os.path.abspath(finfo) 1233 self._filename = os.path.abspath(finfo)
1225 self.itemData[0] = os.path.basename(finfo) 1234 self.itemData[0] = os.path.basename(finfo)
1226 if ( 1235 if (
1227 self.isPython3File() or 1236 self.isPython3File()
1228 self.isRubyFile() or 1237 or self.isRubyFile()
1229 self.isIdlFile() or 1238 or self.isIdlFile()
1230 self.isProtobufFile() 1239 or self.isProtobufFile()
1231 ): 1240 ):
1232 self._dirName = os.path.dirname(finfo) 1241 self._dirName = os.path.dirname(finfo)
1233 self._moduleName = os.path.basename(finfo) 1242 self._moduleName = os.path.basename(finfo)
1234 1243
1235 def fileName(self): 1244 def fileName(self):
1236 """ 1245 """
1237 Public method returning the filename. 1246 Public method returning the filename.
1238 1247
1239 @return filename (string) 1248 @return filename (string)
1240 """ 1249 """
1241 return self._filename 1250 return self._filename
1242 1251
1243 def name(self): 1252 def name(self):
1244 """ 1253 """
1245 Public method to return the name of the item. 1254 Public method to return the name of the item.
1246 1255
1247 @return name of the item (string) 1256 @return name of the item (string)
1248 """ 1257 """
1249 return self._filename 1258 return self._filename
1250 1259
1251 def fileExt(self): 1260 def fileExt(self):
1252 """ 1261 """
1253 Public method returning the file extension. 1262 Public method returning the file extension.
1254 1263
1255 @return file extension (string) 1264 @return file extension (string)
1256 """ 1265 """
1257 return self.fileext 1266 return self.fileext
1258 1267
1259 def dirName(self): 1268 def dirName(self):
1260 """ 1269 """
1261 Public method returning the directory name. 1270 Public method returning the directory name.
1262 1271
1263 @return directory name (string) 1272 @return directory name (string)
1264 """ 1273 """
1265 return self._dirName 1274 return self._dirName
1266 1275
1267 def moduleName(self): 1276 def moduleName(self):
1268 """ 1277 """
1269 Public method returning the module name. 1278 Public method returning the module name.
1270 1279
1271 @return module name (string) 1280 @return module name (string)
1272 """ 1281 """
1273 return self._moduleName 1282 return self._moduleName
1274 1283
1275 def isPython3File(self): 1284 def isPython3File(self):
1276 """ 1285 """
1277 Public method to check, if this file is a Python3 script. 1286 Public method to check, if this file is a Python3 script.
1278 1287
1279 @return flag indicating a Python3 file 1288 @return flag indicating a Python3 file
1280 @rtype bool 1289 @rtype bool
1281 """ 1290 """
1282 return ( 1291 return self.fileext in Preferences.getPython("Python3Extensions") or (
1283 self.fileext in Preferences.getPython("Python3Extensions") or 1292 self.fileext == "" and self.sourceLanguage == "Python3"
1284 (self.fileext == "" and self.sourceLanguage == "Python3")
1285 ) 1293 )
1286 1294
1287 def isCythonFile(self): 1295 def isCythonFile(self):
1288 """ 1296 """
1289 Public method to check, if this file is a Cython file. 1297 Public method to check, if this file is a Cython file.
1290 1298
1291 @return flag indicating a Cython file 1299 @return flag indicating a Cython file
1292 @rtype bool 1300 @rtype bool
1293 """ 1301 """
1294 return ( 1302 return self.fileext in (".pyx", ".pxd", ".pxi") or (
1295 self.fileext in (".pyx", ".pxd", ".pxi") or 1303 self.fileext == "" and self.sourceLanguage == "Cython"
1296 (self.fileext == "" and self.sourceLanguage == "Cython")
1297 ) 1304 )
1298 1305
1299 def isRubyFile(self): 1306 def isRubyFile(self):
1300 """ 1307 """
1301 Public method to check, if this file is a Ruby script. 1308 Public method to check, if this file is a Ruby script.
1302 1309
1303 @return flag indicating a Ruby file 1310 @return flag indicating a Ruby file
1304 @rtype bool 1311 @rtype bool
1305 """ 1312 """
1306 return ( 1313 return self.fileext == ".rb" or (
1307 self.fileext == '.rb' or 1314 self.fileext == "" and self.sourceLanguage == "Ruby"
1308 (self.fileext == "" and self.sourceLanguage == "Ruby")
1309 ) 1315 )
1310 1316
1311 def isDesignerFile(self): 1317 def isDesignerFile(self):
1312 """ 1318 """
1313 Public method to check, if this file is a Qt-Designer file. 1319 Public method to check, if this file is a Qt-Designer file.
1314 1320
1315 @return flag indicating a Qt-Designer file 1321 @return flag indicating a Qt-Designer file
1316 @rtype bool 1322 @rtype bool
1317 """ 1323 """
1318 return self.fileext == '.ui' 1324 return self.fileext == ".ui"
1319 1325
1320 def isLinguistFile(self): 1326 def isLinguistFile(self):
1321 """ 1327 """
1322 Public method to check, if this file is a Qt-Linguist file. 1328 Public method to check, if this file is a Qt-Linguist file.
1323 1329
1324 @return flag indicating a Qt-Linguist file 1330 @return flag indicating a Qt-Linguist file
1325 @rtype bool 1331 @rtype bool
1326 """ 1332 """
1327 return self.fileext in ['.ts', '.qm'] 1333 return self.fileext in [".ts", ".qm"]
1328 1334
1329 def isResourcesFile(self): 1335 def isResourcesFile(self):
1330 """ 1336 """
1331 Public method to check, if this file is a Qt-Resources file. 1337 Public method to check, if this file is a Qt-Resources file.
1332 1338
1333 @return flag indicating a Qt-Resources file 1339 @return flag indicating a Qt-Resources file
1334 @rtype bool 1340 @rtype bool
1335 """ 1341 """
1336 return self.fileext == '.qrc' 1342 return self.fileext == ".qrc"
1337 1343
1338 def isProjectFile(self): 1344 def isProjectFile(self):
1339 """ 1345 """
1340 Public method to check, if this file is an eric project file. 1346 Public method to check, if this file is an eric project file.
1341 1347
1342 @return flag indicating an eric project file 1348 @return flag indicating an eric project file
1343 @rtype bool 1349 @rtype bool
1344 """ 1350 """
1345 return self.fileext in ('.epj', '.e4p') 1351 return self.fileext in (".epj", ".e4p")
1346 1352
1347 def isMultiProjectFile(self): 1353 def isMultiProjectFile(self):
1348 """ 1354 """
1349 Public method to check, if this file is an eric multi project file. 1355 Public method to check, if this file is an eric multi project file.
1350 1356
1351 @return flag indicating an eric project file 1357 @return flag indicating an eric project file
1352 @rtype bool 1358 @rtype bool
1353 """ 1359 """
1354 return self.fileext in ('.emj', '.e4m', '.e5m') 1360 return self.fileext in (".emj", ".e4m", ".e5m")
1355 1361
1356 def isIdlFile(self): 1362 def isIdlFile(self):
1357 """ 1363 """
1358 Public method to check, if this file is a CORBA IDL file. 1364 Public method to check, if this file is a CORBA IDL file.
1359 1365
1360 @return flag indicating a CORBA IDL file 1366 @return flag indicating a CORBA IDL file
1361 @rtype bool 1367 @rtype bool
1362 """ 1368 """
1363 return self.fileext == '.idl' 1369 return self.fileext == ".idl"
1364 1370
1365 def isProtobufFile(self): 1371 def isProtobufFile(self):
1366 """ 1372 """
1367 Public method to check, if this file is a Google Protocol Buffer file. 1373 Public method to check, if this file is a Google Protocol Buffer file.
1368 1374
1369 @return flag indicating a protobuf file 1375 @return flag indicating a protobuf file
1370 @rtype bool 1376 @rtype bool
1371 """ 1377 """
1372 return self.fileext == ".proto" 1378 return self.fileext == ".proto"
1373 1379
1374 def isJavaScriptFile(self): 1380 def isJavaScriptFile(self):
1375 """ 1381 """
1376 Public method to check, if this file is a JavaScript file. 1382 Public method to check, if this file is a JavaScript file.
1377 1383
1378 @return flag indicating a JavaScript file 1384 @return flag indicating a JavaScript file
1379 @rtype bool 1385 @rtype bool
1380 """ 1386 """
1381 return self.fileext == '.js' 1387 return self.fileext == ".js"
1382 1388
1383 def isPixmapFile(self): 1389 def isPixmapFile(self):
1384 """ 1390 """
1385 Public method to check, if this file is a pixmap file. 1391 Public method to check, if this file is a pixmap file.
1386 1392
1387 @return flag indicating a pixmap file 1393 @return flag indicating a pixmap file
1388 @rtype bool 1394 @rtype bool
1389 """ 1395 """
1390 return self.fileext[1:] in QImageReader.supportedImageFormats() 1396 return self.fileext[1:] in QImageReader.supportedImageFormats()
1391 1397
1392 def isSvgFile(self): 1398 def isSvgFile(self):
1393 """ 1399 """
1394 Public method to check, if this file is a SVG file. 1400 Public method to check, if this file is a SVG file.
1395 1401
1396 @return flag indicating a SVG file 1402 @return flag indicating a SVG file
1397 @rtype bool 1403 @rtype bool
1398 """ 1404 """
1399 return self.fileext == '.svg' 1405 return self.fileext == ".svg"
1400 1406
1401 def isDFile(self): 1407 def isDFile(self):
1402 """ 1408 """
1403 Public method to check, if this file is a D file. 1409 Public method to check, if this file is a D file.
1404 1410
1405 @return flag indicating a D file (boolean) 1411 @return flag indicating a D file (boolean)
1406 """ 1412 """
1407 return ( 1413 return self.fileext in [".d", ".di"] or (
1408 self.fileext in ['.d', '.di'] or 1414 self.fileext == "" and self.sourceLanguage == "D"
1409 (self.fileext == "" and self.sourceLanguage == "D")
1410 ) 1415 )
1411 1416
1412 def isEricGraphicsFile(self): 1417 def isEricGraphicsFile(self):
1413 """ 1418 """
1414 Public method to check, if this is an eric graphics file. 1419 Public method to check, if this is an eric graphics file.
1415 1420
1416 @return flag indicating an eric graphics file 1421 @return flag indicating an eric graphics file
1417 @rtype bool 1422 @rtype bool
1418 """ 1423 """
1419 return self.fileext in ('.egj', '.e5g') 1424 return self.fileext in (".egj", ".e5g")
1420 1425
1421 def lessThan(self, other, column, order): 1426 def lessThan(self, other, column, order):
1422 """ 1427 """
1423 Public method to check, if the item is less than the other one. 1428 Public method to check, if the item is less than the other one.
1424 1429
1425 @param other reference to item to compare against (BrowserItem) 1430 @param other reference to item to compare against (BrowserItem)
1426 @param column column number to use for the comparison (integer) 1431 @param column column number to use for the comparison (integer)
1427 @param order sort order (Qt.SortOrder) (for special sorting) 1432 @param order sort order (Qt.SortOrder) (for special sorting)
1428 @return true, if this item is less than other (boolean) 1433 @return true, if this item is less than other (boolean)
1429 """ 1434 """
1430 if ( 1435 if not issubclass(other.__class__, BrowserFileItem) and Preferences.getUI(
1431 not issubclass(other.__class__, BrowserFileItem) and 1436 "BrowsersListFoldersFirst"
1432 Preferences.getUI("BrowsersListFoldersFirst")
1433 ): 1437 ):
1434 return order == Qt.SortOrder.DescendingOrder 1438 return order == Qt.SortOrder.DescendingOrder
1435 1439
1436 if issubclass(other.__class__, BrowserFileItem): 1440 if issubclass(other.__class__, BrowserFileItem):
1437 sinit = os.path.basename(self._filename).startswith('__init__.py') 1441 sinit = os.path.basename(self._filename).startswith("__init__.py")
1438 oinit = os.path.basename(other.fileName()).startswith( 1442 oinit = os.path.basename(other.fileName()).startswith("__init__.py")
1439 '__init__.py')
1440 if sinit and not oinit: 1443 if sinit and not oinit:
1441 return order == Qt.SortOrder.AscendingOrder 1444 return order == Qt.SortOrder.AscendingOrder
1442 if not sinit and oinit: 1445 if not sinit and oinit:
1443 return order == Qt.SortOrder.DescendingOrder 1446 return order == Qt.SortOrder.DescendingOrder
1444 1447
1445 return BrowserItem.lessThan(self, other, column, order) 1448 return BrowserItem.lessThan(self, other, column, order)
1446 1449
1447 1450
1448 class BrowserClassItem(BrowserItem): 1451 class BrowserClassItem(BrowserItem):
1449 """ 1452 """
1450 Class implementing the data structure for browser class items. 1453 Class implementing the data structure for browser class items.
1451 """ 1454 """
1455
1452 def __init__(self, parent, cl, filename): 1456 def __init__(self, parent, cl, filename):
1453 """ 1457 """
1454 Constructor 1458 Constructor
1455 1459
1456 @param parent parent item 1460 @param parent parent item
1457 @param cl Class object to be shown 1461 @param cl Class object to be shown
1458 @param filename filename of the file defining this class 1462 @param filename filename of the file defining this class
1459 """ 1463 """
1460 name = cl.name 1464 name = cl.name
1461 if hasattr(cl, 'super') and cl.super: 1465 if hasattr(cl, "super") and cl.super:
1462 supers = [] 1466 supers = []
1463 for sup in cl.super: 1467 for sup in cl.super:
1464 try: 1468 try:
1465 sname = sup.name 1469 sname = sup.name
1466 if sup.module != cl.module: 1470 if sup.module != cl.module:
1467 sname = "{0}.{1}".format(sup.module, sname) 1471 sname = "{0}.{1}".format(sup.module, sname)
1468 except AttributeError: 1472 except AttributeError:
1469 sname = sup 1473 sname = sup
1470 supers.append(sname) 1474 supers.append(sname)
1471 name += "({0})".format(", ".join(supers)) 1475 name += "({0})".format(", ".join(supers))
1472 1476
1473 BrowserItem.__init__(self, parent, name) 1477 BrowserItem.__init__(self, parent, name)
1474 1478
1475 self.type_ = BrowserItemClass 1479 self.type_ = BrowserItemClass
1476 self._name = name 1480 self._name = name
1477 self._classObject = cl 1481 self._classObject = cl
1478 self._filename = filename 1482 self._filename = filename
1479 1483
1480 import Utilities.ClassBrowsers.ClbrBaseClasses 1484 import Utilities.ClassBrowsers.ClbrBaseClasses
1485
1481 self.isfunction = isinstance( 1486 self.isfunction = isinstance(
1482 self._classObject, 1487 self._classObject, Utilities.ClassBrowsers.ClbrBaseClasses.Function
1483 Utilities.ClassBrowsers.ClbrBaseClasses.Function) 1488 )
1484 self.ismodule = isinstance( 1489 self.ismodule = isinstance(
1485 self._classObject, 1490 self._classObject, Utilities.ClassBrowsers.ClbrBaseClasses.Module
1486 Utilities.ClassBrowsers.ClbrBaseClasses.Module) 1491 )
1487 self.isenum = isinstance( 1492 self.isenum = isinstance(
1488 self._classObject, 1493 self._classObject, Utilities.ClassBrowsers.ClbrBaseClasses.Enum
1489 Utilities.ClassBrowsers.ClbrBaseClasses.Enum) 1494 )
1490 if self.isfunction: 1495 if self.isfunction:
1491 if cl.isPrivate(): 1496 if cl.isPrivate():
1492 self.icon = UI.PixmapCache.getIcon("method_private") 1497 self.icon = UI.PixmapCache.getIcon("method_private")
1493 elif cl.isProtected(): 1498 elif cl.isProtected():
1494 self.icon = UI.PixmapCache.getIcon("method_protected") 1499 self.icon = UI.PixmapCache.getIcon("method_protected")
1495 else: 1500 else:
1496 self.icon = UI.PixmapCache.getIcon("method") 1501 self.icon = UI.PixmapCache.getIcon("method")
1497 self.itemData[0] = "{0}({1})".format( 1502 self.itemData[0] = "{0}({1})".format(
1498 name, ", ".join(self._classObject.parameters)) 1503 name, ", ".join(self._classObject.parameters)
1504 )
1499 if self._classObject.annotation: 1505 if self._classObject.annotation:
1500 self.itemData[0] = "{0} {1}".format( 1506 self.itemData[0] = "{0} {1}".format(
1501 self.itemData[0], self._classObject.annotation) 1507 self.itemData[0], self._classObject.annotation
1502 #- if no defaults are wanted 1508 )
1503 #- ....format(name, 1509 # - if no defaults are wanted
1504 #- ", ".join([e.split('=')[0].strip() 1510 # - ....format(name,
1505 #- for e in self._classObject.parameters])) 1511 # - ", ".join([e.split('=')[0].strip()
1512 # - for e in self._classObject.parameters]))
1506 elif self.ismodule: 1513 elif self.ismodule:
1507 self.icon = UI.PixmapCache.getIcon("module") 1514 self.icon = UI.PixmapCache.getIcon("module")
1508 elif self.isenum: 1515 elif self.isenum:
1509 self.icon = UI.PixmapCache.getIcon("attribute") 1516 self.icon = UI.PixmapCache.getIcon("attribute")
1510 else: 1517 else:
1512 self.icon = UI.PixmapCache.getIcon("class_private") 1519 self.icon = UI.PixmapCache.getIcon("class_private")
1513 elif cl.isProtected(): 1520 elif cl.isProtected():
1514 self.icon = UI.PixmapCache.getIcon("class_protected") 1521 self.icon = UI.PixmapCache.getIcon("class_protected")
1515 else: 1522 else:
1516 self.icon = UI.PixmapCache.getIcon("class") 1523 self.icon = UI.PixmapCache.getIcon("class")
1517 if ( 1524 if self._classObject and (
1518 self._classObject and 1525 self._classObject.methods
1519 (self._classObject.methods or 1526 or self._classObject.classes
1520 self._classObject.classes or 1527 or self._classObject.attributes
1521 self._classObject.attributes or 1528 or self._classObject.globals
1522 self._classObject.globals)
1523 ): 1529 ):
1524 self._populated = False 1530 self._populated = False
1525 self._lazyPopulation = True 1531 self._lazyPopulation = True
1526 1532
1527 def name(self): 1533 def name(self):
1528 """ 1534 """
1529 Public method to return the name of the item. 1535 Public method to return the name of the item.
1530 1536
1531 @return name of the item (string) 1537 @return name of the item (string)
1532 """ 1538 """
1533 return '{0}@@{1}'.format(self._filename, self.lineno()) 1539 return "{0}@@{1}".format(self._filename, self.lineno())
1534 1540
1535 def fileName(self): 1541 def fileName(self):
1536 """ 1542 """
1537 Public method returning the filename. 1543 Public method returning the filename.
1538 1544
1539 @return filename (string) 1545 @return filename (string)
1540 """ 1546 """
1541 return self._filename 1547 return self._filename
1542 1548
1543 def classObject(self): 1549 def classObject(self):
1544 """ 1550 """
1545 Public method returning the class object. 1551 Public method returning the class object.
1546 1552
1547 @return reference to the class object 1553 @return reference to the class object
1548 """ 1554 """
1549 return self._classObject 1555 return self._classObject
1550 1556
1551 def lineno(self): 1557 def lineno(self):
1552 """ 1558 """
1553 Public method returning the line number defining this object. 1559 Public method returning the line number defining this object.
1554 1560
1555 @return line number defining the object (integer) 1561 @return line number defining the object (integer)
1556 """ 1562 """
1557 return self._classObject.lineno 1563 return self._classObject.lineno
1558 1564
1559 def boundaries(self): 1565 def boundaries(self):
1560 """ 1566 """
1561 Public method returning the boundaries of the method definition. 1567 Public method returning the boundaries of the method definition.
1562 1568
1563 @return tuple with start end end line number (integer, integer) 1569 @return tuple with start end end line number (integer, integer)
1564 """ 1570 """
1565 return (self._classObject.lineno, self._classObject.endlineno) 1571 return (self._classObject.lineno, self._classObject.endlineno)
1566 1572
1567 def lessThan(self, other, column, order): 1573 def lessThan(self, other, column, order):
1568 """ 1574 """
1569 Public method to check, if the item is less than the other one. 1575 Public method to check, if the item is less than the other one.
1570 1576
1571 @param other reference to item to compare against (BrowserItem) 1577 @param other reference to item to compare against (BrowserItem)
1572 @param column column number to use for the comparison (integer) 1578 @param column column number to use for the comparison (integer)
1573 @param order sort order (Qt.SortOrder) (for special sorting) 1579 @param order sort order (Qt.SortOrder) (for special sorting)
1574 @return true, if this item is less than other (boolean) 1580 @return true, if this item is less than other (boolean)
1575 """ 1581 """
1576 if issubclass( 1582 if issubclass(other.__class__, (BrowserCodingItem, BrowserClassAttributesItem)):
1577 other.__class__,
1578 (BrowserCodingItem, BrowserClassAttributesItem)
1579 ):
1580 return order == Qt.SortOrder.DescendingOrder 1583 return order == Qt.SortOrder.DescendingOrder
1581 1584
1582 if ( 1585 if Preferences.getUI("BrowsersListContentsByOccurrence") and column == 0:
1583 Preferences.getUI("BrowsersListContentsByOccurrence") and
1584 column == 0
1585 ):
1586 if order == Qt.SortOrder.AscendingOrder: 1586 if order == Qt.SortOrder.AscendingOrder:
1587 return self.lineno() < other.lineno() 1587 return self.lineno() < other.lineno()
1588 else: 1588 else:
1589 return self.lineno() > other.lineno() 1589 return self.lineno() > other.lineno()
1590 1590
1591 return BrowserItem.lessThan(self, other, column, order) 1591 return BrowserItem.lessThan(self, other, column, order)
1592 1592
1593 def isPublic(self): 1593 def isPublic(self):
1594 """ 1594 """
1595 Public method returning the public visibility status. 1595 Public method returning the public visibility status.
1596 1596
1597 @return flag indicating public visibility (boolean) 1597 @return flag indicating public visibility (boolean)
1598 """ 1598 """
1599 return self._classObject.isPublic() 1599 return self._classObject.isPublic()
1600 1600
1601 1601
1602 class BrowserMethodItem(BrowserItem): 1602 class BrowserMethodItem(BrowserItem):
1603 """ 1603 """
1604 Class implementing the data structure for browser method items. 1604 Class implementing the data structure for browser method items.
1605 """ 1605 """
1606
1606 def __init__(self, parent, fn, filename): 1607 def __init__(self, parent, fn, filename):
1607 """ 1608 """
1608 Constructor 1609 Constructor
1609 1610
1610 @param parent parent item 1611 @param parent parent item
1611 @param fn Function object to be shown 1612 @param fn Function object to be shown
1612 @param filename filename of the file defining this class (string) 1613 @param filename filename of the file defining this class (string)
1613 """ 1614 """
1614 name = fn.name 1615 name = fn.name
1615 BrowserItem.__init__(self, parent, name) 1616 BrowserItem.__init__(self, parent, name)
1616 1617
1617 import Utilities.ClassBrowsers.ClbrBaseClasses 1618 import Utilities.ClassBrowsers.ClbrBaseClasses
1619
1618 self.type_ = BrowserItemMethod 1620 self.type_ = BrowserItemMethod
1619 self._name = name 1621 self._name = name
1620 self._functionObject = fn 1622 self._functionObject = fn
1621 self._filename = filename 1623 self._filename = filename
1622 if ( 1624 if (
1623 self._functionObject.modifier == 1625 self._functionObject.modifier
1624 Utilities.ClassBrowsers.ClbrBaseClasses.Function.Static 1626 == Utilities.ClassBrowsers.ClbrBaseClasses.Function.Static
1625 ): 1627 ):
1626 self.icon = UI.PixmapCache.getIcon("method_static") 1628 self.icon = UI.PixmapCache.getIcon("method_static")
1627 elif ( 1629 elif (
1628 self._functionObject.modifier == 1630 self._functionObject.modifier
1629 Utilities.ClassBrowsers.ClbrBaseClasses.Function.Class 1631 == Utilities.ClassBrowsers.ClbrBaseClasses.Function.Class
1630 ): 1632 ):
1631 self.icon = UI.PixmapCache.getIcon("method_class") 1633 self.icon = UI.PixmapCache.getIcon("method_class")
1632 elif self._functionObject.isPrivate(): 1634 elif self._functionObject.isPrivate():
1633 self.icon = UI.PixmapCache.getIcon("method_private") 1635 self.icon = UI.PixmapCache.getIcon("method_private")
1634 elif self._functionObject.isProtected(): 1636 elif self._functionObject.isProtected():
1635 self.icon = UI.PixmapCache.getIcon("method_protected") 1637 self.icon = UI.PixmapCache.getIcon("method_protected")
1636 else: 1638 else:
1637 self.icon = UI.PixmapCache.getIcon("method") 1639 self.icon = UI.PixmapCache.getIcon("method")
1638 self.itemData[0] = "{0}({1})".format( 1640 self.itemData[0] = "{0}({1})".format(
1639 name, ", ".join(self._functionObject.parameters)) 1641 name, ", ".join(self._functionObject.parameters)
1642 )
1640 if self._functionObject.annotation: 1643 if self._functionObject.annotation:
1641 self.itemData[0] = "{0} {1}".format( 1644 self.itemData[0] = "{0} {1}".format(
1642 self.itemData[0], self._functionObject.annotation) 1645 self.itemData[0], self._functionObject.annotation
1646 )
1643 # if no defaults are wanted 1647 # if no defaults are wanted
1644 # ....format(name, 1648 # ....format(name,
1645 # ", ".join([e.split('=')[0].strip() 1649 # ", ".join([e.split('=')[0].strip()
1646 # for e in self._functionObject.parameters])) 1650 # for e in self._functionObject.parameters]))
1647 if ( 1651 if self._functionObject and (
1648 self._functionObject and 1652 self._functionObject.methods or self._functionObject.classes
1649 (self._functionObject.methods or self._functionObject.classes)
1650 ): 1653 ):
1651 self._populated = False 1654 self._populated = False
1652 self._lazyPopulation = True 1655 self._lazyPopulation = True
1653 1656
1654 def name(self): 1657 def name(self):
1655 """ 1658 """
1656 Public method to return the name of the item. 1659 Public method to return the name of the item.
1657 1660
1658 @return name of the item (string) 1661 @return name of the item (string)
1659 """ 1662 """
1660 return '{0}@@{1}'.format(self._filename, self.lineno()) 1663 return "{0}@@{1}".format(self._filename, self.lineno())
1661 1664
1662 def fileName(self): 1665 def fileName(self):
1663 """ 1666 """
1664 Public method returning the filename. 1667 Public method returning the filename.
1665 1668
1666 @return filename (string) 1669 @return filename (string)
1667 """ 1670 """
1668 return self._filename 1671 return self._filename
1669 1672
1670 def functionObject(self): 1673 def functionObject(self):
1671 """ 1674 """
1672 Public method returning the function object. 1675 Public method returning the function object.
1673 1676
1674 @return reference to the function object 1677 @return reference to the function object
1675 """ 1678 """
1676 return self._functionObject 1679 return self._functionObject
1677 1680
1678 def lineno(self): 1681 def lineno(self):
1679 """ 1682 """
1680 Public method returning the line number defining this object. 1683 Public method returning the line number defining this object.
1681 1684
1682 @return line number defining the object (integer) 1685 @return line number defining the object (integer)
1683 """ 1686 """
1684 return self._functionObject.lineno 1687 return self._functionObject.lineno
1685 1688
1686 def boundaries(self): 1689 def boundaries(self):
1687 """ 1690 """
1688 Public method returning the boundaries of the method definition. 1691 Public method returning the boundaries of the method definition.
1689 1692
1690 @return tuple with start end end line number (integer, integer) 1693 @return tuple with start end end line number (integer, integer)
1691 """ 1694 """
1692 return (self._functionObject.lineno, self._functionObject.endlineno) 1695 return (self._functionObject.lineno, self._functionObject.endlineno)
1693 1696
1694 def lessThan(self, other, column, order): 1697 def lessThan(self, other, column, order):
1695 """ 1698 """
1696 Public method to check, if the item is less than the other one. 1699 Public method to check, if the item is less than the other one.
1697 1700
1698 @param other reference to item to compare against (BrowserItem) 1701 @param other reference to item to compare against (BrowserItem)
1699 @param column column number to use for the comparison (integer) 1702 @param column column number to use for the comparison (integer)
1700 @param order sort order (Qt.SortOrder) (for special sorting) 1703 @param order sort order (Qt.SortOrder) (for special sorting)
1701 @return true, if this item is less than other (boolean) 1704 @return true, if this item is less than other (boolean)
1702 """ 1705 """
1703 if issubclass(other.__class__, BrowserMethodItem): 1706 if issubclass(other.__class__, BrowserMethodItem):
1704 if self._name.startswith('__init__'): 1707 if self._name.startswith("__init__"):
1705 return order == Qt.SortOrder.AscendingOrder 1708 return order == Qt.SortOrder.AscendingOrder
1706 if other._name.startswith('__init__'): 1709 if other._name.startswith("__init__"):
1707 return order == Qt.SortOrder.DescendingOrder 1710 return order == Qt.SortOrder.DescendingOrder
1708 elif issubclass(other.__class__, BrowserClassAttributesItem): 1711 elif issubclass(other.__class__, BrowserClassAttributesItem):
1709 return order == Qt.SortOrder.DescendingOrder 1712 return order == Qt.SortOrder.DescendingOrder
1710 1713
1711 if ( 1714 if Preferences.getUI("BrowsersListContentsByOccurrence") and column == 0:
1712 Preferences.getUI("BrowsersListContentsByOccurrence") and
1713 column == 0
1714 ):
1715 if order == Qt.SortOrder.AscendingOrder: 1715 if order == Qt.SortOrder.AscendingOrder:
1716 return self.lineno() < other.lineno() 1716 return self.lineno() < other.lineno()
1717 else: 1717 else:
1718 return self.lineno() > other.lineno() 1718 return self.lineno() > other.lineno()
1719 1719
1720 return BrowserItem.lessThan(self, other, column, order) 1720 return BrowserItem.lessThan(self, other, column, order)
1721 1721
1722 def isPublic(self): 1722 def isPublic(self):
1723 """ 1723 """
1724 Public method returning the public visibility status. 1724 Public method returning the public visibility status.
1725 1725
1726 @return flag indicating public visibility (boolean) 1726 @return flag indicating public visibility (boolean)
1727 """ 1727 """
1728 return self._functionObject.isPublic() 1728 return self._functionObject.isPublic()
1729 1729
1730 1730
1731 class BrowserClassAttributesItem(BrowserItem): 1731 class BrowserClassAttributesItem(BrowserItem):
1732 """ 1732 """
1733 Class implementing the data structure for browser class attributes items. 1733 Class implementing the data structure for browser class attributes items.
1734 """ 1734 """
1735
1735 def __init__(self, parent, attributes, text, isClass=False): 1736 def __init__(self, parent, attributes, text, isClass=False):
1736 """ 1737 """
1737 Constructor 1738 Constructor
1738 1739
1739 @param parent parent item 1740 @param parent parent item
1740 @param attributes list of attributes 1741 @param attributes list of attributes
1741 @param text text to be shown by this item (string) 1742 @param text text to be shown by this item (string)
1742 @param isClass flag indicating class attributes (boolean) 1743 @param isClass flag indicating class attributes (boolean)
1743 """ 1744 """
1744 BrowserItem.__init__(self, parent, text) 1745 BrowserItem.__init__(self, parent, text)
1745 1746
1746 self.type_ = BrowserItemAttributes 1747 self.type_ = BrowserItemAttributes
1747 self._attributes = attributes.copy() 1748 self._attributes = attributes.copy()
1748 self._populated = False 1749 self._populated = False
1749 self._lazyPopulation = True 1750 self._lazyPopulation = True
1750 if isClass: 1751 if isClass:
1751 self.icon = UI.PixmapCache.getIcon("attributes_class") 1752 self.icon = UI.PixmapCache.getIcon("attributes_class")
1752 else: 1753 else:
1753 self.icon = UI.PixmapCache.getIcon("attributes") 1754 self.icon = UI.PixmapCache.getIcon("attributes")
1754 self.__isClass = isClass 1755 self.__isClass = isClass
1755 1756
1756 def name(self): 1757 def name(self):
1757 """ 1758 """
1758 Public method to return the name of the item. 1759 Public method to return the name of the item.
1759 1760
1760 @return name of the item (string) 1761 @return name of the item (string)
1761 """ 1762 """
1762 return '{0}@@{1}'.format(self.parentItem.name(), self.data(0)) 1763 return "{0}@@{1}".format(self.parentItem.name(), self.data(0))
1763 1764
1764 def attributes(self): 1765 def attributes(self):
1765 """ 1766 """
1766 Public method returning the attribute list. 1767 Public method returning the attribute list.
1767 1768
1768 @return reference to the list of attributes 1769 @return reference to the list of attributes
1769 """ 1770 """
1770 return self._attributes 1771 return self._attributes
1771 1772
1772 def isClassAttributes(self): 1773 def isClassAttributes(self):
1773 """ 1774 """
1774 Public method returning the attributes type. 1775 Public method returning the attributes type.
1775 1776
1776 @return flag indicating class attributes (boolean) 1777 @return flag indicating class attributes (boolean)
1777 """ 1778 """
1778 return self.__isClass 1779 return self.__isClass
1779 1780
1780 def lessThan(self, other, column, order): 1781 def lessThan(self, other, column, order):
1781 """ 1782 """
1782 Public method to check, if the item is less than the other one. 1783 Public method to check, if the item is less than the other one.
1783 1784
1784 @param other reference to item to compare against (BrowserItem) 1785 @param other reference to item to compare against (BrowserItem)
1785 @param column column number to use for the comparison (integer) 1786 @param column column number to use for the comparison (integer)
1786 @param order sort order (Qt.SortOrder) (for special sorting) 1787 @param order sort order (Qt.SortOrder) (for special sorting)
1787 @return true, if this item is less than other (boolean) 1788 @return true, if this item is less than other (boolean)
1788 """ 1789 """
1789 if issubclass(other.__class__, BrowserCodingItem): 1790 if issubclass(other.__class__, BrowserCodingItem):
1790 return order == Qt.SortOrder.DescendingOrder 1791 return order == Qt.SortOrder.DescendingOrder
1791 elif issubclass( 1792 elif issubclass(other.__class__, (BrowserClassItem, BrowserMethodItem)):
1792 other.__class__,
1793 (BrowserClassItem, BrowserMethodItem)
1794 ):
1795 return order == Qt.SortOrder.AscendingOrder 1793 return order == Qt.SortOrder.AscendingOrder
1796 1794
1797 return BrowserItem.lessThan(self, other, column, order) 1795 return BrowserItem.lessThan(self, other, column, order)
1798 1796
1799 1797
1800 class BrowserClassAttributeItem(BrowserItem): 1798 class BrowserClassAttributeItem(BrowserItem):
1801 """ 1799 """
1802 Class implementing the data structure for browser class attribute items. 1800 Class implementing the data structure for browser class attribute items.
1803 """ 1801 """
1802
1804 def __init__(self, parent, attribute, isClass=False): 1803 def __init__(self, parent, attribute, isClass=False):
1805 """ 1804 """
1806 Constructor 1805 Constructor
1807 1806
1808 @param parent parent item 1807 @param parent parent item
1809 @param attribute reference to the attribute object 1808 @param attribute reference to the attribute object
1810 @param isClass flag indicating a class attribute (boolean) 1809 @param isClass flag indicating a class attribute (boolean)
1811 """ 1810 """
1812 BrowserItem.__init__(self, parent, attribute.name) 1811 BrowserItem.__init__(self, parent, attribute.name)
1813 1812
1814 self.type_ = BrowserItemAttribute 1813 self.type_ = BrowserItemAttribute
1815 self._attributeObject = attribute 1814 self._attributeObject = attribute
1816 self.__public = attribute.isPublic() 1815 self.__public = attribute.isPublic()
1817 if isClass: 1816 if isClass:
1818 self.icon = UI.PixmapCache.getIcon("attribute_class") 1817 self.icon = UI.PixmapCache.getIcon("attribute_class")
1820 self.icon = UI.PixmapCache.getIcon("attribute_private") 1819 self.icon = UI.PixmapCache.getIcon("attribute_private")
1821 elif attribute.isProtected(): 1820 elif attribute.isProtected():
1822 self.icon = UI.PixmapCache.getIcon("attribute_protected") 1821 self.icon = UI.PixmapCache.getIcon("attribute_protected")
1823 else: 1822 else:
1824 self.icon = UI.PixmapCache.getIcon("attribute") 1823 self.icon = UI.PixmapCache.getIcon("attribute")
1825 1824
1826 def isPublic(self): 1825 def isPublic(self):
1827 """ 1826 """
1828 Public method returning the public visibility status. 1827 Public method returning the public visibility status.
1829 1828
1830 @return flag indicating public visibility (boolean) 1829 @return flag indicating public visibility (boolean)
1831 """ 1830 """
1832 return self.__public 1831 return self.__public
1833 1832
1834 def attributeObject(self): 1833 def attributeObject(self):
1835 """ 1834 """
1836 Public method returning the class object. 1835 Public method returning the class object.
1837 1836
1838 @return reference to the class object 1837 @return reference to the class object
1839 """ 1838 """
1840 return self._attributeObject 1839 return self._attributeObject
1841 1840
1842 def fileName(self): 1841 def fileName(self):
1843 """ 1842 """
1844 Public method returning the filename. 1843 Public method returning the filename.
1845 1844
1846 @return filename (string) 1845 @return filename (string)
1847 """ 1846 """
1848 return self._attributeObject.file 1847 return self._attributeObject.file
1849 1848
1850 def lineno(self): 1849 def lineno(self):
1851 """ 1850 """
1852 Public method returning the line number defining this object. 1851 Public method returning the line number defining this object.
1853 1852
1854 @return line number defining the object (integer) 1853 @return line number defining the object (integer)
1855 """ 1854 """
1856 return self._attributeObject.lineno 1855 return self._attributeObject.lineno
1857 1856
1858 def linenos(self): 1857 def linenos(self):
1859 """ 1858 """
1860 Public method returning the line numbers this object is assigned to. 1859 Public method returning the line numbers this object is assigned to.
1861 1860
1862 @return line number the object is assigned to (list of integers) 1861 @return line number the object is assigned to (list of integers)
1863 """ 1862 """
1864 return self._attributeObject.linenos[:] 1863 return self._attributeObject.linenos[:]
1865 1864
1866 def lessThan(self, other, column, order): 1865 def lessThan(self, other, column, order):
1867 """ 1866 """
1868 Public method to check, if the item is less than the other one. 1867 Public method to check, if the item is less than the other one.
1869 1868
1870 @param other reference to item to compare against (BrowserItem) 1869 @param other reference to item to compare against (BrowserItem)
1871 @param column column number to use for the comparison (integer) 1870 @param column column number to use for the comparison (integer)
1872 @param order sort order (Qt.SortOrder) (for special sorting) 1871 @param order sort order (Qt.SortOrder) (for special sorting)
1873 @return true, if this item is less than other (boolean) 1872 @return true, if this item is less than other (boolean)
1874 """ 1873 """
1875 if ( 1874 if Preferences.getUI("BrowsersListContentsByOccurrence") and column == 0:
1876 Preferences.getUI("BrowsersListContentsByOccurrence") and
1877 column == 0
1878 ):
1879 if order == Qt.SortOrder.AscendingOrder: 1875 if order == Qt.SortOrder.AscendingOrder:
1880 return self.lineno() < other.lineno() 1876 return self.lineno() < other.lineno()
1881 else: 1877 else:
1882 return self.lineno() > other.lineno() 1878 return self.lineno() > other.lineno()
1883 1879
1884 return BrowserItem.lessThan(self, other, column, order) 1880 return BrowserItem.lessThan(self, other, column, order)
1885 1881
1886 1882
1887 class BrowserGlobalsItem(BrowserClassAttributesItem): 1883 class BrowserGlobalsItem(BrowserClassAttributesItem):
1888 """ 1884 """
1889 Class implementing the data structure for browser globals items. 1885 Class implementing the data structure for browser globals items.
1890 """ 1886 """
1887
1891 def __init__(self, parent, attributes, text): 1888 def __init__(self, parent, attributes, text):
1892 """ 1889 """
1893 Constructor 1890 Constructor
1894 1891
1895 @param parent parent item 1892 @param parent parent item
1896 @param attributes list of attributes 1893 @param attributes list of attributes
1897 @param text text to be shown by this item (string) 1894 @param text text to be shown by this item (string)
1898 """ 1895 """
1899 BrowserClassAttributesItem.__init__(self, parent, attributes, text) 1896 BrowserClassAttributesItem.__init__(self, parent, attributes, text)
1901 1898
1902 class BrowserCodingItem(BrowserItem): 1899 class BrowserCodingItem(BrowserItem):
1903 """ 1900 """
1904 Class implementing the data structure for browser coding items. 1901 Class implementing the data structure for browser coding items.
1905 """ 1902 """
1903
1906 def __init__(self, parent, text, linenumber): 1904 def __init__(self, parent, text, linenumber):
1907 """ 1905 """
1908 Constructor 1906 Constructor
1909 1907
1910 @param parent parent item 1908 @param parent parent item
1911 @type BrowserItem 1909 @type BrowserItem
1912 @param text text to be shown by this item 1910 @param text text to be shown by this item
1913 @type str 1911 @type str
1914 @param linenumber line number of the coding line 1912 @param linenumber line number of the coding line
1915 @type int 1913 @type int
1916 """ 1914 """
1917 BrowserItem.__init__(self, parent, text) 1915 BrowserItem.__init__(self, parent, text)
1918 1916
1919 self.type_ = BrowserItemCoding 1917 self.type_ = BrowserItemCoding
1920 self.icon = UI.PixmapCache.getIcon("textencoding") 1918 self.icon = UI.PixmapCache.getIcon("textencoding")
1921 1919
1922 self.__lineno = linenumber 1920 self.__lineno = linenumber
1923 1921
1924 def lineno(self): 1922 def lineno(self):
1925 """ 1923 """
1926 Public method returning the line number of the coding line. 1924 Public method returning the line number of the coding line.
1927 1925
1928 @return line number defining the coding line 1926 @return line number defining the coding line
1929 @rtype int 1927 @rtype int
1930 """ 1928 """
1931 return self.__lineno 1929 return self.__lineno
1932 1930
1933 def lessThan(self, other, column, order): 1931 def lessThan(self, other, column, order):
1934 """ 1932 """
1935 Public method to check, if the item is less than the other one. 1933 Public method to check, if the item is less than the other one.
1936 1934
1937 @param other reference to item to compare against (BrowserItem) 1935 @param other reference to item to compare against (BrowserItem)
1938 @param column column number to use for the comparison (integer) 1936 @param column column number to use for the comparison (integer)
1939 @param order sort order (Qt.SortOrder) (for special sorting) 1937 @param order sort order (Qt.SortOrder) (for special sorting)
1940 @return true, if this item is less than other (boolean) 1938 @return true, if this item is less than other (boolean)
1941 """ 1939 """
1942 if issubclass( 1940 if issubclass(
1943 other.__class__, 1941 other.__class__,
1944 (BrowserClassItem, BrowserClassAttributesItem, BrowserImportItem) 1942 (BrowserClassItem, BrowserClassAttributesItem, BrowserImportItem),
1945 ): 1943 ):
1946 return order == Qt.SortOrder.AscendingOrder 1944 return order == Qt.SortOrder.AscendingOrder
1947 1945
1948 return BrowserItem.lessThan(self, other, column, order) 1946 return BrowserItem.lessThan(self, other, column, order)
1949 1947
1950 1948
1951 class BrowserImportsItem(BrowserItem): 1949 class BrowserImportsItem(BrowserItem):
1952 """ 1950 """
1953 Class implementing the data structure for browser import items. 1951 Class implementing the data structure for browser import items.
1954 """ 1952 """
1953
1955 def __init__(self, parent, text): 1954 def __init__(self, parent, text):
1956 """ 1955 """
1957 Constructor 1956 Constructor
1958 1957
1959 @param parent parent item 1958 @param parent parent item
1960 @param text text to be shown by this item (string) 1959 @param text text to be shown by this item (string)
1961 """ 1960 """
1962 BrowserItem.__init__(self, parent, text) 1961 BrowserItem.__init__(self, parent, text)
1963 1962
1964 self.type_ = BrowserItemImports 1963 self.type_ = BrowserItemImports
1965 self.icon = UI.PixmapCache.getIcon("imports") 1964 self.icon = UI.PixmapCache.getIcon("imports")
1966 1965
1967 def lessThan(self, other, column, order): 1966 def lessThan(self, other, column, order):
1968 """ 1967 """
1969 Public method to check, if the item is less than the other one. 1968 Public method to check, if the item is less than the other one.
1970 1969
1971 @param other reference to item to compare against (BrowserItem) 1970 @param other reference to item to compare against (BrowserItem)
1972 @param column column number to use for the comparison (integer) 1971 @param column column number to use for the comparison (integer)
1973 @param order sort order (Qt.SortOrder) (for special sorting) 1972 @param order sort order (Qt.SortOrder) (for special sorting)
1974 @return true, if this item is less than other (boolean) 1973 @return true, if this item is less than other (boolean)
1975 """ 1974 """
1976 if issubclass( 1975 if issubclass(other.__class__, (BrowserClassItem, BrowserClassAttributesItem)):
1977 other.__class__,
1978 (BrowserClassItem, BrowserClassAttributesItem)
1979 ):
1980 return order == Qt.SortOrder.AscendingOrder 1976 return order == Qt.SortOrder.AscendingOrder
1981 1977
1982 return BrowserItem.lessThan(self, other, column, order) 1978 return BrowserItem.lessThan(self, other, column, order)
1983 1979
1984 1980
1985 class BrowserImportItem(BrowserItem): 1981 class BrowserImportItem(BrowserItem):
1986 """ 1982 """
1987 Class implementing the data structure for browser imported module and 1983 Class implementing the data structure for browser imported module and
1988 imported names items. 1984 imported names items.
1989 """ 1985 """
1986
1990 def __init__(self, parent, text, filename, lineNumbers, isModule=True): 1987 def __init__(self, parent, text, filename, lineNumbers, isModule=True):
1991 """ 1988 """
1992 Constructor 1989 Constructor
1993 1990
1994 @param parent parent item 1991 @param parent parent item
1995 @param text text to be shown by this item (string) 1992 @param text text to be shown by this item (string)
1996 @param filename name of the file (string) 1993 @param filename name of the file (string)
1997 @param lineNumbers list of line numbers of the import statement 1994 @param lineNumbers list of line numbers of the import statement
1998 (list of integer) 1995 (list of integer)
1999 @param isModule flag indicating a module item entry (boolean) 1996 @param isModule flag indicating a module item entry (boolean)
2000 """ 1997 """
2001 BrowserItem.__init__(self, parent, text) 1998 BrowserItem.__init__(self, parent, text)
2002 1999
2003 self.__filename = filename 2000 self.__filename = filename
2004 self.__linenos = lineNumbers[:] 2001 self.__linenos = lineNumbers[:]
2005 2002
2006 self.type_ = BrowserItemImport 2003 self.type_ = BrowserItemImport
2007 if isModule: 2004 if isModule:
2008 self.icon = UI.PixmapCache.getIcon("importedModule") 2005 self.icon = UI.PixmapCache.getIcon("importedModule")
2009 else: 2006 else:
2010 self.icon = UI.PixmapCache.getIcon("importedName") 2007 self.icon = UI.PixmapCache.getIcon("importedName")
2011 2008
2012 def fileName(self): 2009 def fileName(self):
2013 """ 2010 """
2014 Public method returning the filename. 2011 Public method returning the filename.
2015 2012
2016 @return filename (string) 2013 @return filename (string)
2017 """ 2014 """
2018 return self.__filename 2015 return self.__filename
2019 2016
2020 def lineno(self): 2017 def lineno(self):
2021 """ 2018 """
2022 Public method returning the line number of the first import. 2019 Public method returning the line number of the first import.
2023 2020
2024 @return line number of the first import (integer) 2021 @return line number of the first import (integer)
2025 """ 2022 """
2026 return self.__linenos[0] 2023 return self.__linenos[0]
2027 2024
2028 def linenos(self): 2025 def linenos(self):
2029 """ 2026 """
2030 Public method returning the line numbers of all imports. 2027 Public method returning the line numbers of all imports.
2031 2028
2032 @return line numbers of all imports (list of integers) 2029 @return line numbers of all imports (list of integers)
2033 """ 2030 """
2034 return self.__linenos[:] 2031 return self.__linenos[:]
2035 2032
2036 def lessThan(self, other, column, order): 2033 def lessThan(self, other, column, order):
2037 """ 2034 """
2038 Public method to check, if the item is less than the other one. 2035 Public method to check, if the item is less than the other one.
2039 2036
2040 @param other reference to item to compare against (BrowserItem) 2037 @param other reference to item to compare against (BrowserItem)
2041 @param column column number to use for the comparison (integer) 2038 @param column column number to use for the comparison (integer)
2042 @param order sort order (Qt.SortOrder) (for special sorting) 2039 @param order sort order (Qt.SortOrder) (for special sorting)
2043 @return true, if this item is less than other (boolean) 2040 @return true, if this item is less than other (boolean)
2044 """ 2041 """
2045 if ( 2042 if Preferences.getUI("BrowsersListContentsByOccurrence") and column == 0:
2046 Preferences.getUI("BrowsersListContentsByOccurrence") and
2047 column == 0
2048 ):
2049 if order == Qt.SortOrder.AscendingOrder: 2043 if order == Qt.SortOrder.AscendingOrder:
2050 return self.lineno() < other.lineno() 2044 return self.lineno() < other.lineno()
2051 else: 2045 else:
2052 return self.lineno() > other.lineno() 2046 return self.lineno() > other.lineno()
2053 2047
2054 return BrowserItem.lessThan(self, other, column, order) 2048 return BrowserItem.lessThan(self, other, column, order)

eric ide

mercurial