eric6/UI/BrowserModel.py

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

eric ide

mercurial