eric6/UI/BrowserModel.py

branch
maintenance
changeset 8273
698ae46f40a4
parent 8176
31965986ecd1
parent 8270
6ba3564b7161
child 8400
b3eefd7e58d1
equal deleted inserted replaced
8190:fb0ef164f536 8273:698ae46f40a4
8 """ 8 """
9 9
10 import os 10 import os
11 import fnmatch 11 import fnmatch
12 import json 12 import json
13 import contextlib
13 14
14 from PyQt5.QtCore import ( 15 from PyQt5.QtCore import (
15 QDir, QModelIndex, QAbstractItemModel, QFileSystemWatcher, Qt, QProcess, 16 QDir, QModelIndex, QAbstractItemModel, QFileSystemWatcher, Qt, QProcess,
16 QCoreApplication 17 QCoreApplication
17 ) 18 )
45 46
46 @param parent reference to parent object (QObject) 47 @param parent reference to parent object (QObject)
47 @param nopopulate flag indicating to not populate the model 48 @param nopopulate flag indicating to not populate the model
48 (boolean) 49 (boolean)
49 """ 50 """
50 super(BrowserModel, self).__init__(parent) 51 super().__init__(parent)
51 52
52 self.progDir = None 53 self.progDir = None
53 54
54 self.__sysPathInterpreter = "" 55 self.__sysPathInterpreter = ""
55 self.__sysPathItem = None 56 self.__sysPathItem = None
74 @return number of columns (integer) 75 @return number of columns (integer)
75 """ 76 """
76 if parent is None: 77 if parent is None:
77 parent = QModelIndex() 78 parent = QModelIndex()
78 79
79 if parent.isValid(): 80 item = (parent.internalPointer() if parent.isValid()
80 item = parent.internalPointer() 81 else self.rootItem)
81 else:
82 item = self.rootItem
83 82
84 return item.columnCount() + 1 83 return item.columnCount() + 1
85 84
86 def data(self, index, role): 85 def data(self, index, role):
87 """ 86 """
171 row >= self.rowCount(parent) or 170 row >= self.rowCount(parent) or
172 column >= self.columnCount(parent) 171 column >= self.columnCount(parent)
173 ): 172 ):
174 return QModelIndex() 173 return QModelIndex()
175 174
176 if not parent.isValid(): 175 parentItem = (
177 parentItem = self.rootItem 176 parent.internalPointer()
178 else: 177 if parent.isValid() else
179 parentItem = parent.internalPointer() 178 self.rootItem
179 )
180 180
181 try: 181 try:
182 if not parentItem.isPopulated(): 182 if not parentItem.isPopulated():
183 self.populateItem(parentItem) 183 self.populateItem(parentItem)
184 childItem = parentItem.child(row) 184 childItem = parentItem.child(row)
345 continue 345 continue
346 346
347 cnt = itm.childCount() 347 cnt = itm.childCount()
348 self.beginInsertRows( 348 self.beginInsertRows(
349 self.createIndex(itm.row(), 0, itm), cnt, cnt) 349 self.createIndex(itm.row(), 0, itm), cnt, cnt)
350 if f.isDir(): 350 node = (
351 node = BrowserDirectoryItem( 351 BrowserDirectoryItem(
352 itm, 352 itm,
353 Utilities.toNativeSeparators(f.absoluteFilePath()), 353 Utilities.toNativeSeparators(f.absoluteFilePath()),
354 False) 354 False)
355 else: 355 if f.isDir() else
356 node = BrowserFileItem( 356 BrowserFileItem(
357 itm, 357 itm,
358 Utilities.toNativeSeparators(f.absoluteFilePath())) 358 Utilities.toNativeSeparators(f.absoluteFilePath()))
359 )
359 self._addItem(node, itm) 360 self._addItem(node, itm)
360 self.endInsertRows() 361 self.endInsertRows()
361 362
362 # step 2: check for removed entries 363 # step 2: check for removed entries
363 if len(entryInfoList) != itm.childCount(): 364 if len(entryInfoList) != itm.childCount():
509 @param parent index of parent item (QModelIndex) 510 @param parent index of parent item (QModelIndex)
510 """ 511 """
511 if parent is None: 512 if parent is None:
512 parent = QModelIndex() 513 parent = QModelIndex()
513 514
514 if not parent.isValid(): 515 parentItem = (
515 parentItem = self.rootItem 516 parent.internalPointer()
516 else: 517 if parent.isValid() else
517 parentItem = parent.internalPointer() 518 self.rootItem
519 )
518 520
519 cnt = parentItem.childCount() 521 cnt = parentItem.childCount()
520 self.beginInsertRows(parent, cnt, cnt) 522 self.beginInsertRows(parent, cnt, cnt)
521 self._addItem(itm, parentItem) 523 self._addItem(itm, parentItem)
522 self.endInsertRows() 524 self.endInsertRows()
603 if repopulate: 605 if repopulate:
604 self.beginInsertRows( 606 self.beginInsertRows(
605 self.createIndex(parentItem.row(), 0, parentItem), 607 self.createIndex(parentItem.row(), 0, parentItem),
606 0, len(syspath) - 1) 608 0, len(syspath) - 1)
607 for p in syspath: 609 for p in syspath:
608 if os.path.isdir(p): 610 node = (
609 node = BrowserDirectoryItem(parentItem, p) 611 BrowserDirectoryItem(parentItem, p)
610 else: 612 if os.path.isdir(p) else
611 node = BrowserFileItem(parentItem, p) 613 BrowserFileItem(parentItem, p)
614 )
612 self._addItem(node, parentItem) 615 self._addItem(node, parentItem)
613 if repopulate: 616 if repopulate:
614 self.endInsertRows() 617 self.endInsertRows()
615 else: 618 else:
616 proc.kill() 619 proc.kill()
648 for key in keys: 651 for key in keys:
649 if key.startswith("@@"): 652 if key.startswith("@@"):
650 # special treatment done later 653 # special treatment done later
651 continue 654 continue
652 cl = dictionary[key] 655 cl = dictionary[key]
653 try: 656 with contextlib.suppress(AttributeError):
654 if cl.module == moduleName: 657 if cl.module == moduleName:
655 node = BrowserClassItem(parentItem, cl, fileName) 658 node = BrowserClassItem(parentItem, cl, fileName)
656 self._addItem(node, parentItem) 659 self._addItem(node, parentItem)
657 except AttributeError:
658 pass
659 if "@@Coding@@" in keys and Preferences.getUI("BrowserShowCoding"): 660 if "@@Coding@@" in keys and Preferences.getUI("BrowserShowCoding"):
660 node = BrowserCodingItem( 661 node = BrowserCodingItem(
661 parentItem, 662 parentItem,
662 QCoreApplication.translate("BrowserModel", "Coding: {0}") 663 QCoreApplication.translate("BrowserModel", "Coding: {0}")
663 .format(dictionary["@@Coding@@"].coding), 664 .format(dictionary["@@Coding@@"].coding),
858 self._addItem(node, parentItem) 859 self._addItem(node, parentItem)
859 if repopulate: 860 if repopulate:
860 self.endInsertRows() 861 self.endInsertRows()
861 862
862 863
863 class BrowserItem(object): 864 class BrowserItem:
864 """ 865 """
865 Class implementing the data structure for browser items. 866 Class implementing the data structure for browser items.
866 """ 867 """
867 def __init__(self, parent, data): 868 def __init__(self, parent, data):
868 """ 869 """
1042 @param parent parent item 1043 @param parent parent item
1043 @param dinfo dinfo is the string for the directory (string) 1044 @param dinfo dinfo is the string for the directory (string)
1044 @param full flag indicating full pathname should be displayed (boolean) 1045 @param full flag indicating full pathname should be displayed (boolean)
1045 """ 1046 """
1046 self._dirName = os.path.abspath(dinfo) 1047 self._dirName = os.path.abspath(dinfo)
1047 1048 dn = self._dirName if full else os.path.basename(self._dirName)
1048 if full:
1049 dn = self._dirName
1050 else:
1051 dn = os.path.basename(self._dirName)
1052
1053 BrowserItem.__init__(self, parent, dn) 1049 BrowserItem.__init__(self, parent, dn)
1054 1050
1055 self.type_ = BrowserItemDirectory 1051 self.type_ = BrowserItemDirectory
1056 if ( 1052 if (
1057 not Utilities.isDrive(self._dirName) and 1053 not Utilities.isDrive(self._dirName) and
1071 1067
1072 @param dinfo dinfo is the string for the directory (string) 1068 @param dinfo dinfo is the string for the directory (string)
1073 @param full flag indicating full pathname should be displayed (boolean) 1069 @param full flag indicating full pathname should be displayed (boolean)
1074 """ 1070 """
1075 self._dirName = os.path.abspath(dinfo) 1071 self._dirName = os.path.abspath(dinfo)
1076 1072 dn = self._dirName if full else os.path.basename(self._dirName)
1077 if full:
1078 dn = self._dirName
1079 else:
1080 dn = os.path.basename(self._dirName)
1081 self.itemData[0] = dn 1073 self.itemData[0] = dn
1082 1074
1083 def dirName(self): 1075 def dirName(self):
1084 """ 1076 """
1085 Public method returning the directory name. 1077 Public method returning the directory name.
1103 @param other reference to item to compare against (BrowserItem) 1095 @param other reference to item to compare against (BrowserItem)
1104 @param column column number to use for the comparison (integer) 1096 @param column column number to use for the comparison (integer)
1105 @param order sort order (Qt.SortOrder) (for special sorting) 1097 @param order sort order (Qt.SortOrder) (for special sorting)
1106 @return true, if this item is less than other (boolean) 1098 @return true, if this item is less than other (boolean)
1107 """ 1099 """
1108 if issubclass(other.__class__, BrowserFileItem): 1100 if (
1109 if Preferences.getUI("BrowsersListFoldersFirst"): 1101 issubclass(other.__class__, BrowserFileItem) and
1110 return order == Qt.SortOrder.AscendingOrder 1102 Preferences.getUI("BrowsersListFoldersFirst")
1103 ):
1104 return order == Qt.SortOrder.AscendingOrder
1111 1105
1112 return BrowserItem.lessThan(self, other, column, order) 1106 return BrowserItem.lessThan(self, other, column, order)
1113 1107
1114 1108
1115 class BrowserSysPathItem(BrowserItem): 1109 class BrowserSysPathItem(BrowserItem):
1159 self._dirName = os.path.dirname(finfo) 1153 self._dirName = os.path.dirname(finfo)
1160 self.sourceLanguage = sourceLanguage 1154 self.sourceLanguage = sourceLanguage
1161 1155
1162 self._moduleName = '' 1156 self._moduleName = ''
1163 1157
1158 # TODO: add icon for eric graphics file
1164 pixName = "" 1159 pixName = ""
1165 if self.isPython3File(): 1160 if self.isPython3File():
1166 pixName = "filePython" 1161 pixName = "filePython"
1167 self._populated = False 1162 self._populated = False
1168 self._lazyPopulation = True 1163 self._lazyPopulation = True
1304 1299
1305 def isRubyFile(self): 1300 def isRubyFile(self):
1306 """ 1301 """
1307 Public method to check, if this file is a Ruby script. 1302 Public method to check, if this file is a Ruby script.
1308 1303
1309 @return flag indicating a Ruby file (boolean) 1304 @return flag indicating a Ruby file
1305 @rtype bool
1310 """ 1306 """
1311 return ( 1307 return (
1312 self.fileext == '.rb' or 1308 self.fileext == '.rb' or
1313 (self.fileext == "" and self.sourceLanguage == "Ruby") 1309 (self.fileext == "" and self.sourceLanguage == "Ruby")
1314 ) 1310 )
1315 1311
1316 def isDesignerFile(self): 1312 def isDesignerFile(self):
1317 """ 1313 """
1318 Public method to check, if this file is a Qt-Designer file. 1314 Public method to check, if this file is a Qt-Designer file.
1319 1315
1320 @return flag indicating a Qt-Designer file (boolean) 1316 @return flag indicating a Qt-Designer file
1317 @rtype bool
1321 """ 1318 """
1322 return self.fileext == '.ui' 1319 return self.fileext == '.ui'
1323 1320
1324 def isLinguistFile(self): 1321 def isLinguistFile(self):
1325 """ 1322 """
1326 Public method to check, if this file is a Qt-Linguist file. 1323 Public method to check, if this file is a Qt-Linguist file.
1327 1324
1328 @return flag indicating a Qt-Linguist file (boolean) 1325 @return flag indicating a Qt-Linguist file
1326 @rtype bool
1329 """ 1327 """
1330 return self.fileext in ['.ts', '.qm'] 1328 return self.fileext in ['.ts', '.qm']
1331 1329
1332 def isResourcesFile(self): 1330 def isResourcesFile(self):
1333 """ 1331 """
1334 Public method to check, if this file is a Qt-Resources file. 1332 Public method to check, if this file is a Qt-Resources file.
1335 1333
1336 @return flag indicating a Qt-Resources file (boolean) 1334 @return flag indicating a Qt-Resources file
1335 @rtype bool
1337 """ 1336 """
1338 return self.fileext == '.qrc' 1337 return self.fileext == '.qrc'
1339 1338
1340 def isProjectFile(self): 1339 def isProjectFile(self):
1341 """ 1340 """
1342 Public method to check, if this file is an eric project file. 1341 Public method to check, if this file is an eric project file.
1343 1342
1344 @return flag indicating an eric project file (boolean) 1343 @return flag indicating an eric project file
1344 @rtype bool
1345 """ 1345 """
1346 return self.fileext in ('.epj', '.e4p') 1346 return self.fileext in ('.epj', '.e4p')
1347 1347
1348 def isMultiProjectFile(self): 1348 def isMultiProjectFile(self):
1349 """ 1349 """
1350 Public method to check, if this file is an eric multi project file. 1350 Public method to check, if this file is an eric multi project file.
1351 1351
1352 @return flag indicating an eric project file (boolean) 1352 @return flag indicating an eric project file
1353 @rtype bool
1353 """ 1354 """
1354 return self.fileext in ('.emj', '.e4m', '.e5m') 1355 return self.fileext in ('.emj', '.e4m', '.e5m')
1355 1356
1356 def isIdlFile(self): 1357 def isIdlFile(self):
1357 """ 1358 """
1358 Public method to check, if this file is a CORBA IDL file. 1359 Public method to check, if this file is a CORBA IDL file.
1359 1360
1360 @return flag indicating a CORBA IDL file (boolean) 1361 @return flag indicating a CORBA IDL file
1362 @rtype bool
1361 """ 1363 """
1362 return self.fileext == '.idl' 1364 return self.fileext == '.idl'
1363 1365
1364 def isProtobufFile(self): 1366 def isProtobufFile(self):
1365 """ 1367 """
1372 1374
1373 def isJavaScriptFile(self): 1375 def isJavaScriptFile(self):
1374 """ 1376 """
1375 Public method to check, if this file is a JavaScript file. 1377 Public method to check, if this file is a JavaScript file.
1376 1378
1377 @return flag indicating a JavaScript file (boolean) 1379 @return flag indicating a JavaScript file
1380 @rtype bool
1378 """ 1381 """
1379 return self.fileext == '.js' 1382 return self.fileext == '.js'
1380 1383
1381 def isPixmapFile(self): 1384 def isPixmapFile(self):
1382 """ 1385 """
1383 Public method to check, if this file is a pixmap file. 1386 Public method to check, if this file is a pixmap file.
1384 1387
1385 @return flag indicating a pixmap file (boolean) 1388 @return flag indicating a pixmap file
1389 @rtype bool
1386 """ 1390 """
1387 return self.fileext[1:] in QImageReader.supportedImageFormats() 1391 return self.fileext[1:] in QImageReader.supportedImageFormats()
1388 1392
1389 def isSvgFile(self): 1393 def isSvgFile(self):
1390 """ 1394 """
1391 Public method to check, if this file is a SVG file. 1395 Public method to check, if this file is a SVG file.
1392 1396
1393 @return flag indicating a SVG file (boolean) 1397 @return flag indicating a SVG file
1398 @rtype bool
1394 """ 1399 """
1395 return self.fileext == '.svg' 1400 return self.fileext == '.svg'
1396 1401
1397 def isDFile(self): 1402 def isDFile(self):
1398 """ 1403 """
1403 return ( 1408 return (
1404 self.fileext in ['.d', '.di'] or 1409 self.fileext in ['.d', '.di'] or
1405 (self.fileext == "" and self.sourceLanguage == "D") 1410 (self.fileext == "" and self.sourceLanguage == "D")
1406 ) 1411 )
1407 1412
1413 def isEricGraphicsFile(self):
1414 """
1415 Public method to check, if this is an eric graphics file.
1416
1417 @return flag indicating an eric graphics file
1418 @rtype bool
1419 """
1420 return self.fileext in ('.egj', '.e5g')
1421
1408 def lessThan(self, other, column, order): 1422 def lessThan(self, other, column, order):
1409 """ 1423 """
1410 Public method to check, if the item is less than the other one. 1424 Public method to check, if the item is less than the other one.
1411 1425
1412 @param other reference to item to compare against (BrowserItem) 1426 @param other reference to item to compare against (BrowserItem)
1413 @param column column number to use for the comparison (integer) 1427 @param column column number to use for the comparison (integer)
1414 @param order sort order (Qt.SortOrder) (for special sorting) 1428 @param order sort order (Qt.SortOrder) (for special sorting)
1415 @return true, if this item is less than other (boolean) 1429 @return true, if this item is less than other (boolean)
1416 """ 1430 """
1417 if not issubclass(other.__class__, BrowserFileItem): 1431 if (
1418 if Preferences.getUI("BrowsersListFoldersFirst"): 1432 not issubclass(other.__class__, BrowserFileItem) and
1419 return order == Qt.SortOrder.DescendingOrder 1433 Preferences.getUI("BrowsersListFoldersFirst")
1434 ):
1435 return order == Qt.SortOrder.DescendingOrder
1420 1436
1421 if issubclass(other.__class__, BrowserFileItem): 1437 if issubclass(other.__class__, BrowserFileItem):
1422 sinit = os.path.basename(self._filename).startswith('__init__.py') 1438 sinit = os.path.basename(self._filename).startswith('__init__.py')
1423 oinit = os.path.basename(other.fileName()).startswith( 1439 oinit = os.path.basename(other.fileName()).startswith(
1424 '__init__.py') 1440 '__init__.py')
1451 if sup.module != cl.module: 1467 if sup.module != cl.module:
1452 sname = "{0}.{1}".format(sup.module, sname) 1468 sname = "{0}.{1}".format(sup.module, sname)
1453 except AttributeError: 1469 except AttributeError:
1454 sname = sup 1470 sname = sup
1455 supers.append(sname) 1471 supers.append(sname)
1456 name = name + "({0})".format(", ".join(supers)) 1472 name += "({0})".format(", ".join(supers))
1457 1473
1458 BrowserItem.__init__(self, parent, name) 1474 BrowserItem.__init__(self, parent, name)
1459 1475
1460 self.type_ = BrowserItemClass 1476 self.type_ = BrowserItemClass
1461 self._name = name 1477 self._name = name

eric ide

mercurial