9 |
9 |
10 import sys |
10 import sys |
11 import os |
11 import os |
12 import fnmatch |
12 import fnmatch |
13 |
13 |
14 from PyQt4.QtCore import QDir, QModelIndex, QAbstractItemModel, QFileSystemWatcher, Qt |
14 from PyQt4.QtCore import QDir, QModelIndex, QAbstractItemModel, \ |
|
15 QFileSystemWatcher, Qt |
15 from PyQt4.QtGui import QImageReader, QApplication, QFont |
16 from PyQt4.QtGui import QImageReader, QApplication, QFont |
16 |
17 |
17 import UI.PixmapCache |
18 import UI.PixmapCache |
18 import Preferences |
19 import Preferences |
19 import Utilities |
20 import Utilities |
36 def __init__(self, parent=None, nopopulate=False): |
37 def __init__(self, parent=None, nopopulate=False): |
37 """ |
38 """ |
38 Constructor |
39 Constructor |
39 |
40 |
40 @param parent reference to parent object (QObject) |
41 @param parent reference to parent object (QObject) |
41 @keyparam nopopulate flag indicating to not populate the model (boolean) |
42 @keyparam nopopulate flag indicating to not populate the model |
|
43 (boolean) |
42 """ |
44 """ |
43 super().__init__(parent) |
45 super().__init__(parent) |
44 |
46 |
45 self.progDir = None |
47 self.progDir = None |
46 self.watchedItems = {} |
48 self.watchedItems = {} |
82 item = index.internalPointer() |
84 item = index.internalPointer() |
83 if index.column() < item.columnCount(): |
85 if index.column() < item.columnCount(): |
84 return item.data(index.column()) |
86 return item.data(index.column()) |
85 elif index.column() == item.columnCount() and \ |
87 elif index.column() == item.columnCount() and \ |
86 index.column() < self.columnCount(self.parent(index)): |
88 index.column() < self.columnCount(self.parent(index)): |
87 # This is for the case where an item under a multi-column parent |
89 # This is for the case where an item under a multi-column |
88 # doesn't have a value for all the columns |
90 # parent doesn't have a value for all the columns |
89 return "" |
91 return "" |
90 elif role == Qt.DecorationRole: |
92 elif role == Qt.DecorationRole: |
91 if index.column() == 0: |
93 if index.column() == 0: |
92 return index.internalPointer().getIcon() |
94 return index.internalPointer().getIcon() |
93 elif role == Qt.FontRole: |
95 elif role == Qt.FontRole: |
282 if path not in self.watchedItems: |
284 if path not in self.watchedItems: |
283 # just ignore the situation we don't have a reference to the item |
285 # just ignore the situation we don't have a reference to the item |
284 return |
286 return |
285 |
287 |
286 if Preferences.getUI("BrowsersListHiddenFiles"): |
288 if Preferences.getUI("BrowsersListHiddenFiles"): |
287 filter = QDir.Filters(QDir.AllEntries | QDir.Hidden | QDir.NoDotAndDotDot) |
289 filter = QDir.Filters( |
|
290 QDir.AllEntries | QDir.Hidden | QDir.NoDotAndDotDot) |
288 else: |
291 else: |
289 filter = QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot) |
292 filter = QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot) |
290 |
293 |
291 for itm in self.watchedItems[path]: |
294 for itm in self.watchedItems[path]: |
292 oldCnt = itm.childCount() |
295 oldCnt = itm.childCount() |
350 self.toplevelDirs = [] |
353 self.toplevelDirs = [] |
351 tdp = Preferences.Prefs.settings.value('BrowserModel/ToplevelDirs') |
354 tdp = Preferences.Prefs.settings.value('BrowserModel/ToplevelDirs') |
352 if tdp: |
355 if tdp: |
353 self.toplevelDirs = tdp |
356 self.toplevelDirs = tdp |
354 else: |
357 else: |
355 self.toplevelDirs.append(Utilities.toNativeSeparators(QDir.homePath())) |
358 self.toplevelDirs.append( |
|
359 Utilities.toNativeSeparators(QDir.homePath())) |
356 for d in QDir.drives(): |
360 for d in QDir.drives(): |
357 self.toplevelDirs.append(Utilities.toNativeSeparators( |
361 self.toplevelDirs.append(Utilities.toNativeSeparators( |
358 d.absoluteFilePath())) |
362 d.absoluteFilePath())) |
359 |
363 |
360 for d in self.toplevelDirs: |
364 for d in self.toplevelDirs: |
361 itm = BrowserDirectoryItem(self.rootItem, d) |
365 itm = BrowserDirectoryItem(self.rootItem, d) |
362 self._addItem(itm, self.rootItem) |
366 self._addItem(itm, self.rootItem) |
363 |
367 |
364 def programChange(self, dirname): |
368 def programChange(self, dirname): |
365 """ |
369 """ |
366 Public method to change the entry for the directory of file being debugged. |
370 Public method to change the entry for the directory of file being |
|
371 debugged. |
367 |
372 |
368 @param dirname name of the directory containing the file (string) |
373 @param dirname name of the directory containing the file (string) |
369 """ |
374 """ |
370 if self.progDir: |
375 if self.progDir: |
371 if dirname == self.progDir.dirName(): |
376 if dirname == self.progDir.dirName(): |
372 return |
377 return |
373 |
378 |
374 # remove old entry |
379 # remove old entry |
375 self._removeWatchedItem(self.progDir) |
380 self._removeWatchedItem(self.progDir) |
376 self.beginRemoveRows(QModelIndex(), self.progDir.row(), self.progDir.row()) |
381 self.beginRemoveRows( |
|
382 QModelIndex(), self.progDir.row(), self.progDir.row()) |
377 self.rootItem.removeChild(self.progDir) |
383 self.rootItem.removeChild(self.progDir) |
378 self.endRemoveRows() |
384 self.endRemoveRows() |
379 self.progDir = None |
385 self.progDir = None |
380 |
386 |
381 itm = BrowserDirectoryItem(self.rootItem, dirname) |
387 itm = BrowserDirectoryItem(self.rootItem, dirname) |
395 |
401 |
396 def removeToplevelDir(self, index): |
402 def removeToplevelDir(self, index): |
397 """ |
403 """ |
398 Public method to remove a toplevel directory. |
404 Public method to remove a toplevel directory. |
399 |
405 |
400 @param index index of the toplevel directory to be removed (QModelIndex) |
406 @param index index of the toplevel directory to be removed |
|
407 (QModelIndex) |
401 """ |
408 """ |
402 if not index.isValid(): |
409 if not index.isValid(): |
403 return |
410 return |
404 |
411 |
405 item = index.internalPointer() |
412 item = index.internalPointer() |
473 self._addWatchedItem(parentItem) |
480 self._addWatchedItem(parentItem) |
474 |
481 |
475 qdir = QDir(parentItem.dirName()) |
482 qdir = QDir(parentItem.dirName()) |
476 |
483 |
477 if Preferences.getUI("BrowsersListHiddenFiles"): |
484 if Preferences.getUI("BrowsersListHiddenFiles"): |
478 filter = QDir.Filters(QDir.AllEntries | QDir.Hidden | QDir.NoDotAndDotDot) |
485 filter = QDir.Filters( |
|
486 QDir.AllEntries | QDir.Hidden | QDir.NoDotAndDotDot) |
479 else: |
487 else: |
480 filter = QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot) |
488 filter = QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot) |
481 entryInfoList = qdir.entryInfoList(filter) |
489 entryInfoList = qdir.entryInfoList(filter) |
482 if len(entryInfoList) > 0: |
490 if len(entryInfoList) > 0: |
483 if repopulate: |
491 if repopulate: |
484 self.beginInsertRows(self.createIndex(parentItem.row(), 0, parentItem), |
492 self.beginInsertRows( |
|
493 self.createIndex(parentItem.row(), 0, parentItem), |
485 0, len(entryInfoList) - 1) |
494 0, len(entryInfoList) - 1) |
486 for f in entryInfoList: |
495 for f in entryInfoList: |
487 if f.isDir(): |
496 if f.isDir(): |
488 node = BrowserDirectoryItem(parentItem, |
497 node = BrowserDirectoryItem(parentItem, |
489 Utilities.toNativeSeparators(f.absoluteFilePath()), |
498 Utilities.toNativeSeparators(f.absoluteFilePath()), |
490 False) |
499 False) |
491 else: |
500 else: |
492 fileFilters = Preferences.getUI("BrowsersFileFilters").split(";") |
501 fileFilters = \ |
|
502 Preferences.getUI("BrowsersFileFilters").split(";") |
493 if fileFilters: |
503 if fileFilters: |
494 fn = f.fileName() |
504 fn = f.fileName() |
495 if any([fnmatch.fnmatch(fn, ff.strip()) |
505 if any([fnmatch.fnmatch(fn, ff.strip()) |
496 for ff in fileFilters]): |
506 for ff in fileFilters]): |
497 continue |
507 continue |
508 @param parentItem reference to the sys.path item to be populated |
518 @param parentItem reference to the sys.path item to be populated |
509 @param repopulate flag indicating a repopulation (boolean) |
519 @param repopulate flag indicating a repopulation (boolean) |
510 """ |
520 """ |
511 if len(sys.path) > 0: |
521 if len(sys.path) > 0: |
512 if repopulate: |
522 if repopulate: |
513 self.beginInsertRows(self.createIndex(parentItem.row(), 0, parentItem), |
523 self.beginInsertRows( |
|
524 self.createIndex(parentItem.row(), 0, parentItem), |
514 0, len(sys.path) - 1) |
525 0, len(sys.path) - 1) |
515 for p in sys.path: |
526 for p in sys.path: |
516 if p == '': |
527 if p == '': |
517 p = os.getcwd() |
528 p = os.getcwd() |
518 |
529 |
539 return |
550 return |
540 |
551 |
541 keys = list(dict.keys()) |
552 keys = list(dict.keys()) |
542 if len(keys) > 0: |
553 if len(keys) > 0: |
543 if repopulate: |
554 if repopulate: |
544 self.beginInsertRows(self.createIndex(parentItem.row(), 0, parentItem), |
555 self.beginInsertRows( |
|
556 self.createIndex(parentItem.row(), 0, parentItem), |
545 0, len(keys) - 1) |
557 0, len(keys) - 1) |
546 for key in keys: |
558 for key in keys: |
547 if key.startswith("@@"): |
559 if key.startswith("@@"): |
548 # special treatment done later |
560 # special treatment done later |
549 continue |
561 continue |
587 for name in list(cl.methods.keys()): |
599 for name in list(cl.methods.keys()): |
588 keys.append((name, 'm')) |
600 keys.append((name, 'm')) |
589 |
601 |
590 if len(keys) > 0: |
602 if len(keys) > 0: |
591 if repopulate: |
603 if repopulate: |
592 self.beginInsertRows(self.createIndex(parentItem.row(), 0, parentItem), |
604 self.beginInsertRows( |
|
605 self.createIndex(parentItem.row(), 0, parentItem), |
593 0, len(keys) - 1) |
606 0, len(keys) - 1) |
594 for key, kind in keys: |
607 for key, kind in keys: |
595 if kind == 'c': |
608 if kind == 'c': |
596 node = BrowserClassItem(parentItem, cl.classes[key], file_) |
609 node = BrowserClassItem(parentItem, cl.classes[key], file_) |
597 elif kind == 'm': |
610 elif kind == 'm': |
598 node = BrowserMethodItem(parentItem, cl.methods[key], file_) |
611 node = BrowserMethodItem(parentItem, cl.methods[key], |
|
612 file_) |
599 self._addItem(node, parentItem) |
613 self._addItem(node, parentItem) |
600 if repopulate: |
614 if repopulate: |
601 self.endInsertRows() |
615 self.endInsertRows() |
602 |
616 |
603 if len(cl.attributes): |
617 if len(cl.attributes): |
641 for name in list(fn.methods.keys()): |
655 for name in list(fn.methods.keys()): |
642 keys.append((name, 'm')) |
656 keys.append((name, 'm')) |
643 |
657 |
644 if len(keys) > 0: |
658 if len(keys) > 0: |
645 if repopulate: |
659 if repopulate: |
646 self.beginInsertRows(self.createIndex(parentItem.row(), 0, parentItem), |
660 self.beginInsertRows( |
|
661 self.createIndex(parentItem.row(), 0, parentItem), |
647 0, len(keys) - 1) |
662 0, len(keys) - 1) |
648 for key, kind in keys: |
663 for key, kind in keys: |
649 if kind == 'c': |
664 if kind == 'c': |
650 node = BrowserClassItem(parentItem, fn.classes[key], file_) |
665 node = BrowserClassItem(parentItem, fn.classes[key], file_) |
651 elif kind == 'm': |
666 elif kind == 'm': |
652 node = BrowserMethodItem(parentItem, fn.methods[key], file_) |
667 node = BrowserMethodItem(parentItem, fn.methods[key], |
|
668 file_) |
653 self._addItem(node, parentItem) |
669 self._addItem(node, parentItem) |
654 if repopulate: |
670 if repopulate: |
655 self.endInsertRows() |
671 self.endInsertRows() |
656 |
672 |
657 def populateClassAttributesItem(self, parentItem, repopulate=False): |
673 def populateClassAttributesItem(self, parentItem, repopulate=False): |
658 """ |
674 """ |
659 Public method to populate a class attributes item's subtree. |
675 Public method to populate a class attributes item's subtree. |
660 |
676 |
661 @param parentItem reference to the class attributes item to be populated |
677 @param parentItem reference to the class attributes item to be |
|
678 populated |
662 @param repopulate flag indicating a repopulation (boolean) |
679 @param repopulate flag indicating a repopulation (boolean) |
663 """ |
680 """ |
664 classAttributes = parentItem.isClassAttributes() |
681 classAttributes = parentItem.isClassAttributes() |
665 attributes = parentItem.attributes() |
682 attributes = parentItem.attributes() |
666 if not attributes: |
683 if not attributes: |
667 return |
684 return |
668 |
685 |
669 keys = list(attributes.keys()) |
686 keys = list(attributes.keys()) |
670 if len(keys) > 0: |
687 if len(keys) > 0: |
671 if repopulate: |
688 if repopulate: |
672 self.beginInsertRows(self.createIndex(parentItem.row(), 0, parentItem), |
689 self.beginInsertRows( |
|
690 self.createIndex(parentItem.row(), 0, parentItem), |
673 0, len(keys) - 1) |
691 0, len(keys) - 1) |
674 for key in keys: |
692 for key in keys: |
675 node = BrowserClassAttributeItem(parentItem, attributes[key], |
693 node = BrowserClassAttributeItem(parentItem, attributes[key], |
676 classAttributes) |
694 classAttributes) |
677 self._addItem(node, parentItem) |
695 self._addItem(node, parentItem) |
1081 Public method to check, if this file is a Python script. |
1099 Public method to check, if this file is a Python script. |
1082 |
1100 |
1083 @return flag indicating a Python file (boolean) |
1101 @return flag indicating a Python file (boolean) |
1084 """ |
1102 """ |
1085 return self.fileext in Preferences.getPython("PythonExtensions") or \ |
1103 return self.fileext in Preferences.getPython("PythonExtensions") or \ |
1086 (self.fileext == "" and self.sourceLanguage in ["Python", "Python2"]) |
1104 (self.fileext == "" and self.sourceLanguage in ["Python", |
|
1105 "Python2"]) |
1087 |
1106 |
1088 def isPython3File(self): |
1107 def isPython3File(self): |
1089 """ |
1108 """ |
1090 Public method to check, if this file is a Python3 script. |
1109 Public method to check, if this file is a Python3 script. |
1091 |
1110 |
1197 if Preferences.getUI("BrowsersListFoldersFirst"): |
1216 if Preferences.getUI("BrowsersListFoldersFirst"): |
1198 return order == Qt.DescendingOrder |
1217 return order == Qt.DescendingOrder |
1199 |
1218 |
1200 if issubclass(other.__class__, BrowserFileItem): |
1219 if issubclass(other.__class__, BrowserFileItem): |
1201 sinit = os.path.basename(self._filename).startswith('__init__.py') |
1220 sinit = os.path.basename(self._filename).startswith('__init__.py') |
1202 oinit = os.path.basename(other.fileName()).startswith('__init__.py') |
1221 oinit = \ |
|
1222 os.path.basename(other.fileName()).startswith('__init__.py') |
1203 if sinit and not oinit: |
1223 if sinit and not oinit: |
1204 return order == Qt.AscendingOrder |
1224 return order == Qt.AscendingOrder |
1205 if not sinit and oinit: |
1225 if not sinit and oinit: |
1206 return order == Qt.DescendingOrder |
1226 return order == Qt.DescendingOrder |
1207 |
1227 |
1239 self.name = name |
1259 self.name = name |
1240 self._classObject = cl |
1260 self._classObject = cl |
1241 self._filename = filename |
1261 self._filename = filename |
1242 |
1262 |
1243 import Utilities.ClassBrowsers.ClbrBaseClasses |
1263 import Utilities.ClassBrowsers.ClbrBaseClasses |
1244 self.isfunction = isinstance(self._classObject, |
1264 self.isfunction = isinstance( |
1245 Utilities.ClassBrowsers.ClbrBaseClasses.Function) |
1265 self._classObject, |
1246 self.ismodule = isinstance(self._classObject, |
1266 Utilities.ClassBrowsers.ClbrBaseClasses.Function) |
1247 Utilities.ClassBrowsers.ClbrBaseClasses.Module) |
1267 self.ismodule = isinstance( |
|
1268 self._classObject, |
|
1269 Utilities.ClassBrowsers.ClbrBaseClasses.Module) |
1248 if self.isfunction: |
1270 if self.isfunction: |
1249 if cl.isPrivate(): |
1271 if cl.isPrivate(): |
1250 self.icon = UI.PixmapCache.getIcon("method_private.png") |
1272 self.icon = UI.PixmapCache.getIcon("method_private.png") |
1251 elif cl.isProtected(): |
1273 elif cl.isProtected(): |
1252 self.icon = UI.PixmapCache.getIcon("method_protected.png") |
1274 self.icon = UI.PixmapCache.getIcon("method_protected.png") |
1253 else: |
1275 else: |
1254 self.icon = UI.PixmapCache.getIcon("method.png") |
1276 self.icon = UI.PixmapCache.getIcon("method.png") |
1255 self.itemData[0] = "{0}({1})".format( |
1277 self.itemData[0] = "{0}({1})".format( |
1256 name, ", ".join(self._classObject.parameters)) |
1278 name, ", ".join(self._classObject.parameters)) |
1257 # if no defaults are wanted |
1279 # if no defaults are wanted |
1258 # ....format(name, ", ".join([e.split('=')[0].strip() \ |
1280 # ....format(name, |
1259 # for e in self._classObject.parameters])) |
1281 # ", ".join([e.split('=')[0].strip() \ |
|
1282 # for e in self._classObject.parameters])) |
1260 elif self.ismodule: |
1283 elif self.ismodule: |
1261 self.icon = UI.PixmapCache.getIcon("module.png") |
1284 self.icon = UI.PixmapCache.getIcon("module.png") |
1262 else: |
1285 else: |
1263 if cl.isPrivate(): |
1286 if cl.isPrivate(): |
1264 self.icon = UI.PixmapCache.getIcon("class_private.png") |
1287 self.icon = UI.PixmapCache.getIcon("class_private.png") |
1316 """ |
1339 """ |
1317 if issubclass(other.__class__, BrowserCodingItem) or \ |
1340 if issubclass(other.__class__, BrowserCodingItem) or \ |
1318 issubclass(other.__class__, BrowserClassAttributesItem): |
1341 issubclass(other.__class__, BrowserClassAttributesItem): |
1319 return order == Qt.DescendingOrder |
1342 return order == Qt.DescendingOrder |
1320 |
1343 |
1321 if Preferences.getUI("BrowsersListContentsByOccurrence") and column == 0: |
1344 if Preferences.getUI("BrowsersListContentsByOccurrence") and \ |
|
1345 column == 0: |
1322 if order == Qt.AscendingOrder: |
1346 if order == Qt.AscendingOrder: |
1323 return self.lineno() < other.lineno() |
1347 return self.lineno() < other.lineno() |
1324 else: |
1348 else: |
1325 return self.lineno() > other.lineno() |
1349 return self.lineno() > other.lineno() |
1326 |
1350 |
1368 else: |
1392 else: |
1369 self.icon = UI.PixmapCache.getIcon("method.png") |
1393 self.icon = UI.PixmapCache.getIcon("method.png") |
1370 self.itemData[0] = "{0}({1})".format( |
1394 self.itemData[0] = "{0}({1})".format( |
1371 name, ", ".join(self._functionObject.parameters)) |
1395 name, ", ".join(self._functionObject.parameters)) |
1372 # if no defaults are wanted |
1396 # if no defaults are wanted |
1373 # ....format(name, ", ".join( |
1397 # ....format(name, |
1374 # [e.split('=')[0].strip() for e in self._functionObject.parameters])) |
1398 # ", ".join([e.split('=')[0].strip() |
|
1399 # for e in self._functionObject.parameters])) |
1375 if self._functionObject and \ |
1400 if self._functionObject and \ |
1376 (self._functionObject.methods or self._functionObject.classes): |
1401 (self._functionObject.methods or self._functionObject.classes): |
1377 self._populated = False |
1402 self._populated = False |
1378 self._lazyPopulation = True |
1403 self._lazyPopulation = True |
1379 |
1404 |
1424 if other.name.startswith('__init__'): |
1449 if other.name.startswith('__init__'): |
1425 return order == Qt.DescendingOrder |
1450 return order == Qt.DescendingOrder |
1426 elif issubclass(other.__class__, BrowserClassAttributesItem): |
1451 elif issubclass(other.__class__, BrowserClassAttributesItem): |
1427 return order == Qt.DescendingOrder |
1452 return order == Qt.DescendingOrder |
1428 |
1453 |
1429 if Preferences.getUI("BrowsersListContentsByOccurrence") and column == 0: |
1454 if Preferences.getUI("BrowsersListContentsByOccurrence") and \ |
|
1455 column == 0: |
1430 if order == Qt.AscendingOrder: |
1456 if order == Qt.AscendingOrder: |
1431 return self.lineno() < other.lineno() |
1457 return self.lineno() < other.lineno() |
1432 else: |
1458 else: |
1433 return self.lineno() > other.lineno() |
1459 return self.lineno() > other.lineno() |
1434 |
1460 |
1575 @param other reference to item to compare against (BrowserItem) |
1601 @param other reference to item to compare against (BrowserItem) |
1576 @param column column number to use for the comparison (integer) |
1602 @param column column number to use for the comparison (integer) |
1577 @param order sort order (Qt.SortOrder) (for special sorting) |
1603 @param order sort order (Qt.SortOrder) (for special sorting) |
1578 @return true, if this item is less than other (boolean) |
1604 @return true, if this item is less than other (boolean) |
1579 """ |
1605 """ |
1580 if Preferences.getUI("BrowsersListContentsByOccurrence") and column == 0: |
1606 if Preferences.getUI("BrowsersListContentsByOccurrence") and \ |
|
1607 column == 0: |
1581 if order == Qt.AscendingOrder: |
1608 if order == Qt.AscendingOrder: |
1582 return self.lineno() < other.lineno() |
1609 return self.lineno() < other.lineno() |
1583 else: |
1610 else: |
1584 return self.lineno() > other.lineno() |
1611 return self.lineno() > other.lineno() |
1585 |
1612 |