eric6/UI/BrowserModel.py

changeset 7264
bedbe458d792
parent 7249
0bf517e60f54
child 7360
9190402e4505
equal deleted inserted replaced
7263:c1af2e327675 7264:bedbe458d792
10 10
11 import os 11 import os
12 import fnmatch 12 import fnmatch
13 import json 13 import json
14 14
15 from PyQt5.QtCore import QDir, QModelIndex, QAbstractItemModel, \ 15 from PyQt5.QtCore import (
16 QFileSystemWatcher, Qt, QProcess, QCoreApplication 16 QDir, QModelIndex, QAbstractItemModel, QFileSystemWatcher, Qt, QProcess,
17 QCoreApplication
18 )
17 from PyQt5.QtGui import QImageReader, QFont 19 from PyQt5.QtGui import QImageReader, QFont
18 from PyQt5.QtWidgets import QApplication 20 from PyQt5.QtWidgets import QApplication
19 21
20 import UI.PixmapCache 22 import UI.PixmapCache
21 import Preferences 23 import Preferences
92 94
93 if role == Qt.DisplayRole: 95 if role == Qt.DisplayRole:
94 item = index.internalPointer() 96 item = index.internalPointer()
95 if index.column() < item.columnCount(): 97 if index.column() < item.columnCount():
96 return item.data(index.column()) 98 return item.data(index.column())
97 elif index.column() == item.columnCount() and \ 99 elif (
98 index.column() < self.columnCount(self.parent(index)): 100 index.column() == item.columnCount() and
101 index.column() < self.columnCount(self.parent(index))
102 ):
99 # This is for the case where an item under a multi-column 103 # This is for the case where an item under a multi-column
100 # parent doesn't have a value for all the columns 104 # parent doesn't have a value for all the columns
101 return "" 105 return ""
102 elif role == Qt.DecorationRole: 106 elif role == Qt.DecorationRole:
103 if index.column() == 0: 107 if index.column() == 0:
153 parent = QModelIndex() 157 parent = QModelIndex()
154 158
155 # The model/view framework considers negative values out-of-bounds, 159 # The model/view framework considers negative values out-of-bounds,
156 # however in python they work when indexing into lists. So make sure 160 # however in python they work when indexing into lists. So make sure
157 # we return an invalid index for out-of-bounds row/col 161 # we return an invalid index for out-of-bounds row/col
158 if row < 0 or column < 0 or \ 162 if (
159 row >= self.rowCount(parent) or column >= self.columnCount(parent): 163 row < 0 or
164 column < 0 or
165 row >= self.rowCount(parent) or
166 column >= self.columnCount(parent)
167 ):
160 return QModelIndex() 168 return QModelIndex()
161 169
162 if not parent.isValid(): 170 if not parent.isValid():
163 parentItem = self.rootItem 171 parentItem = self.rootItem
164 else: 172 else:
267 275
268 @param itm item to be watched (BrowserDirectoryItem) 276 @param itm item to be watched (BrowserDirectoryItem)
269 """ 277 """
270 if isinstance(itm, BrowserDirectoryItem): 278 if isinstance(itm, BrowserDirectoryItem):
271 dirName = itm.dirName() 279 dirName = itm.dirName()
272 if dirName != "" and \ 280 if (
273 not dirName.startswith("//") and \ 281 dirName != "" and
274 not dirName.startswith("\\\\"): 282 not dirName.startswith("//") and
283 not dirName.startswith("\\\\")
284 ):
275 if dirName not in self.watcher.directories(): 285 if dirName not in self.watcher.directories():
276 self.watcher.addPath(dirName) 286 self.watcher.addPath(dirName)
277 if dirName in self.watchedItems: 287 if dirName in self.watchedItems:
278 if itm not in self.watchedItems[dirName]: 288 if itm not in self.watchedItems[dirName]:
279 self.watchedItems[dirName].append(itm) 289 self.watchedItems[dirName].append(itm)
557 node = BrowserDirectoryItem( 567 node = BrowserDirectoryItem(
558 parentItem, 568 parentItem,
559 Utilities.toNativeSeparators(f.absoluteFilePath()), 569 Utilities.toNativeSeparators(f.absoluteFilePath()),
560 False) 570 False)
561 else: 571 else:
562 fileFilters = \ 572 fileFilters = Preferences.getUI(
563 Preferences.getUI("BrowsersFileFilters").split(";") 573 "BrowsersFileFilters").split(";")
564 if fileFilters: 574 if fileFilters:
565 fn = f.fileName() 575 fn = f.fileName()
566 if any(fnmatch.fnmatch(fn, ff.strip()) 576 if any(fnmatch.fnmatch(fn, ff.strip())
567 for ff in fileFilters): 577 for ff in fileFilters):
568 continue 578 continue
656 node = BrowserImportsItem( 666 node = BrowserImportsItem(
657 parentItem, 667 parentItem,
658 QCoreApplication.translate("BrowserModel", "Imports")) 668 QCoreApplication.translate("BrowserModel", "Imports"))
659 self._addItem(node, parentItem) 669 self._addItem(node, parentItem)
660 if "@@Import@@" in keys: 670 if "@@Import@@" in keys:
661 for importedModule in \ 671 for importedModule in (
662 dictionary["@@Import@@"].getImports().values(): 672 dictionary["@@Import@@"].getImports().values()
673 ):
663 m_node = BrowserImportItem( 674 m_node = BrowserImportItem(
664 node, 675 node,
665 importedModule.importedModuleName, 676 importedModule.importedModuleName,
666 importedModule.file, 677 importedModule.file,
667 importedModule.linenos) 678 importedModule.linenos)
668 self._addItem(m_node, node) 679 self._addItem(m_node, node)
669 for importedName, linenos in \ 680 for importedName, linenos in (
670 importedModule.importedNames.items(): 681 importedModule.importedNames.items()
682 ):
671 mn_node = BrowserImportItem( 683 mn_node = BrowserImportItem(
672 m_node, 684 m_node,
673 importedName, 685 importedName,
674 importedModule.file, 686 importedModule.file,
675 linenos, 687 linenos,
985 dn = os.path.basename(self._dirName) 997 dn = os.path.basename(self._dirName)
986 998
987 BrowserItem.__init__(self, parent, dn) 999 BrowserItem.__init__(self, parent, dn)
988 1000
989 self.type_ = BrowserItemDirectory 1001 self.type_ = BrowserItemDirectory
990 if not Utilities.isDrive(self._dirName) and \ 1002 if (
991 os.path.lexists(self._dirName) and os.path.islink(self._dirName): 1003 not Utilities.isDrive(self._dirName) and
1004 os.path.lexists(self._dirName) and
1005 os.path.islink(self._dirName)
1006 ):
992 self.symlink = True 1007 self.symlink = True
993 self.icon = UI.PixmapCache.getSymlinkIcon("dirClosed.png") 1008 self.icon = UI.PixmapCache.getSymlinkIcon("dirClosed.png")
994 else: 1009 else:
995 self.icon = UI.PixmapCache.getIcon("dirClosed.png") 1010 self.icon = UI.PixmapCache.getIcon("dirClosed.png")
996 self._populated = False 1011 self._populated = False
1161 @param finfo the string for the file (string) 1176 @param finfo the string for the file (string)
1162 @param full flag indicating full pathname should be displayed (boolean) 1177 @param full flag indicating full pathname should be displayed (boolean)
1163 """ 1178 """
1164 self._filename = os.path.abspath(finfo) 1179 self._filename = os.path.abspath(finfo)
1165 self.itemData[0] = os.path.basename(finfo) 1180 self.itemData[0] = os.path.basename(finfo)
1166 if self.isPython2File() or self.isPython3File() or \ 1181 if (
1167 self.isRubyFile() or self.isIdlFile() or \ 1182 self.isPython2File() or
1168 self.isProtobufFile(): 1183 self.isPython3File() or
1184 self.isRubyFile() or
1185 self.isIdlFile() or
1186 self.isProtobufFile()
1187 ):
1169 self._dirName = os.path.dirname(finfo) 1188 self._dirName = os.path.dirname(finfo)
1170 self._moduleName = os.path.basename(finfo) 1189 self._moduleName = os.path.basename(finfo)
1171 1190
1172 def fileName(self): 1191 def fileName(self):
1173 """ 1192 """
1213 """ 1232 """
1214 Public method to check, if this file is a Python script. 1233 Public method to check, if this file is a Python script.
1215 1234
1216 @return flag indicating a Python file (boolean) 1235 @return flag indicating a Python file (boolean)
1217 """ 1236 """
1218 return self.fileext in Preferences.getPython("PythonExtensions") or \ 1237 return (
1238 self.fileext in Preferences.getPython("PythonExtensions") or
1219 (self.fileext == "" and 1239 (self.fileext == "" and
1220 self.sourceLanguage in ["Python", "Python2"]) 1240 self.sourceLanguage in ["Python", "Python2"])
1241 )
1221 1242
1222 def isPython3File(self): 1243 def isPython3File(self):
1223 """ 1244 """
1224 Public method to check, if this file is a Python3 script. 1245 Public method to check, if this file is a Python3 script.
1225 1246
1226 @return flag indicating a Python file (boolean) 1247 @return flag indicating a Python file (boolean)
1227 """ 1248 """
1228 return self.fileext in Preferences.getPython("Python3Extensions") or \ 1249 return (
1250 self.fileext in Preferences.getPython("Python3Extensions") or
1229 (self.fileext == "" and self.sourceLanguage == "Python3") 1251 (self.fileext == "" and self.sourceLanguage == "Python3")
1252 )
1230 1253
1231 def isRubyFile(self): 1254 def isRubyFile(self):
1232 """ 1255 """
1233 Public method to check, if this file is a Ruby script. 1256 Public method to check, if this file is a Ruby script.
1234 1257
1235 @return flag indicating a Ruby file (boolean) 1258 @return flag indicating a Ruby file (boolean)
1236 """ 1259 """
1237 return self.fileext == '.rb' or \ 1260 return (
1261 self.fileext == '.rb' or
1238 (self.fileext == "" and self.sourceLanguage == "Ruby") 1262 (self.fileext == "" and self.sourceLanguage == "Ruby")
1263 )
1239 1264
1240 def isDesignerFile(self): 1265 def isDesignerFile(self):
1241 """ 1266 """
1242 Public method to check, if this file is a Qt-Designer file. 1267 Public method to check, if this file is a Qt-Designer file.
1243 1268
1322 """ 1347 """
1323 Public method to check, if this file is a D file. 1348 Public method to check, if this file is a D file.
1324 1349
1325 @return flag indicating a D file (boolean) 1350 @return flag indicating a D file (boolean)
1326 """ 1351 """
1327 return self.fileext in ['.d', '.di'] or \ 1352 return (
1353 self.fileext in ['.d', '.di'] or
1328 (self.fileext == "" and self.sourceLanguage == "D") 1354 (self.fileext == "" and self.sourceLanguage == "D")
1355 )
1329 1356
1330 def lessThan(self, other, column, order): 1357 def lessThan(self, other, column, order):
1331 """ 1358 """
1332 Public method to check, if the item is less than the other one. 1359 Public method to check, if the item is less than the other one.
1333 1360
1340 if Preferences.getUI("BrowsersListFoldersFirst"): 1367 if Preferences.getUI("BrowsersListFoldersFirst"):
1341 return order == Qt.DescendingOrder 1368 return order == Qt.DescendingOrder
1342 1369
1343 if issubclass(other.__class__, BrowserFileItem): 1370 if issubclass(other.__class__, BrowserFileItem):
1344 sinit = os.path.basename(self._filename).startswith('__init__.py') 1371 sinit = os.path.basename(self._filename).startswith('__init__.py')
1345 oinit = \ 1372 oinit = os.path.basename(other.fileName()).startswith(
1346 os.path.basename(other.fileName()).startswith('__init__.py') 1373 '__init__.py')
1347 if sinit and not oinit: 1374 if sinit and not oinit:
1348 return order == Qt.AscendingOrder 1375 return order == Qt.AscendingOrder
1349 if not sinit and oinit: 1376 if not sinit and oinit:
1350 return order == Qt.DescendingOrder 1377 return order == Qt.DescendingOrder
1351 1378
1419 self.icon = UI.PixmapCache.getIcon("class_private.png") 1446 self.icon = UI.PixmapCache.getIcon("class_private.png")
1420 elif cl.isProtected(): 1447 elif cl.isProtected():
1421 self.icon = UI.PixmapCache.getIcon("class_protected.png") 1448 self.icon = UI.PixmapCache.getIcon("class_protected.png")
1422 else: 1449 else:
1423 self.icon = UI.PixmapCache.getIcon("class.png") 1450 self.icon = UI.PixmapCache.getIcon("class.png")
1424 if self._classObject and \ 1451 if (
1425 (self._classObject.methods or 1452 self._classObject and
1426 self._classObject.classes or 1453 (self._classObject.methods or
1427 self._classObject.attributes): 1454 self._classObject.classes or
1455 self._classObject.attributes)
1456 ):
1428 self._populated = False 1457 self._populated = False
1429 self._lazyPopulation = True 1458 self._lazyPopulation = True
1430 1459
1431 def name(self): 1460 def name(self):
1432 """ 1461 """
1475 @param other reference to item to compare against (BrowserItem) 1504 @param other reference to item to compare against (BrowserItem)
1476 @param column column number to use for the comparison (integer) 1505 @param column column number to use for the comparison (integer)
1477 @param order sort order (Qt.SortOrder) (for special sorting) 1506 @param order sort order (Qt.SortOrder) (for special sorting)
1478 @return true, if this item is less than other (boolean) 1507 @return true, if this item is less than other (boolean)
1479 """ 1508 """
1480 if issubclass(other.__class__, BrowserCodingItem) or \ 1509 if issubclass(
1481 issubclass(other.__class__, BrowserClassAttributesItem): 1510 other.__class__,
1511 (BrowserCodingItem, BrowserClassAttributesItem)
1512 ):
1482 return order == Qt.DescendingOrder 1513 return order == Qt.DescendingOrder
1483 1514
1484 if Preferences.getUI("BrowsersListContentsByOccurrence") and \ 1515 if (
1485 column == 0: 1516 Preferences.getUI("BrowsersListContentsByOccurrence") and
1517 column == 0
1518 ):
1486 if order == Qt.AscendingOrder: 1519 if order == Qt.AscendingOrder:
1487 return self.lineno() < other.lineno() 1520 return self.lineno() < other.lineno()
1488 else: 1521 else:
1489 return self.lineno() > other.lineno() 1522 return self.lineno() > other.lineno()
1490 1523
1517 import Utilities.ClassBrowsers.ClbrBaseClasses 1550 import Utilities.ClassBrowsers.ClbrBaseClasses
1518 self.type_ = BrowserItemMethod 1551 self.type_ = BrowserItemMethod
1519 self._name = name 1552 self._name = name
1520 self._functionObject = fn 1553 self._functionObject = fn
1521 self._filename = filename 1554 self._filename = filename
1522 if self._functionObject.modifier == \ 1555 if (
1523 Utilities.ClassBrowsers.ClbrBaseClasses.Function.Static: 1556 self._functionObject.modifier ==
1557 Utilities.ClassBrowsers.ClbrBaseClasses.Function.Static
1558 ):
1524 self.icon = UI.PixmapCache.getIcon("method_static.png") 1559 self.icon = UI.PixmapCache.getIcon("method_static.png")
1525 elif self._functionObject.modifier == \ 1560 elif (
1526 Utilities.ClassBrowsers.ClbrBaseClasses.Function.Class: 1561 self._functionObject.modifier ==
1562 Utilities.ClassBrowsers.ClbrBaseClasses.Function.Class
1563 ):
1527 self.icon = UI.PixmapCache.getIcon("method_class.png") 1564 self.icon = UI.PixmapCache.getIcon("method_class.png")
1528 elif self._functionObject.isPrivate(): 1565 elif self._functionObject.isPrivate():
1529 self.icon = UI.PixmapCache.getIcon("method_private.png") 1566 self.icon = UI.PixmapCache.getIcon("method_private.png")
1530 elif self._functionObject.isProtected(): 1567 elif self._functionObject.isProtected():
1531 self.icon = UI.PixmapCache.getIcon("method_protected.png") 1568 self.icon = UI.PixmapCache.getIcon("method_protected.png")
1538 self.itemData[0], self._functionObject.annotation) 1575 self.itemData[0], self._functionObject.annotation)
1539 # if no defaults are wanted 1576 # if no defaults are wanted
1540 # ....format(name, 1577 # ....format(name,
1541 # ", ".join([e.split('=')[0].strip() 1578 # ", ".join([e.split('=')[0].strip()
1542 # for e in self._functionObject.parameters])) 1579 # for e in self._functionObject.parameters]))
1543 if self._functionObject and \ 1580 if (
1544 (self._functionObject.methods or self._functionObject.classes): 1581 self._functionObject and
1582 (self._functionObject.methods or self._functionObject.classes)
1583 ):
1545 self._populated = False 1584 self._populated = False
1546 self._lazyPopulation = True 1585 self._lazyPopulation = True
1547 1586
1548 def name(self): 1587 def name(self):
1549 """ 1588 """
1600 if other._name.startswith('__init__'): 1639 if other._name.startswith('__init__'):
1601 return order == Qt.DescendingOrder 1640 return order == Qt.DescendingOrder
1602 elif issubclass(other.__class__, BrowserClassAttributesItem): 1641 elif issubclass(other.__class__, BrowserClassAttributesItem):
1603 return order == Qt.DescendingOrder 1642 return order == Qt.DescendingOrder
1604 1643
1605 if Preferences.getUI("BrowsersListContentsByOccurrence") and \ 1644 if (
1606 column == 0: 1645 Preferences.getUI("BrowsersListContentsByOccurrence") and
1646 column == 0
1647 ):
1607 if order == Qt.AscendingOrder: 1648 if order == Qt.AscendingOrder:
1608 return self.lineno() < other.lineno() 1649 return self.lineno() < other.lineno()
1609 else: 1650 else:
1610 return self.lineno() > other.lineno() 1651 return self.lineno() > other.lineno()
1611 1652
1678 @param order sort order (Qt.SortOrder) (for special sorting) 1719 @param order sort order (Qt.SortOrder) (for special sorting)
1679 @return true, if this item is less than other (boolean) 1720 @return true, if this item is less than other (boolean)
1680 """ 1721 """
1681 if issubclass(other.__class__, BrowserCodingItem): 1722 if issubclass(other.__class__, BrowserCodingItem):
1682 return order == Qt.DescendingOrder 1723 return order == Qt.DescendingOrder
1683 elif issubclass(other.__class__, BrowserClassItem) or \ 1724 elif issubclass(
1684 issubclass(other.__class__, BrowserMethodItem): 1725 other.__class__,
1726 (BrowserClassItem, BrowserMethodItem)
1727 ):
1685 return order == Qt.AscendingOrder 1728 return order == Qt.AscendingOrder
1686 1729
1687 return BrowserItem.lessThan(self, other, column, order) 1730 return BrowserItem.lessThan(self, other, column, order)
1688 1731
1689 1732
1760 @param other reference to item to compare against (BrowserItem) 1803 @param other reference to item to compare against (BrowserItem)
1761 @param column column number to use for the comparison (integer) 1804 @param column column number to use for the comparison (integer)
1762 @param order sort order (Qt.SortOrder) (for special sorting) 1805 @param order sort order (Qt.SortOrder) (for special sorting)
1763 @return true, if this item is less than other (boolean) 1806 @return true, if this item is less than other (boolean)
1764 """ 1807 """
1765 if Preferences.getUI("BrowsersListContentsByOccurrence") and \ 1808 if (
1766 column == 0: 1809 Preferences.getUI("BrowsersListContentsByOccurrence") and
1810 column == 0
1811 ):
1767 if order == Qt.AscendingOrder: 1812 if order == Qt.AscendingOrder:
1768 return self.lineno() < other.lineno() 1813 return self.lineno() < other.lineno()
1769 else: 1814 else:
1770 return self.lineno() > other.lineno() 1815 return self.lineno() > other.lineno()
1771 1816
1810 @param other reference to item to compare against (BrowserItem) 1855 @param other reference to item to compare against (BrowserItem)
1811 @param column column number to use for the comparison (integer) 1856 @param column column number to use for the comparison (integer)
1812 @param order sort order (Qt.SortOrder) (for special sorting) 1857 @param order sort order (Qt.SortOrder) (for special sorting)
1813 @return true, if this item is less than other (boolean) 1858 @return true, if this item is less than other (boolean)
1814 """ 1859 """
1815 if issubclass(other.__class__, BrowserClassItem) or \ 1860 if issubclass(
1816 issubclass(other.__class__, BrowserClassAttributesItem) or \ 1861 other.__class__,
1817 issubclass(other.__class__, BrowserImportItem): 1862 (BrowserClassItem, BrowserClassAttributesItem, BrowserImportItem)
1863 ):
1818 return order == Qt.AscendingOrder 1864 return order == Qt.AscendingOrder
1819 1865
1820 return BrowserItem.lessThan(self, other, column, order) 1866 return BrowserItem.lessThan(self, other, column, order)
1821 1867
1822 1868
1843 @param other reference to item to compare against (BrowserItem) 1889 @param other reference to item to compare against (BrowserItem)
1844 @param column column number to use for the comparison (integer) 1890 @param column column number to use for the comparison (integer)
1845 @param order sort order (Qt.SortOrder) (for special sorting) 1891 @param order sort order (Qt.SortOrder) (for special sorting)
1846 @return true, if this item is less than other (boolean) 1892 @return true, if this item is less than other (boolean)
1847 """ 1893 """
1848 if issubclass(other.__class__, BrowserClassItem) or \ 1894 if issubclass(
1849 issubclass(other.__class__, BrowserClassAttributesItem): 1895 other.__class__,
1896 (BrowserClassItem, BrowserClassAttributesItem)
1897 ):
1850 return order == Qt.AscendingOrder 1898 return order == Qt.AscendingOrder
1851 1899
1852 return BrowserItem.lessThan(self, other, column, order) 1900 return BrowserItem.lessThan(self, other, column, order)
1853 1901
1854 1902
1910 @param other reference to item to compare against (BrowserItem) 1958 @param other reference to item to compare against (BrowserItem)
1911 @param column column number to use for the comparison (integer) 1959 @param column column number to use for the comparison (integer)
1912 @param order sort order (Qt.SortOrder) (for special sorting) 1960 @param order sort order (Qt.SortOrder) (for special sorting)
1913 @return true, if this item is less than other (boolean) 1961 @return true, if this item is less than other (boolean)
1914 """ 1962 """
1915 if Preferences.getUI("BrowsersListContentsByOccurrence") and \ 1963 if (
1916 column == 0: 1964 Preferences.getUI("BrowsersListContentsByOccurrence") and
1965 column == 0
1966 ):
1917 if order == Qt.AscendingOrder: 1967 if order == Qt.AscendingOrder:
1918 return self.lineno() < other.lineno() 1968 return self.lineno() < other.lineno()
1919 else: 1969 else:
1920 return self.lineno() > other.lineno() 1970 return self.lineno() > other.lineno()
1921 1971

eric ide

mercurial