src/eric7/Project/Project.py

branch
eric7
changeset 9514
2b104ad132a4
parent 9512
6e29913ba7b6
child 9515
275334bc9607
equal deleted inserted replaced
9513:6e260b424396 9514:2b104ad132a4
481 self.dbgGlobalConfigOverride = { 481 self.dbgGlobalConfigOverride = {
482 "enable": False, 482 "enable": False,
483 "redirect": True, 483 "redirect": True,
484 } 484 }
485 485
486 self.pdata = { 486 self.__pdata = {
487 "DESCRIPTION": "", 487 "DESCRIPTION": "",
488 "VERSION": "", 488 "VERSION": "",
489 "SOURCES": [], 489 "SOURCES": [],
490 "FORMS": [], 490 "FORMS": [],
491 "RESOURCES": [], 491 "RESOURCES": [],
545 "DOCSTRING": "", 545 "DOCSTRING": "",
546 "TESTING_FRAMEWORK": "", 546 "TESTING_FRAMEWORK": "",
547 "LICENSE": "", 547 "LICENSE": "",
548 "EMBEDDED_VENV": False, 548 "EMBEDDED_VENV": False,
549 } 549 }
550 self.__knownFileCategories = [
551 "FORMS",
552 "OTHERS",
553 "RESOURCES",
554 "SOURCES",
555 "TRANSLATIONS",
556 "INTERFACES",
557 "PROTOCOLS",
558 ]
550 559
551 self.__initDebugProperties() 560 self.__initDebugProperties()
552 561
553 self.pudata = { 562 self.pudata = {
554 "VCSOVERRIDE": "", 563 "VCSOVERRIDE": "",
556 } 565 }
557 566
558 self.vcs = self.initVCS() 567 self.vcs = self.initVCS()
559 568
560 self.__initVenvConfiguration() 569 self.__initVenvConfiguration()
570
571 def getProjectData(self, dataKey=None, default=None):
572 """
573 Public method to get the data associated with the given data key.
574
575 Note: If dataKey is None, a copy of the project data structure
576 is returned.
577
578 @param dataKey key of the data to get (defaults to None)
579 @type str (optional)
580 @param default default value for non-existent keys (defaults to None)
581 @type Any (optional)
582 @return requested data or None if the data key doesn't exist or
583 a copy of the project data dictionary
584 @rtype Any
585 """
586 if dataKey is None:
587 return copy.deepcopy(self.__pdata)
588
589 try:
590 return self.__pdata[dataKey]
591 except KeyError:
592 return default
593
594 def setProjectData(self, data, dataKey=None):
595 """
596 Public method to set data associated with the given data key in the project
597 dictionary
598
599 Note: If no data key is given or is None, the data must be a dictionary used
600 to update the project data.
601
602 @param data data to be set or a dictionary to update the project data
603 @type Any
604 @param dataKey key of the data to set (defaults to None)
605 @type str (optional)
606 """
607 if dataKey is None:
608 self.__pdata.update(data)
609 else:
610 self.__pdata[dataKey] = data
611 self.setDirty(True)
561 612
562 def getData(self, category, key): 613 def getData(self, category, key):
563 """ 614 """
564 Public method to get data out of the project data store. 615 Public method to get data out of the project data store.
565 616
577 "CHECKERSPARMS", 628 "CHECKERSPARMS",
578 "PACKAGERSPARMS", 629 "PACKAGERSPARMS",
579 "DOCUMENTATIONPARMS", 630 "DOCUMENTATIONPARMS",
580 "OTHERTOOLSPARMS", 631 "OTHERTOOLSPARMS",
581 ] 632 ]
582 and key in self.pdata[category] 633 and key in self.__pdata[category]
583 ): 634 ):
584 return copy.deepcopy(self.pdata[category][key]) 635 return copy.deepcopy(self.__pdata[category][key])
585 else: 636 else:
586 return None 637 return None
587 638
588 def setData(self, category, key, data): 639 def setData(self, category, key, data):
589 """ 640 """
606 ]: 657 ]:
607 return False 658 return False
608 659
609 # test for changes of data and save them in the project 660 # test for changes of data and save them in the project
610 # 1. there were none, now there are 661 # 1. there were none, now there are
611 if key not in self.pdata[category] and len(data) > 0: 662 if key not in self.__pdata[category] and len(data) > 0:
612 self.pdata[category][key] = copy.deepcopy(data) 663 self.__pdata[category][key] = copy.deepcopy(data)
613 self.setDirty(True) 664 self.setDirty(True)
614 # 2. there were some, now there aren't 665 # 2. there were some, now there aren't
615 elif key in self.pdata[category] and len(data) == 0: 666 elif key in self.__pdata[category] and len(data) == 0:
616 del self.pdata[category][key] 667 del self.__pdata[category][key]
617 self.setDirty(True) 668 self.setDirty(True)
618 # 3. there were some and still are 669 # 3. there were some and still are
619 elif key in self.pdata[category] and len(data) > 0: 670 elif key in self.__pdata[category] and len(data) > 0:
620 if data != self.pdata[category][key]: 671 if data != self.__pdata[category][key]:
621 self.pdata[category][key] = copy.deepcopy(data) 672 self.__pdata[category][key] = copy.deepcopy(data)
622 self.setDirty(True) 673 self.setDirty(True)
623 # 4. there were none and none are given 674 # 4. there were none and none are given
624 else: 675 else:
625 return False 676 return False
626 return True 677 return True
627 678
679 def getFileCategories(self):
680 """
681 Public method to get the list of known file categories.
682
683 @return list of known file categories
684 @rtype list of str
685 """
686 return self.__knownFileCategories[:]
687
628 def initFileTypes(self): 688 def initFileTypes(self):
629 """ 689 """
630 Public method to initialize the filetype associations with default 690 Public method to initialize the filetype associations with default
631 values. 691 values.
632 """ 692 """
633 self.pdata["FILETYPES"] = { 693 self.__pdata["FILETYPES"] = {
634 "*.txt": "OTHERS", 694 "*.txt": "OTHERS",
635 "*.md": "OTHERS", 695 "*.md": "OTHERS",
636 "*.rst": "OTHERS", 696 "*.rst": "OTHERS",
637 "README": "OTHERS", 697 "README": "OTHERS",
638 "README.*": "OTHERS", 698 "README.*": "OTHERS",
643 "Makefile": "OTHERS", 703 "Makefile": "OTHERS",
644 } 704 }
645 705
646 # Sources 706 # Sources
647 sourceKey = ( 707 sourceKey = (
648 "Mixed" if self.pdata["MIXEDLANGUAGE"] else self.pdata["PROGLANGUAGE"] 708 "Mixed" if self.__pdata["MIXEDLANGUAGE"] else self.__pdata["PROGLANGUAGE"]
649 ) 709 )
650 for ext in self.__sourceExtensions(sourceKey): 710 for ext in self.__sourceExtensions(sourceKey):
651 self.pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES" 711 self.__pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES"
652 712
653 # IDL interfaces 713 # IDL interfaces
654 self.pdata["FILETYPES"]["*.idl"] = "INTERFACES" 714 self.__pdata["FILETYPES"]["*.idl"] = "INTERFACES"
655 715
656 # Protobuf Files 716 # Protobuf Files
657 self.pdata["FILETYPES"]["*.proto"] = "PROTOCOLS" 717 self.__pdata["FILETYPES"]["*.proto"] = "PROTOCOLS"
658 718
659 # Forms 719 # Forms
660 if self.pdata["PROJECTTYPE"] in [ 720 if self.__pdata["PROJECTTYPE"] in [
661 "E7Plugin", 721 "E7Plugin",
662 "PyQt5", 722 "PyQt5",
663 "PyQt6", 723 "PyQt6",
664 "PySide2", 724 "PySide2",
665 "PySide6", 725 "PySide6",
666 ]: 726 ]:
667 self.pdata["FILETYPES"]["*.ui"] = "FORMS" 727 self.__pdata["FILETYPES"]["*.ui"] = "FORMS"
668 728
669 # Resources 729 # Resources
670 if self.pdata["PROJECTTYPE"] in [ 730 if self.__pdata["PROJECTTYPE"] in [
671 "PyQt5", 731 "PyQt5",
672 "PyQt5C", 732 "PyQt5C",
673 "PySide2", 733 "PySide2",
674 "PySide2C", 734 "PySide2C",
675 "PySide6", 735 "PySide6",
676 "PySide6C", 736 "PySide6C",
677 ]: 737 ]:
678 self.pdata["FILETYPES"]["*.qrc"] = "RESOURCES" 738 self.__pdata["FILETYPES"]["*.qrc"] = "RESOURCES"
679 739
680 # Translations 740 # Translations
681 if self.pdata["PROJECTTYPE"] in [ 741 if self.__pdata["PROJECTTYPE"] in [
682 "E7Plugin", 742 "E7Plugin",
683 "PyQt5", 743 "PyQt5",
684 "PyQt5C", 744 "PyQt5C",
685 "PyQt6", 745 "PyQt6",
686 "PyQt6C", 746 "PyQt6C",
687 "PySide2", 747 "PySide2",
688 "PySide2C", 748 "PySide2C",
689 "PySide6", 749 "PySide6",
690 "PySide6C", 750 "PySide6C",
691 ]: 751 ]:
692 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" 752 self.__pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS"
693 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" 753 self.__pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS"
694 754
695 # Project type specific ones 755 # Project type specific ones
696 with contextlib.suppress(KeyError): 756 with contextlib.suppress(KeyError):
697 if self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]] is not None: 757 if self.__fileTypeCallbacks[self.__pdata["PROJECTTYPE"]] is not None:
698 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() 758 ftypes = self.__fileTypeCallbacks[self.__pdata["PROJECTTYPE"]]()
699 self.pdata["FILETYPES"].update(ftypes) 759 self.__pdata["FILETYPES"].update(ftypes)
700 760
701 self.setDirty(True) 761 self.setDirty(True)
702 762
703 def updateFileTypes(self): 763 def updateFileTypes(self):
704 """ 764 """
705 Public method to update the filetype associations with new default 765 Public method to update the filetype associations with new default
706 values. 766 values.
707 """ 767 """
708 if self.pdata["PROJECTTYPE"] in [ 768 if self.__pdata["PROJECTTYPE"] in [
709 "E7Plugin", 769 "E7Plugin",
710 "PyQt5", 770 "PyQt5",
711 "PyQt5C", 771 "PyQt5C",
712 "PyQt6", 772 "PyQt6",
713 "PyQt6C", 773 "PyQt6C",
714 "PySide2", 774 "PySide2",
715 "PySide2C", 775 "PySide2C",
716 "PySide6", 776 "PySide6",
717 "PySide6C", 777 "PySide6C",
718 ]: 778 ]:
719 if "*.ts" not in self.pdata["FILETYPES"]: 779 if "*.ts" not in self.__pdata["FILETYPES"]:
720 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" 780 self.__pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS"
721 if "*.qm" not in self.pdata["FILETYPES"]: 781 if "*.qm" not in self.__pdata["FILETYPES"]:
722 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" 782 self.__pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS"
723 with contextlib.suppress(KeyError): 783 with contextlib.suppress(KeyError):
724 if self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]] is not None: 784 if self.__fileTypeCallbacks[self.__pdata["PROJECTTYPE"]] is not None:
725 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() 785 ftypes = self.__fileTypeCallbacks[self.__pdata["PROJECTTYPE"]]()
726 for pattern, ftype in list(ftypes.items()): 786 for pattern, ftype in list(ftypes.items()):
727 if pattern not in self.pdata["FILETYPES"]: 787 if pattern not in self.__pdata["FILETYPES"]:
728 self.pdata["FILETYPES"][pattern] = ftype 788 self.__pdata["FILETYPES"][pattern] = ftype
729 self.setDirty(True) 789 self.setDirty(True)
730 790
731 def __loadRecent(self): 791 def __loadRecent(self):
732 """ 792 """
733 Private method to load the recently opened project filenames. 793 Private method to load the recently opened project filenames.
842 902
843 @param index key of the list to be checked (string) 903 @param index key of the list to be checked (string)
844 """ 904 """
845 removed = False 905 removed = False
846 removelist = [] 906 removelist = []
847 for file in self.pdata[index]: 907 for file in self.__pdata[index]:
848 if not os.path.exists(os.path.join(self.ppath, file)): 908 if not os.path.exists(os.path.join(self.ppath, file)):
849 removelist.append(file) 909 removelist.append(file)
850 removed = True 910 removed = True
851 911
852 if removed: 912 if removed:
853 for file in removelist: 913 for file in removelist:
854 self.pdata[index].remove(file) 914 self.__pdata[index].remove(file)
855 self.setDirty(True) 915 self.setDirty(True)
856 916
857 def __readProject(self, fn): 917 def __readProject(self, fn):
858 """ 918 """
859 Private method to read in a project (.epj or .e4p) file. 919 Private method to read in a project (.epj or .e4p) file.
873 reader.readXML() 933 reader.readXML()
874 res = not reader.hasError() 934 res = not reader.hasError()
875 f.close() 935 f.close()
876 936
877 # create hash value, if it doesn't have one 937 # create hash value, if it doesn't have one
878 if reader.version.startswith("5.") and not self.pdata["HASH"]: 938 if reader.version.startswith("5.") and not self.__pdata["HASH"]:
879 hashStr = str( 939 hashStr = str(
880 QCryptographicHash.hash( 940 QCryptographicHash.hash(
881 QByteArray(self.ppath.encode("utf-8")), 941 QByteArray(self.ppath.encode("utf-8")),
882 QCryptographicHash.Algorithm.Sha1, 942 QCryptographicHash.Algorithm.Sha1,
883 ).toHex(), 943 ).toHex(),
884 encoding="utf-8", 944 encoding="utf-8",
885 ) 945 )
886 self.pdata["HASH"] = hashStr 946 self.__pdata["HASH"] = hashStr
887 self.setDirty(True) 947 self.setDirty(True)
888 else: 948 else:
889 EricMessageBox.critical( 949 EricMessageBox.critical(
890 self.ui, 950 self.ui,
891 self.tr("Read Project File"), 951 self.tr("Read Project File"),
900 self.ppath = os.path.abspath(os.path.dirname(fn)) 960 self.ppath = os.path.abspath(os.path.dirname(fn))
901 961
902 # insert filename into list of recently opened projects 962 # insert filename into list of recently opened projects
903 self.__syncRecent() 963 self.__syncRecent()
904 964
905 if self.pdata["TRANSLATIONPATTERN"]: 965 if self.__pdata["TRANSLATIONPATTERN"]:
906 self.translationsRoot = self.pdata["TRANSLATIONPATTERN"].split( 966 self.translationsRoot = self.__pdata["TRANSLATIONPATTERN"].split(
907 "%language%" 967 "%language%"
908 )[0] 968 )[0]
909 elif self.pdata["MAINSCRIPT"]: 969 elif self.__pdata["MAINSCRIPT"]:
910 self.translationsRoot = os.path.splitext(self.pdata["MAINSCRIPT"])[0] 970 self.translationsRoot = os.path.splitext(self.__pdata["MAINSCRIPT"])[0]
911 if os.path.isdir(os.path.join(self.ppath, self.translationsRoot)): 971 if os.path.isdir(os.path.join(self.ppath, self.translationsRoot)):
912 dn = self.translationsRoot 972 dn = self.translationsRoot
913 else: 973 else:
914 dn = os.path.dirname(self.translationsRoot) 974 dn = os.path.dirname(self.translationsRoot)
915 if dn not in self.subdirs: 975 if dn not in self.subdirs:
917 977
918 self.name = os.path.splitext(os.path.basename(fn))[0] 978 self.name = os.path.splitext(os.path.basename(fn))[0]
919 979
920 # check, if the files of the project still exist in the 980 # check, if the files of the project still exist in the
921 # project directory 981 # project directory
922 self.__checkFilesExist("SOURCES") 982 for fileCategory in self.__knownFileCategories:
923 self.__checkFilesExist("FORMS") 983 self.__checkFilesExist(fileCategory)
924 self.__checkFilesExist("INTERFACES") 984 ##self.__checkFilesExist("SOURCES")
925 self.__checkFilesExist("PROTOCOLS") 985 ##self.__checkFilesExist("FORMS")
926 self.__checkFilesExist("TRANSLATIONS") 986 ##self.__checkFilesExist("INTERFACES")
927 self.__checkFilesExist("RESOURCES") 987 ##self.__checkFilesExist("PROTOCOLS")
928 self.__checkFilesExist("OTHERS") 988 ##self.__checkFilesExist("TRANSLATIONS")
989 ##self.__checkFilesExist("RESOURCES")
990 ##self.__checkFilesExist("OTHERS")
929 991
930 # get the names of subdirectories the files are stored in 992 # get the names of subdirectories the files are stored in
931 for fn in ( 993 for fileCategory in [
932 self.pdata["SOURCES"] 994 c for c in self.__knownFileCategories if c != "OTHERS"
933 + self.pdata["FORMS"] 995 ]:
934 + self.pdata["INTERFACES"] 996 for fn in self.__pdata[fileCategory]:
935 + self.pdata["PROTOCOLS"] 997 ##self.__pdata["SOURCES"]
936 + self.pdata["RESOURCES"] 998 ##+ self.__pdata["FORMS"]
937 + self.pdata["TRANSLATIONS"] 999 ##+ self.__pdata["INTERFACES"]
938 ): 1000 ##+ self.__pdata["PROTOCOLS"]
939 dn = os.path.dirname(fn) 1001 ##+ self.__pdata["RESOURCES"]
940 if dn not in self.subdirs: 1002 ##+ self.__pdata["TRANSLATIONS"]
941 self.subdirs.append(dn) 1003 ##):
1004 dn = os.path.dirname(fn)
1005 if dn not in self.subdirs:
1006 self.subdirs.append(dn)
942 1007
943 # get the names of other subdirectories 1008 # get the names of other subdirectories
944 for fn in self.pdata["OTHERS"]: 1009 for fn in self.__pdata["OTHERS"]:
945 dn = os.path.dirname(fn) 1010 dn = os.path.dirname(fn)
946 if dn not in self.otherssubdirs: 1011 if dn not in self.otherssubdirs:
947 self.otherssubdirs.append(dn) 1012 self.otherssubdirs.append(dn)
948 1013
949 return res 1014 return res
958 is used instead of the one in the project object. This is the 1023 is used instead of the one in the project object. This is the
959 'save as' action. 1024 'save as' action.
960 @return flag indicating success 1025 @return flag indicating success
961 """ 1026 """
962 if self.vcs is not None: 1027 if self.vcs is not None:
963 self.pdata["VCSOPTIONS"] = copy.deepcopy(self.vcs.vcsGetOptions()) 1028 self.__pdata["VCSOPTIONS"] = copy.deepcopy(self.vcs.vcsGetOptions())
964 self.pdata["VCSOTHERDATA"] = copy.deepcopy(self.vcs.vcsGetOtherData()) 1029 self.__pdata["VCSOTHERDATA"] = copy.deepcopy(self.vcs.vcsGetOtherData())
965 1030
966 if not self.pdata["HASH"]: 1031 if not self.__pdata["HASH"]:
967 hashStr = str( 1032 hashStr = str(
968 QCryptographicHash.hash( 1033 QCryptographicHash.hash(
969 QByteArray(self.ppath.encode("utf-8")), 1034 QByteArray(self.ppath.encode("utf-8")),
970 QCryptographicHash.Algorithm.Sha1, 1035 QCryptographicHash.Algorithm.Sha1,
971 ).toHex(), 1036 ).toHex(),
972 encoding="utf-8", 1037 encoding="utf-8",
973 ) 1038 )
974 self.pdata["HASH"] = hashStr 1039 self.__pdata["HASH"] = hashStr
975 1040
976 if fn is None: 1041 if fn is None:
977 fn = self.pfile 1042 fn = self.pfile
978 1043
979 with EricOverrideCursor(): 1044 with EricOverrideCursor():
1351 """ 1416 """
1352 Public method to return the status of the debug properties. 1417 Public method to return the status of the debug properties.
1353 1418
1354 @return load status of debug properties (boolean) 1419 @return load status of debug properties (boolean)
1355 """ 1420 """
1356 return self.debugPropertiesLoaded or self.pdata["EMBEDDED_VENV"] 1421 return self.debugPropertiesLoaded or self.__pdata["EMBEDDED_VENV"]
1357 1422
1358 def __showDebugProperties(self): 1423 def __showDebugProperties(self):
1359 """ 1424 """
1360 Private slot to display the debugger properties dialog. 1425 Private slot to display the debugger properties dialog.
1361 """ 1426 """
1456 """ 1521 """
1457 Public method to get the translation pattern. 1522 Public method to get the translation pattern.
1458 1523
1459 @return translation pattern (string) 1524 @return translation pattern (string)
1460 """ 1525 """
1461 return self.pdata["TRANSLATIONPATTERN"] 1526 return self.__pdata["TRANSLATIONPATTERN"]
1462 1527
1463 def setTranslationPattern(self, pattern): 1528 def setTranslationPattern(self, pattern):
1464 """ 1529 """
1465 Public method to set the translation pattern. 1530 Public method to set the translation pattern.
1466 1531
1467 @param pattern translation pattern 1532 @param pattern translation pattern
1468 @type str 1533 @type str
1469 """ 1534 """
1470 self.pdata["TRANSLATIONPATTERN"] = pattern 1535 self.__pdata["TRANSLATIONPATTERN"] = pattern
1471 1536
1472 def addLanguage(self): 1537 def addLanguage(self):
1473 """ 1538 """
1474 Public slot used to add a language to the project. 1539 Public slot used to add a language to the project.
1475 """ 1540 """
1476 from .AddLanguageDialog import AddLanguageDialog 1541 from .AddLanguageDialog import AddLanguageDialog
1477 1542
1478 if not self.pdata["TRANSLATIONPATTERN"]: 1543 if not self.__pdata["TRANSLATIONPATTERN"]:
1479 EricMessageBox.critical( 1544 EricMessageBox.critical(
1480 self.ui, 1545 self.ui,
1481 self.tr("Add Language"), 1546 self.tr("Add Language"),
1482 self.tr("You have to specify a translation pattern first."), 1547 self.tr("You have to specify a translation pattern first."),
1483 ) 1548 )
1484 return 1549 return
1485 1550
1486 dlg = AddLanguageDialog(self.parent()) 1551 dlg = AddLanguageDialog(self.parent())
1487 if dlg.exec() == QDialog.DialogCode.Accepted: 1552 if dlg.exec() == QDialog.DialogCode.Accepted:
1488 lang = dlg.getSelectedLanguage() 1553 lang = dlg.getSelectedLanguage()
1489 if self.pdata["PROJECTTYPE"] in [ 1554 if self.__pdata["PROJECTTYPE"] in [
1490 "PyQt5", 1555 "PyQt5",
1491 "PyQt5C", 1556 "PyQt5C",
1492 "PyQt6", 1557 "PyQt6",
1493 "PyQt6C", 1558 "PyQt6C",
1494 "E7Plugin", 1559 "E7Plugin",
1495 "PySide2", 1560 "PySide2",
1496 "PySide2C", 1561 "PySide2C",
1497 "PySide6", 1562 "PySide6",
1498 "PySide6C", 1563 "PySide6C",
1499 ]: 1564 ]:
1500 langFile = self.pdata["TRANSLATIONPATTERN"].replace("%language%", lang) 1565 langFile = self.__pdata["TRANSLATIONPATTERN"].replace(
1566 "%language%", lang
1567 )
1501 self.appendFile(langFile) 1568 self.appendFile(langFile)
1502 self.projectLanguageAddedByCode.emit(lang) 1569 self.projectLanguageAddedByCode.emit(lang)
1503 1570
1504 def __binaryTranslationFile(self, langFile): 1571 def __binaryTranslationFile(self, langFile):
1505 """ 1572 """
1510 @return name of the binary translations file (string) 1577 @return name of the binary translations file (string)
1511 """ 1578 """
1512 qmFile = "" 1579 qmFile = ""
1513 try: 1580 try:
1514 if ( 1581 if (
1515 self.__binaryTranslationsCallbacks[self.pdata["PROJECTTYPE"]] 1582 self.__binaryTranslationsCallbacks[self.__pdata["PROJECTTYPE"]]
1516 is not None 1583 is not None
1517 ): 1584 ):
1518 qmFile = self.__binaryTranslationsCallbacks[self.pdata["PROJECTTYPE"]]( 1585 qmFile = self.__binaryTranslationsCallbacks[
1519 langFile 1586 self.__pdata["PROJECTTYPE"]
1520 ) 1587 ](langFile)
1521 except KeyError: 1588 except KeyError:
1522 qmFile = langFile.replace(".ts", ".qm") 1589 qmFile = langFile.replace(".ts", ".qm")
1523 if qmFile == langFile: 1590 if qmFile == langFile:
1524 qmFile = "" 1591 qmFile = ""
1525 return qmFile 1592 return qmFile
1526 1593
1527 def checkLanguageFiles(self): 1594 def checkLanguageFiles(self):
1528 """ 1595 """
1529 Public slot to check the language files after a release process. 1596 Public slot to check the language files after a release process.
1530 """ 1597 """
1531 tbPath = self.pdata["TRANSLATIONSBINPATH"] 1598 tbPath = self.__pdata["TRANSLATIONSBINPATH"]
1532 for langFile in self.pdata["TRANSLATIONS"][:]: 1599 for langFile in self.__pdata["TRANSLATIONS"][:]:
1533 qmFile = self.__binaryTranslationFile(langFile) 1600 qmFile = self.__binaryTranslationFile(langFile)
1534 if qmFile: 1601 if qmFile:
1535 if qmFile not in self.pdata["TRANSLATIONS"] and os.path.exists( 1602 if qmFile not in self.__pdata["TRANSLATIONS"] and os.path.exists(
1536 os.path.join(self.ppath, qmFile) 1603 os.path.join(self.ppath, qmFile)
1537 ): 1604 ):
1538 self.appendFile(qmFile) 1605 self.appendFile(qmFile)
1539 if tbPath: 1606 if tbPath:
1540 qmFile = os.path.join(tbPath, os.path.basename(qmFile)) 1607 qmFile = os.path.join(tbPath, os.path.basename(qmFile))
1541 if qmFile not in self.pdata["TRANSLATIONS"] and os.path.exists( 1608 if qmFile not in self.__pdata["TRANSLATIONS"] and os.path.exists(
1542 os.path.join(self.ppath, qmFile) 1609 os.path.join(self.ppath, qmFile)
1543 ): 1610 ):
1544 self.appendFile(qmFile) 1611 self.appendFile(qmFile)
1545 1612
1546 def removeLanguageFile(self, langFile): 1613 def removeLanguageFile(self, langFile):
1551 1618
1552 @param langFile the translation file to be removed (string) 1619 @param langFile the translation file to be removed (string)
1553 """ 1620 """
1554 langFile = self.getRelativePath(langFile) 1621 langFile = self.getRelativePath(langFile)
1555 qmFile = self.__binaryTranslationFile(langFile) 1622 qmFile = self.__binaryTranslationFile(langFile)
1556 self.pdata["TRANSLATIONS"].remove(langFile) 1623 self.__pdata["TRANSLATIONS"].remove(langFile)
1557 self.__model.removeItem(langFile) 1624 self.__model.removeItem(langFile)
1558 if qmFile: 1625 if qmFile:
1559 with contextlib.suppress(ValueError): 1626 with contextlib.suppress(ValueError):
1560 if self.pdata["TRANSLATIONSBINPATH"]: 1627 if self.__pdata["TRANSLATIONSBINPATH"]:
1561 qmFile = self.getRelativePath( 1628 qmFile = self.getRelativePath(
1562 os.path.join( 1629 os.path.join(
1563 self.pdata["TRANSLATIONSBINPATH"], os.path.basename(qmFile) 1630 self.__pdata["TRANSLATIONSBINPATH"],
1631 os.path.basename(qmFile),
1564 ) 1632 )
1565 ) 1633 )
1566 self.pdata["TRANSLATIONS"].remove(qmFile) 1634 self.__pdata["TRANSLATIONS"].remove(qmFile)
1567 self.__model.removeItem(qmFile) 1635 self.__model.removeItem(qmFile)
1568 self.setDirty(True) 1636 self.setDirty(True)
1569 1637
1570 def deleteLanguageFile(self, langFile): 1638 def deleteLanguageFile(self, langFile):
1571 """ 1639 """
1599 self.removeLanguageFile(langFile) 1667 self.removeLanguageFile(langFile)
1600 1668
1601 # now get rid of the .qm file 1669 # now get rid of the .qm file
1602 if qmFile: 1670 if qmFile:
1603 try: 1671 try:
1604 if self.pdata["TRANSLATIONSBINPATH"]: 1672 if self.__pdata["TRANSLATIONSBINPATH"]:
1605 qmFile = self.getRelativePath( 1673 qmFile = self.getRelativePath(
1606 os.path.join( 1674 os.path.join(
1607 self.pdata["TRANSLATIONSBINPATH"], os.path.basename(qmFile) 1675 self.__pdata["TRANSLATIONSBINPATH"],
1676 os.path.basename(qmFile),
1608 ) 1677 )
1609 ) 1678 )
1610 fn = os.path.join(self.ppath, qmFile) 1679 fn = os.path.join(self.ppath, qmFile)
1611 if os.path.exists(fn): 1680 if os.path.exists(fn):
1612 s2t(fn) 1681 s2t(fn)
1644 filetype = "OTHERS" 1713 filetype = "OTHERS"
1645 bfn = os.path.basename(newfn) 1714 bfn = os.path.basename(newfn)
1646 if fnmatch.fnmatch(bfn, "*.ts") or fnmatch.fnmatch(bfn, "*.qm"): 1715 if fnmatch.fnmatch(bfn, "*.ts") or fnmatch.fnmatch(bfn, "*.qm"):
1647 filetype = "TRANSLATIONS" 1716 filetype = "TRANSLATIONS"
1648 else: 1717 else:
1649 for pattern in sorted(self.pdata["FILETYPES"].keys(), reverse=True): 1718 for pattern in sorted(self.__pdata["FILETYPES"].keys(), reverse=True):
1650 if fnmatch.fnmatch(bfn, pattern): 1719 if fnmatch.fnmatch(bfn, pattern):
1651 filetype = self.pdata["FILETYPES"][pattern] 1720 filetype = self.__pdata["FILETYPES"][pattern]
1652 break 1721 break
1653 1722
1654 if filetype == "__IGNORE__": 1723 if filetype == "__IGNORE__":
1655 return 1724 return
1656 1725
1726 # TODO: change this logic to be more generic (use fileCategory)
1657 if filetype in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES"]: 1727 if filetype in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES"]:
1658 if filetype == "SOURCES": 1728 if filetype == "SOURCES":
1659 if newfn not in self.pdata["SOURCES"]: 1729 if newfn not in self.__pdata["SOURCES"]:
1660 self.pdata["SOURCES"].append(newfn) 1730 self.__pdata["SOURCES"].append(newfn)
1661 self.projectSourceAdded.emit(newfn) 1731 self.projectSourceAdded.emit(newfn)
1662 updateModel and self.__model.addNewItem("SOURCES", newfn) 1732 updateModel and self.__model.addNewItem("SOURCES", newfn)
1663 dirty = True 1733 dirty = True
1664 else: 1734 else:
1665 updateModel and self.repopulateItem(newfn) 1735 updateModel and self.repopulateItem(newfn)
1666 elif filetype == "FORMS": 1736 elif filetype == "FORMS":
1667 if newfn not in self.pdata["FORMS"]: 1737 if newfn not in self.__pdata["FORMS"]:
1668 self.pdata["FORMS"].append(newfn) 1738 self.__pdata["FORMS"].append(newfn)
1669 self.projectFormAdded.emit(newfn) 1739 self.projectFormAdded.emit(newfn)
1670 updateModel and self.__model.addNewItem("FORMS", newfn) 1740 updateModel and self.__model.addNewItem("FORMS", newfn)
1671 dirty = True 1741 dirty = True
1672 else: 1742 else:
1673 updateModel and self.repopulateItem(newfn) 1743 updateModel and self.repopulateItem(newfn)
1674 elif filetype == "INTERFACES": 1744 elif filetype == "INTERFACES":
1675 if newfn not in self.pdata["INTERFACES"]: 1745 if newfn not in self.__pdata["INTERFACES"]:
1676 self.pdata["INTERFACES"].append(newfn) 1746 self.__pdata["INTERFACES"].append(newfn)
1677 self.projectInterfaceAdded.emit(newfn) 1747 self.projectInterfaceAdded.emit(newfn)
1678 (updateModel and self.__model.addNewItem("INTERFACES", newfn)) 1748 (updateModel and self.__model.addNewItem("INTERFACES", newfn))
1679 dirty = True 1749 dirty = True
1680 else: 1750 else:
1681 updateModel and self.repopulateItem(newfn) 1751 updateModel and self.repopulateItem(newfn)
1682 elif filetype == "PROTOCOLS": 1752 elif filetype == "PROTOCOLS":
1683 if newfn not in self.pdata["PROTOCOLS"]: 1753 if newfn not in self.__pdata["PROTOCOLS"]:
1684 self.pdata["PROTOCOLS"].append(newfn) 1754 self.__pdata["PROTOCOLS"].append(newfn)
1685 self.projectProtocolAdded.emit(newfn) 1755 self.projectProtocolAdded.emit(newfn)
1686 (updateModel and self.__model.addNewItem("PROTOCOLS", newfn)) 1756 (updateModel and self.__model.addNewItem("PROTOCOLS", newfn))
1687 dirty = True 1757 dirty = True
1688 else: 1758 else:
1689 updateModel and self.repopulateItem(newfn) 1759 updateModel and self.repopulateItem(newfn)
1690 elif filetype == "RESOURCES": 1760 elif filetype == "RESOURCES":
1691 if newfn not in self.pdata["RESOURCES"]: 1761 if newfn not in self.__pdata["RESOURCES"]:
1692 self.pdata["RESOURCES"].append(newfn) 1762 self.__pdata["RESOURCES"].append(newfn)
1693 self.projectResourceAdded.emit(newfn) 1763 self.projectResourceAdded.emit(newfn)
1694 updateModel and self.__model.addNewItem("RESOURCES", newfn) 1764 updateModel and self.__model.addNewItem("RESOURCES", newfn)
1695 dirty = True 1765 dirty = True
1696 else: 1766 else:
1697 updateModel and self.repopulateItem(newfn) 1767 updateModel and self.repopulateItem(newfn)
1698 if newdir not in self.subdirs: 1768 if newdir not in self.subdirs:
1699 self.subdirs.append(newdir) 1769 self.subdirs.append(newdir)
1700 elif filetype == "TRANSLATIONS": 1770 elif filetype == "TRANSLATIONS":
1701 if newfn not in self.pdata["TRANSLATIONS"]: 1771 if newfn not in self.__pdata["TRANSLATIONS"]:
1702 self.pdata["TRANSLATIONS"].append(newfn) 1772 self.__pdata["TRANSLATIONS"].append(newfn)
1703 updateModel and self.__model.addNewItem("TRANSLATIONS", newfn) 1773 updateModel and self.__model.addNewItem("TRANSLATIONS", newfn)
1704 self.projectLanguageAdded.emit(newfn) 1774 self.projectLanguageAdded.emit(newfn)
1705 dirty = True 1775 dirty = True
1706 else: 1776 else:
1707 updateModel and self.repopulateItem(newfn) 1777 updateModel and self.repopulateItem(newfn)
1708 else: # filetype == "OTHERS" 1778 else: # filetype == "OTHERS"
1709 if newfn not in self.pdata["OTHERS"]: 1779 if newfn not in self.__pdata["OTHERS"]:
1710 self.pdata["OTHERS"].append(newfn) 1780 self.__pdata["OTHERS"].append(newfn)
1711 self.othersAdded(newfn, updateModel) 1781 self.othersAdded(newfn, updateModel)
1712 dirty = True 1782 dirty = True
1713 else: 1783 else:
1714 updateModel and self.repopulateItem(newfn) 1784 updateModel and self.repopulateItem(newfn)
1715 if newdir not in self.otherssubdirs: 1785 if newdir not in self.otherssubdirs:
1789 @param quiet flag indicating quiet operations (boolean) 1859 @param quiet flag indicating quiet operations (boolean)
1790 """ 1860 """
1791 # get all relevant filename patterns 1861 # get all relevant filename patterns
1792 patterns = [] 1862 patterns = []
1793 ignorePatterns = [] 1863 ignorePatterns = []
1794 for pattern, patterntype in list(self.pdata["FILETYPES"].items()): 1864 for pattern, patterntype in list(self.__pdata["FILETYPES"].items()):
1795 if patterntype == filetype: 1865 if patterntype == filetype:
1796 patterns.append(pattern) 1866 patterns.append(pattern)
1797 elif patterntype == "__IGNORE__": 1867 elif patterntype == "__IGNORE__":
1798 ignorePatterns.append(pattern) 1868 ignorePatterns.append(pattern)
1799 1869
1869 # first perform the addition of source 1939 # first perform the addition of source
1870 self.__addSingleDirectory(filetype, source, target, True) 1940 self.__addSingleDirectory(filetype, source, target, True)
1871 1941
1872 ignore_patterns = [ 1942 ignore_patterns = [
1873 pattern 1943 pattern
1874 for pattern, filetype in self.pdata["FILETYPES"].items() 1944 for pattern, filetype in self.__pdata["FILETYPES"].items()
1875 if filetype == "__IGNORE__" 1945 if filetype == "__IGNORE__"
1876 ] 1946 ]
1877 1947
1878 # now recurse into subdirectories 1948 # now recurse into subdirectories
1879 for name in os.listdir(source): 1949 for name in os.listdir(source):
1945 2015
1946 # if it ends with the directory separator character, remove it 2016 # if it ends with the directory separator character, remove it
1947 if fn.endswith(os.sep): 2017 if fn.endswith(os.sep):
1948 fn = fn[:-1] 2018 fn = fn[:-1]
1949 2019
1950 if fn not in self.pdata["OTHERS"]: 2020 if fn not in self.__pdata["OTHERS"]:
1951 self.pdata["OTHERS"].append(fn) 2021 self.__pdata["OTHERS"].append(fn)
1952 self.othersAdded(fn) 2022 self.othersAdded(fn)
1953 self.setDirty(True) 2023 self.setDirty(True)
1954 2024
1955 if os.path.isdir(fn) and fn not in self.otherssubdirs: 2025 if os.path.isdir(fn) and fn not in self.otherssubdirs:
1956 self.otherssubdirs.append(fn) 2026 self.otherssubdirs.append(fn)
2036 Public method to rename the main script. 2106 Public method to rename the main script.
2037 2107
2038 @param oldfn old filename (string) 2108 @param oldfn old filename (string)
2039 @param newfn new filename of the main script (string) 2109 @param newfn new filename of the main script (string)
2040 """ 2110 """
2041 if self.pdata["MAINSCRIPT"]: 2111 if self.__pdata["MAINSCRIPT"]:
2042 ofn = self.getRelativePath(oldfn) 2112 ofn = self.getRelativePath(oldfn)
2043 if ofn != self.pdata["MAINSCRIPT"]: 2113 if ofn != self.__pdata["MAINSCRIPT"]:
2044 return 2114 return
2045 2115
2046 fn = self.getRelativePath(newfn) 2116 fn = self.getRelativePath(newfn)
2047 self.pdata["MAINSCRIPT"] = fn 2117 self.__pdata["MAINSCRIPT"] = fn
2048 self.setDirty(True) 2118 self.setDirty(True)
2049 2119
2050 def renameFile(self, oldfn, newfn=None): 2120 def renameFile(self, oldfn, newfn=None):
2051 """ 2121 """
2052 Public slot to rename a file of the project. 2122 Public slot to rename a file of the project.
2054 @param oldfn old filename of the file (string) 2124 @param oldfn old filename of the file (string)
2055 @param newfn new filename of the file (string) 2125 @param newfn new filename of the file (string)
2056 @return flag indicating success 2126 @return flag indicating success
2057 """ 2127 """
2058 fn = self.getRelativePath(oldfn) 2128 fn = self.getRelativePath(oldfn)
2059 isSourceFile = fn in self.pdata["SOURCES"] 2129 isSourceFile = fn in self.__pdata["SOURCES"]
2060 2130
2061 if newfn is None: 2131 if newfn is None:
2062 newfn = EricFileDialog.getSaveFileName( 2132 newfn = EricFileDialog.getSaveFileName(
2063 None, 2133 None,
2064 self.tr("Rename file"), 2134 self.tr("Rename file"),
2094 """Reason: {1}</p>""" 2164 """Reason: {1}</p>"""
2095 ).format(oldfn, str(msg)), 2165 ).format(oldfn, str(msg)),
2096 ) 2166 )
2097 return False 2167 return False
2098 2168
2099 if ( 2169 ##if (
2100 fn in self.pdata["SOURCES"] 2170 ##fn in self.__pdata["SOURCES"]
2101 or fn in self.pdata["FORMS"] 2171 ##or fn in self.__pdata["FORMS"]
2102 or fn in self.pdata["TRANSLATIONS"] 2172 ##or fn in self.__pdata["TRANSLATIONS"]
2103 or fn in self.pdata["INTERFACES"] 2173 ##or fn in self.__pdata["INTERFACES"]
2104 or fn in self.pdata["PROTOCOLS"] 2174 ##or fn in self.__pdata["PROTOCOLS"]
2105 or fn in self.pdata["RESOURCES"] 2175 ##or fn in self.__pdata["RESOURCES"]
2106 or fn in self.pdata["OTHERS"] 2176 ##or fn in self.__pdata["OTHERS"]
2107 ): 2177 ##):
2178 if any(fn in self.__pdata[category] for category in self.__knownFileCategories):
2108 self.renameFileInPdata(oldfn, newfn, isSourceFile) 2179 self.renameFileInPdata(oldfn, newfn, isSourceFile)
2109 2180
2110 return True 2181 return True
2111 2182
2112 def renameFileInPdata(self, oldname, newname, isSourceFile=False): 2183 def renameFileInPdata(self, oldname, newname, isSourceFile=False):
2113 """ 2184 """
2114 Public method to rename a file in the pdata structure. 2185 Public method to rename a file in the __pdata structure.
2115 2186
2116 @param oldname old filename (string) 2187 @param oldname old filename (string)
2117 @param newname new filename (string) 2188 @param newname new filename (string)
2118 @param isSourceFile flag indicating that this is a source file 2189 @param isSourceFile flag indicating that this is a source file
2119 even if it doesn't have the source extension (boolean) 2190 even if it doesn't have the source extension (boolean)
2138 @param start prefix (string) 2209 @param start prefix (string)
2139 @return list of files starting with a common prefix (list of strings) 2210 @return list of files starting with a common prefix (list of strings)
2140 """ 2211 """
2141 filelist = [] 2212 filelist = []
2142 start = self.getRelativePath(start) 2213 start = self.getRelativePath(start)
2143 for key in [ 2214 ##for key in [
2144 "SOURCES", 2215 ##"SOURCES",
2145 "FORMS", 2216 ##"FORMS",
2146 "INTERFACES", 2217 ##"INTERFACES",
2147 "PROTOCOLS", 2218 ##"PROTOCOLS",
2148 "RESOURCES", 2219 ##"RESOURCES",
2149 "OTHERS", 2220 ##"OTHERS",
2221 ##]:
2222 for fileCategory in [
2223 c for c in self.__knownFileCategories if c != "TRANSLATIONS"
2150 ]: 2224 ]:
2151 for entry in self.pdata[key][:]: 2225 for entry in self.__pdata[fileCategory][:]:
2152 if entry.startswith(start): 2226 if entry.startswith(start):
2153 filelist.append(os.path.join(self.ppath, entry)) 2227 filelist.append(os.path.join(self.ppath, entry))
2154 return filelist 2228 return filelist
2155 2229
2156 def __reorganizeFiles(self): 2230 def __reorganizeFiles(self):
2159 """ 2233 """
2160 reorganized = False 2234 reorganized = False
2161 2235
2162 # init data store for the reorganization 2236 # init data store for the reorganization
2163 newPdata = {} 2237 newPdata = {}
2164 for key in [ 2238 ##for key in [
2165 "SOURCES", 2239 ##"SOURCES",
2166 "FORMS", 2240 ##"FORMS",
2167 "INTERFACES", 2241 ##"INTERFACES",
2168 "PROTOCOLS", 2242 ##"PROTOCOLS",
2169 "RESOURCES", 2243 ##"RESOURCES",
2170 "OTHERS", 2244 ##"OTHERS",
2171 "TRANSLATIONS", 2245 ##"TRANSLATIONS",
2172 ]: 2246 ##]:
2173 newPdata[key] = [] 2247 for fileCategory in self.__knownFileCategories:
2248 newPdata[fileCategory] = []
2174 2249
2175 # iterate over all files checking for a reassignment 2250 # iterate over all files checking for a reassignment
2176 for key in [ 2251 ##for key in [
2177 "SOURCES", 2252 ##"SOURCES",
2178 "FORMS", 2253 ##"FORMS",
2179 "INTERFACES", 2254 ##"INTERFACES",
2180 "PROTOCOLS", 2255 ##"PROTOCOLS",
2181 "RESOURCES", 2256 ##"RESOURCES",
2182 "OTHERS", 2257 ##"OTHERS",
2183 "TRANSLATIONS", 2258 ##"TRANSLATIONS",
2184 ]: 2259 ##]:
2185 for fn in self.pdata[key][:]: 2260 for fileCategory in self.__knownFileCategories:
2186 filetype = key 2261 for fn in self.__pdata[fileCategory][:]:
2262 filetype = fileCategory
2187 bfn = os.path.basename(fn) 2263 bfn = os.path.basename(fn)
2188 for pattern in sorted(self.pdata["FILETYPES"].keys(), reverse=True): 2264 for pattern in sorted(self.__pdata["FILETYPES"].keys(), reverse=True):
2189 if fnmatch.fnmatch(bfn, pattern): 2265 if fnmatch.fnmatch(bfn, pattern):
2190 filetype = self.pdata["FILETYPES"][pattern] 2266 filetype = self.__pdata["FILETYPES"][pattern]
2191 break 2267 break
2192 2268
2193 if filetype != "__IGNORE__": 2269 if filetype != "__IGNORE__":
2194 newPdata[filetype].append(fn) 2270 newPdata[filetype].append(fn)
2195 if filetype != key: 2271 if filetype != fileCategory:
2196 reorganized = True 2272 reorganized = True
2197 2273
2198 if reorganized: 2274 if reorganized:
2199 # copy the reorganized files back to the project 2275 # copy the reorganized files back to the project
2200 for key in [ 2276 ##for key in [
2201 "SOURCES", 2277 ##"SOURCES",
2202 "FORMS", 2278 ##"FORMS",
2203 "INTERFACES", 2279 ##"INTERFACES",
2204 "PROTOCOLS", 2280 ##"PROTOCOLS",
2205 "RESOURCES", 2281 ##"RESOURCES",
2206 "OTHERS", 2282 ##"OTHERS",
2207 "TRANSLATIONS", 2283 ##"TRANSLATIONS",
2208 ]: 2284 ##]:
2209 self.pdata[key] = newPdata[key][:] 2285 for fileCategory in self.__knownFileCategories:
2286 self.__pdata[fileCategory] = newPdata[fileCategory][:]
2210 2287
2211 # repopulate the model 2288 # repopulate the model
2212 self.__model.projectClosed(False) 2289 self.__model.projectClosed(False)
2213 self.__model.projectOpened() 2290 self.__model.projectOpened()
2214 2291
2219 @param olddn original directory name (string) 2296 @param olddn original directory name (string)
2220 @param newdn new directory name (string) 2297 @param newdn new directory name (string)
2221 """ 2298 """
2222 olddn = self.getRelativePath(olddn) 2299 olddn = self.getRelativePath(olddn)
2223 newdn = self.getRelativePath(newdn) 2300 newdn = self.getRelativePath(newdn)
2224 for key in [ 2301 ##for key in [
2225 "SOURCES", 2302 ##"SOURCES",
2226 "FORMS", 2303 ##"FORMS",
2227 "INTERFACES", 2304 ##"INTERFACES",
2228 "PROTOCOLS", 2305 ##"PROTOCOLS",
2229 "RESOURCES", 2306 ##"RESOURCES",
2230 "OTHERS", 2307 ##"OTHERS",
2308 ##]:
2309 for fileCategory in [
2310 c for c in self.__knownFileCategories if c != "TRANSLATIONS"
2231 ]: 2311 ]:
2232 for entry in self.pdata[key][:]: 2312 for entry in self.__pdata[fileCategory][:]:
2233 if entry.startswith(olddn): 2313 if entry.startswith(olddn):
2234 entry = entry.replace(olddn, newdn) 2314 entry = entry.replace(olddn, newdn)
2235 self.appendFile(os.path.join(self.ppath, entry), key == "SOURCES") 2315 self.appendFile(
2316 os.path.join(self.ppath, entry), fileCategory == "SOURCES"
2317 )
2236 self.setDirty(True) 2318 self.setDirty(True)
2237 2319
2238 def moveDirectory(self, olddn, newdn): 2320 def moveDirectory(self, olddn, newdn):
2239 """ 2321 """
2240 Public slot to move a directory. 2322 Public slot to move a directory.
2243 @param newdn new directory name (string) 2325 @param newdn new directory name (string)
2244 """ 2326 """
2245 olddn = self.getRelativePath(olddn) 2327 olddn = self.getRelativePath(olddn)
2246 newdn = self.getRelativePath(newdn) 2328 newdn = self.getRelativePath(newdn)
2247 typeStrings = [] 2329 typeStrings = []
2248 for key in [ 2330 ##for key in [
2249 "SOURCES", 2331 ##"SOURCES",
2250 "FORMS", 2332 ##"FORMS",
2251 "INTERFACES", 2333 ##"INTERFACES",
2252 "PROTOCOLS", 2334 ##"PROTOCOLS",
2253 "RESOURCES", 2335 ##"RESOURCES",
2254 "OTHERS", 2336 ##"OTHERS",
2337 ##]:
2338 for fileCategory in [
2339 c for c in self.__knownFileCategories if c != "TRANSLATIONS"
2255 ]: 2340 ]:
2256 for entry in self.pdata[key][:]: 2341 for entry in self.__pdata[fileCategory][:]:
2257 if entry.startswith(olddn): 2342 if entry.startswith(olddn):
2258 if key not in typeStrings: 2343 if fileCategory not in typeStrings:
2259 typeStrings.append(key) 2344 typeStrings.append(fileCategory)
2260 self.pdata[key].remove(entry) 2345 self.__pdata[fileCategory].remove(entry)
2261 entry = entry.replace(olddn, newdn) 2346 entry = entry.replace(olddn, newdn)
2262 self.pdata[key].append(entry) 2347 self.__pdata[fileCategory].append(entry)
2263 if key == "OTHERS": 2348 if fileCategory == "OTHERS":
2264 if newdn not in self.otherssubdirs: 2349 if newdn not in self.otherssubdirs:
2265 self.otherssubdirs.append(newdn) 2350 self.otherssubdirs.append(newdn)
2266 else: 2351 else:
2267 if newdn not in self.subdirs: 2352 if newdn not in self.subdirs:
2268 self.subdirs.append(newdn) 2353 self.subdirs.append(newdn)
2287 @param updateModel flag indicating an update of the model is 2372 @param updateModel flag indicating an update of the model is
2288 requested (boolean) 2373 requested (boolean)
2289 """ 2374 """
2290 fn = self.getRelativePath(fn) 2375 fn = self.getRelativePath(fn)
2291 dirty = True 2376 dirty = True
2292 if fn in self.pdata["SOURCES"]: 2377 # TODO: change this logic to be more generic (use fileCategory)
2293 self.pdata["SOURCES"].remove(fn) 2378 if fn in self.__pdata["SOURCES"]:
2379 self.__pdata["SOURCES"].remove(fn)
2294 self.projectSourceRemoved.emit(fn) 2380 self.projectSourceRemoved.emit(fn)
2295 elif fn in self.pdata["FORMS"]: 2381 elif fn in self.__pdata["FORMS"]:
2296 self.pdata["FORMS"].remove(fn) 2382 self.__pdata["FORMS"].remove(fn)
2297 self.projectFormRemoved.emit(fn) 2383 self.projectFormRemoved.emit(fn)
2298 elif fn in self.pdata["INTERFACES"]: 2384 elif fn in self.__pdata["INTERFACES"]:
2299 self.pdata["INTERFACES"].remove(fn) 2385 self.__pdata["INTERFACES"].remove(fn)
2300 self.projectInterfaceRemoved.emit(fn) 2386 self.projectInterfaceRemoved.emit(fn)
2301 elif fn in self.pdata["PROTOCOLS"]: 2387 elif fn in self.__pdata["PROTOCOLS"]:
2302 self.pdata["PROTOCOLS"].remove(fn) 2388 self.__pdata["PROTOCOLS"].remove(fn)
2303 self.projectProtocolRemoved.emit(fn) 2389 self.projectProtocolRemoved.emit(fn)
2304 elif fn in self.pdata["RESOURCES"]: 2390 elif fn in self.__pdata["RESOURCES"]:
2305 self.pdata["RESOURCES"].remove(fn) 2391 self.__pdata["RESOURCES"].remove(fn)
2306 self.projectResourceRemoved.emit(fn) 2392 self.projectResourceRemoved.emit(fn)
2307 elif fn in self.pdata["OTHERS"]: 2393 elif fn in self.__pdata["OTHERS"]:
2308 self.pdata["OTHERS"].remove(fn) 2394 self.__pdata["OTHERS"].remove(fn)
2309 self.projectOthersRemoved.emit(fn) 2395 self.projectOthersRemoved.emit(fn)
2310 elif fn in self.pdata["TRANSLATIONS"]: 2396 elif fn in self.__pdata["TRANSLATIONS"]:
2311 self.pdata["TRANSLATIONS"].remove(fn) 2397 self.__pdata["TRANSLATIONS"].remove(fn)
2312 self.projectLanguageRemoved.emit(fn) 2398 self.projectLanguageRemoved.emit(fn)
2313 else: 2399 else:
2314 dirty = False 2400 dirty = False
2315 updateModel and self.__model.removeItem(fn) 2401 updateModel and self.__model.removeItem(fn)
2316 if dirty: 2402 if dirty:
2324 2410
2325 @param dn directory name to be removed from the project 2411 @param dn directory name to be removed from the project
2326 """ 2412 """
2327 dirty = False 2413 dirty = False
2328 dn = self.getRelativePath(dn) 2414 dn = self.getRelativePath(dn)
2329 for entry in self.pdata["OTHERS"][:]: 2415 for entry in self.__pdata["OTHERS"][:]:
2330 if entry.startswith(dn): 2416 if entry.startswith(dn):
2331 self.pdata["OTHERS"].remove(entry) 2417 self.__pdata["OTHERS"].remove(entry)
2332 dirty = True 2418 dirty = True
2333 dn2 = dn if dn.endswith(os.sep) else dn + os.sep 2419 dn2 = dn if dn.endswith(os.sep) else dn + os.sep
2334 for key in [ 2420 ##for key in [
2335 "SOURCES", 2421 ##"SOURCES",
2336 "FORMS", 2422 ##"FORMS",
2337 "INTERFACES", 2423 ##"INTERFACES",
2338 "PROTOCOLS", 2424 ##"PROTOCOLS",
2339 "RESOURCES", 2425 ##"RESOURCES",
2340 "TRANSLATIONS", 2426 ##"TRANSLATIONS",
2341 ]: 2427 ##]:
2342 for entry in self.pdata[key][:]: 2428 for fileCategory in [c for c in self.__knownFileCategories if c != "OTHERS"]:
2429 for entry in self.__pdata[fileCategory][:]:
2343 if entry.startswith(dn2): 2430 if entry.startswith(dn2):
2344 self.pdata[key].remove(entry) 2431 self.__pdata[fileCategory].remove(entry)
2345 dirty = True 2432 dirty = True
2346 self.__model.removeItem(dn) 2433 self.__model.removeItem(dn)
2347 if dirty: 2434 if dirty:
2348 self.setDirty(True) 2435 self.setDirty(True)
2349 self.directoryRemoved.emit(dn) 2436 self.directoryRemoved.emit(dn)
2429 2516
2430 @param fn filename to be checked (string) 2517 @param fn filename to be checked (string)
2431 @return flag indicating, if the project contains the file (boolean) 2518 @return flag indicating, if the project contains the file (boolean)
2432 """ 2519 """
2433 fn = self.getRelativePath(fn) 2520 fn = self.getRelativePath(fn)
2434 return ( 2521 return any(
2435 fn in self.pdata["SOURCES"] 2522 fn in self.__pdata[category]
2436 or fn in self.pdata["FORMS"] 2523 for category in self.__knownFileCategories
2437 or fn in self.pdata["INTERFACES"] 2524 if category != "TRANSLATIONS"
2438 or fn in self.pdata["PROTOCOLS"] 2525 )
2439 or fn in self.pdata["RESOURCES"] 2526 ##fn in self.__pdata["SOURCES"]
2440 or fn in self.pdata["OTHERS"] 2527 ##or fn in self.__pdata["FORMS"]
2441 ) 2528 ##or fn in self.__pdata["INTERFACES"]
2529 ##or fn in self.__pdata["PROTOCOLS"]
2530 ##or fn in self.__pdata["RESOURCES"]
2531 ##or fn in self.__pdata["OTHERS"]
2532 ##)
2442 2533
2443 def createNewProject(self): 2534 def createNewProject(self):
2444 """ 2535 """
2445 Public slot to built a new project. 2536 Public slot to built a new project.
2446 2537
2456 2547
2457 dlg = PropertiesDialog(self, True) 2548 dlg = PropertiesDialog(self, True)
2458 if dlg.exec() == QDialog.DialogCode.Accepted: 2549 if dlg.exec() == QDialog.DialogCode.Accepted:
2459 self.closeProject() 2550 self.closeProject()
2460 dlg.storeData() 2551 dlg.storeData()
2461 self.pdata["VCS"] = "None" 2552 self.__pdata["VCS"] = "None"
2462 self.opened = True 2553 self.opened = True
2463 if not self.pdata["FILETYPES"]: 2554 if not self.__pdata["FILETYPES"]:
2464 self.initFileTypes() 2555 self.initFileTypes()
2465 self.setDirty(True) 2556 self.setDirty(True)
2466 self.closeAct.setEnabled(True) 2557 self.closeAct.setEnabled(True)
2467 self.saveasAct.setEnabled(True) 2558 self.saveasAct.setEnabled(True)
2468 self.actGrp2.setEnabled(True) 2559 self.actGrp2.setEnabled(True)
2477 self.menuCheckAct.setEnabled(True) 2568 self.menuCheckAct.setEnabled(True)
2478 self.menuShowAct.setEnabled(True) 2569 self.menuShowAct.setEnabled(True)
2479 self.menuDiagramAct.setEnabled(True) 2570 self.menuDiagramAct.setEnabled(True)
2480 self.menuApidocAct.setEnabled(True) 2571 self.menuApidocAct.setEnabled(True)
2481 self.menuPackagersAct.setEnabled(True) 2572 self.menuPackagersAct.setEnabled(True)
2482 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"] in ["E7Plugin"]) 2573 self.pluginGrp.setEnabled(self.__pdata["PROJECTTYPE"] in ["E7Plugin"])
2483 self.addLanguageAct.setEnabled(bool(self.pdata["TRANSLATIONPATTERN"])) 2574 self.addLanguageAct.setEnabled(bool(self.__pdata["TRANSLATIONPATTERN"]))
2484 self.makeGrp.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) 2575 self.makeGrp.setEnabled(self.__pdata["MAKEPARAMS"]["MakeEnabled"])
2485 self.menuMakeAct.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) 2576 self.menuMakeAct.setEnabled(self.__pdata["MAKEPARAMS"]["MakeEnabled"])
2486 self.menuOtherToolsAct.setEnabled(True) 2577 self.menuOtherToolsAct.setEnabled(True)
2487 self.menuFormattingAct.setEnabled(True) 2578 self.menuFormattingAct.setEnabled(True)
2488 2579
2489 self.projectAboutToBeCreated.emit() 2580 self.projectAboutToBeCreated.emit()
2490 2581
2493 QByteArray(self.ppath.encode("utf-8")), 2584 QByteArray(self.ppath.encode("utf-8")),
2494 QCryptographicHash.Algorithm.Sha1, 2585 QCryptographicHash.Algorithm.Sha1,
2495 ).toHex(), 2586 ).toHex(),
2496 encoding="utf-8", 2587 encoding="utf-8",
2497 ) 2588 )
2498 self.pdata["HASH"] = hashStr 2589 self.__pdata["HASH"] = hashStr
2499 2590
2500 if self.pdata["PROGLANGUAGE"] == "MicroPython": 2591 if self.__pdata["PROGLANGUAGE"] == "MicroPython":
2501 # change the lexer association for *.py files 2592 # change the lexer association for *.py files
2502 self.pdata["LEXERASSOCS"] = { 2593 self.__pdata["LEXERASSOCS"] = {
2503 "*.py": "MicroPython", 2594 "*.py": "MicroPython",
2504 } 2595 }
2505 2596
2506 # create the project directory if it doesn't exist already 2597 # create the project directory if it doesn't exist already
2507 if not os.path.isdir(self.ppath): 2598 if not os.path.isdir(self.ppath):
2519 self.vcs = self.initVCS() 2610 self.vcs = self.initVCS()
2520 return 2611 return
2521 2612
2522 # create an empty __init__.py file to make it a Python package 2613 # create an empty __init__.py file to make it a Python package
2523 # (only for Python and Python3) 2614 # (only for Python and Python3)
2524 if self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]: 2615 if self.__pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]:
2525 fn = os.path.join(self.ppath, "__init__.py") 2616 fn = os.path.join(self.ppath, "__init__.py")
2526 with open(fn, "w", encoding="utf-8"): 2617 with open(fn, "w", encoding="utf-8"):
2527 pass 2618 pass
2528 self.appendFile(fn, True) 2619 self.appendFile(fn, True)
2529 2620
2530 # create an empty main script file, if a name was given 2621 # create an empty main script file, if a name was given
2531 if self.pdata["MAINSCRIPT"]: 2622 if self.__pdata["MAINSCRIPT"]:
2532 if not os.path.isabs(self.pdata["MAINSCRIPT"]): 2623 if not os.path.isabs(self.__pdata["MAINSCRIPT"]):
2533 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) 2624 ms = os.path.join(self.ppath, self.__pdata["MAINSCRIPT"])
2534 else: 2625 else:
2535 ms = self.pdata["MAINSCRIPT"] 2626 ms = self.__pdata["MAINSCRIPT"]
2536 os.makedirs(os.path.dirname(ms), exist_ok=True) 2627 os.makedirs(os.path.dirname(ms), exist_ok=True)
2537 with open(ms, "w"): 2628 with open(ms, "w"):
2538 pass 2629 pass
2539 self.appendFile(ms, True) 2630 self.appendFile(ms, True)
2540 2631
2541 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: 2632 if self.__pdata["MAKEPARAMS"]["MakeEnabled"]:
2542 mf = self.pdata["MAKEPARAMS"]["MakeFile"] 2633 mf = self.__pdata["MAKEPARAMS"]["MakeFile"]
2543 if mf: 2634 if mf:
2544 if not os.path.isabs(mf): 2635 if not os.path.isabs(mf):
2545 mf = os.path.join(self.ppath, mf) 2636 mf = os.path.join(self.ppath, mf)
2546 else: 2637 else:
2547 mf = os.path.join(self.ppath, Project.DefaultMakefile) 2638 mf = os.path.join(self.ppath, Project.DefaultMakefile)
2553 tpd = os.path.join(self.ppath, self.translationsRoot) 2644 tpd = os.path.join(self.ppath, self.translationsRoot)
2554 if not self.translationsRoot.endswith(os.sep): 2645 if not self.translationsRoot.endswith(os.sep):
2555 tpd = os.path.dirname(tpd) 2646 tpd = os.path.dirname(tpd)
2556 if not os.path.isdir(tpd): 2647 if not os.path.isdir(tpd):
2557 os.makedirs(tpd, exist_ok=True) 2648 os.makedirs(tpd, exist_ok=True)
2558 if self.pdata["TRANSLATIONSBINPATH"]: 2649 if self.__pdata["TRANSLATIONSBINPATH"]:
2559 tpd = os.path.join(self.ppath, self.pdata["TRANSLATIONSBINPATH"]) 2650 tpd = os.path.join(self.ppath, self.__pdata["TRANSLATIONSBINPATH"])
2560 if not os.path.isdir(tpd): 2651 if not os.path.isdir(tpd):
2561 os.makedirs(tpd, exist_ok=True) 2652 os.makedirs(tpd, exist_ok=True)
2562 2653
2563 # create management directory if not present 2654 # create management directory if not present
2564 self.createProjectManagementDir() 2655 self.createProjectManagementDir()
2578 " writable.</p>" 2669 " writable.</p>"
2579 ).format(self.ppath), 2670 ).format(self.ppath),
2580 ) 2671 )
2581 return 2672 return
2582 2673
2583 if self.pdata["MAINSCRIPT"]: 2674 if self.__pdata["MAINSCRIPT"]:
2584 if not os.path.isabs(self.pdata["MAINSCRIPT"]): 2675 if not os.path.isabs(self.__pdata["MAINSCRIPT"]):
2585 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) 2676 ms = os.path.join(self.ppath, self.__pdata["MAINSCRIPT"])
2586 else: 2677 else:
2587 ms = self.pdata["MAINSCRIPT"] 2678 ms = self.__pdata["MAINSCRIPT"]
2588 if not os.path.exists(ms): 2679 if not os.path.exists(ms):
2589 try: 2680 try:
2590 os.makedirs(os.path.dirname(ms)) 2681 os.makedirs(os.path.dirname(ms))
2591 with open(ms, "w"): 2682 with open(ms, "w"):
2592 pass 2683 pass
2601 ) 2692 )
2602 self.appendFile(ms, True) 2693 self.appendFile(ms, True)
2603 else: 2694 else:
2604 ms = "" 2695 ms = ""
2605 2696
2606 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: 2697 if self.__pdata["MAKEPARAMS"]["MakeEnabled"]:
2607 mf = self.pdata["MAKEPARAMS"]["MakeFile"] 2698 mf = self.__pdata["MAKEPARAMS"]["MakeFile"]
2608 if mf: 2699 if mf:
2609 if not os.path.isabs(mf): 2700 if not os.path.isabs(mf):
2610 mf = os.path.join(self.ppath, mf) 2701 mf = os.path.join(self.ppath, mf)
2611 else: 2702 else:
2612 mf = os.path.join(self.ppath, Project.DefaultMakefile) 2703 mf = os.path.join(self.ppath, Project.DefaultMakefile)
2636 if res: 2727 if res:
2637 self.newProjectAddFiles(ms) 2728 self.newProjectAddFiles(ms)
2638 addAllToVcs = res 2729 addAllToVcs = res
2639 # create an empty __init__.py file to make it a Python package 2730 # create an empty __init__.py file to make it a Python package
2640 # if none exists (only for Python and Python3) 2731 # if none exists (only for Python and Python3)
2641 if self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]: 2732 if self.__pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]:
2642 fn = os.path.join(self.ppath, "__init__.py") 2733 fn = os.path.join(self.ppath, "__init__.py")
2643 if not os.path.exists(fn): 2734 if not os.path.exists(fn):
2644 with open(fn, "w", encoding="utf-8"): 2735 with open(fn, "w", encoding="utf-8"):
2645 pass 2736 pass
2646 self.appendFile(fn, True) 2737 self.appendFile(fn, True)
2674 vcsSystem = "None" 2765 vcsSystem = "None"
2675 else: 2766 else:
2676 vcsSystem = "None" 2767 vcsSystem = "None"
2677 else: 2768 else:
2678 vcsSystem = vcsData[0][1] 2769 vcsSystem = vcsData[0][1]
2679 self.pdata["VCS"] = vcsSystem 2770 self.__pdata["VCS"] = vcsSystem
2680 self.vcs = self.initVCS() 2771 self.vcs = self.initVCS()
2681 self.setDirty(True) 2772 self.setDirty(True)
2682 if self.vcs is not None: 2773 if self.vcs is not None:
2683 # edit VCS command options 2774 # edit VCS command options
2684 if self.vcs.vcsSupportCommandOptions(): 2775 if self.vcs.vcsSupportCommandOptions():
2709 ) 2800 )
2710 if apres: 2801 if apres:
2711 self.saveProject() 2802 self.saveProject()
2712 self.vcs.vcsAdd(self.pfile) 2803 self.vcs.vcsAdd(self.pfile)
2713 else: 2804 else:
2714 self.pdata["VCS"] = "None" 2805 self.__pdata["VCS"] = "None"
2715 self.saveProject() 2806 self.saveProject()
2716 break 2807 break
2717 2808
2718 # put the project under VCS control 2809 # put the project under VCS control
2719 if self.vcs is None and self.vcsSoftwareAvailable() and self.vcsRequested: 2810 if self.vcs is None and self.vcsSoftwareAvailable() and self.vcsRequested:
2735 False, 2826 False,
2736 ) 2827 )
2737 if ok and vcsSelected != self.tr("None"): 2828 if ok and vcsSelected != self.tr("None"):
2738 for vcsSystem, vcsSystemDisplay in vcsSystemsDict.items(): 2829 for vcsSystem, vcsSystemDisplay in vcsSystemsDict.items():
2739 if vcsSystemDisplay == vcsSelected: 2830 if vcsSystemDisplay == vcsSelected:
2740 self.pdata["VCS"] = vcsSystem 2831 self.__pdata["VCS"] = vcsSystem
2741 break 2832 break
2742 else: 2833 else:
2743 self.pdata["VCS"] = "None" 2834 self.__pdata["VCS"] = "None"
2744 else: 2835 else:
2745 self.pdata["VCS"] = "None" 2836 self.__pdata["VCS"] = "None"
2746 self.vcs = self.initVCS() 2837 self.vcs = self.initVCS()
2747 if self.vcs is not None: 2838 if self.vcs is not None:
2748 vcsdlg = self.vcs.vcsOptionsDialog(self, self.name) 2839 vcsdlg = self.vcs.vcsOptionsDialog(self, self.name)
2749 if vcsdlg.exec() == QDialog.DialogCode.Accepted: 2840 if vcsdlg.exec() == QDialog.DialogCode.Accepted:
2750 vcsDataDict = vcsdlg.getData() 2841 vcsDataDict = vcsdlg.getData()
2751 else: 2842 else:
2752 self.pdata["VCS"] = "None" 2843 self.__pdata["VCS"] = "None"
2753 self.vcs = self.initVCS() 2844 self.vcs = self.initVCS()
2754 self.setDirty(True) 2845 self.setDirty(True)
2755 if self.vcs is not None: 2846 if self.vcs is not None:
2756 # edit VCS command options 2847 # edit VCS command options
2757 if self.vcs.vcsSupportCommandOptions(): 2848 if self.vcs.vcsSupportCommandOptions():
2780 2871
2781 else: 2872 else:
2782 self.newProjectHooks.emit() 2873 self.newProjectHooks.emit()
2783 self.newProject.emit() 2874 self.newProject.emit()
2784 2875
2785 if self.pdata["EMBEDDED_VENV"]: 2876 if self.__pdata["EMBEDDED_VENV"]:
2786 self.__createEmbeddedEnvironment() 2877 self.__createEmbeddedEnvironment()
2787 self.menuEnvironmentAct.setEnabled(self.pdata["EMBEDDED_VENV"]) 2878 self.menuEnvironmentAct.setEnabled(self.__pdata["EMBEDDED_VENV"])
2788 2879
2789 def newProjectAddFiles(self, mainscript): 2880 def newProjectAddFiles(self, mainscript):
2790 """ 2881 """
2791 Public method to add files to a new project. 2882 Public method to add files to a new project.
2792 2883
2795 # Show the file type associations for the user to change 2886 # Show the file type associations for the user to change
2796 self.__showFiletypeAssociations() 2887 self.__showFiletypeAssociations()
2797 2888
2798 with EricOverrideCursor(): 2889 with EricOverrideCursor():
2799 # search the project directory for files with known extensions 2890 # search the project directory for files with known extensions
2800 filespecs = list(self.pdata["FILETYPES"].keys()) 2891 filespecs = list(self.__pdata["FILETYPES"].keys())
2801 for filespec in filespecs: 2892 for filespec in filespecs:
2802 files = Utilities.direntries(self.ppath, True, filespec) 2893 files = Utilities.direntries(self.ppath, True, filespec)
2803 for file in files: 2894 for file in files:
2804 self.appendFile(file) 2895 self.appendFile(file)
2805 2896
2809 if not self.translationsRoot.endswith(os.sep): 2900 if not self.translationsRoot.endswith(os.sep):
2810 tpd = os.path.dirname(tpd) 2901 tpd = os.path.dirname(tpd)
2811 else: 2902 else:
2812 tpd = self.ppath 2903 tpd = self.ppath
2813 tslist = [] 2904 tslist = []
2814 if self.pdata["TRANSLATIONPATTERN"]: 2905 if self.__pdata["TRANSLATIONPATTERN"]:
2815 pattern = os.path.basename(self.pdata["TRANSLATIONPATTERN"]) 2906 pattern = os.path.basename(self.__pdata["TRANSLATIONPATTERN"])
2816 if "%language%" in pattern: 2907 if "%language%" in pattern:
2817 pattern = pattern.replace("%language%", "*") 2908 pattern = pattern.replace("%language%", "*")
2818 else: 2909 else:
2819 tpd = self.pdata["TRANSLATIONPATTERN"].split("%language%")[0] 2910 tpd = self.__pdata["TRANSLATIONPATTERN"].split("%language%")[0]
2820 else: 2911 else:
2821 pattern = "*.ts" 2912 pattern = "*.ts"
2822 tslist.extend(Utilities.direntries(tpd, True, pattern)) 2913 tslist.extend(Utilities.direntries(tpd, True, pattern))
2823 pattern = self.__binaryTranslationFile(pattern) 2914 pattern = self.__binaryTranslationFile(pattern)
2824 if pattern: 2915 if pattern:
2828 # the first entry determines the mainscript name 2919 # the first entry determines the mainscript name
2829 mainscriptname = ( 2920 mainscriptname = (
2830 os.path.splitext(mainscript)[0] 2921 os.path.splitext(mainscript)[0]
2831 or os.path.basename(tslist[0]).split("_")[0] 2922 or os.path.basename(tslist[0]).split("_")[0]
2832 ) 2923 )
2833 self.pdata["TRANSLATIONPATTERN"] = os.path.join( 2924 self.__pdata["TRANSLATIONPATTERN"] = os.path.join(
2834 os.path.dirname(tslist[0]), 2925 os.path.dirname(tslist[0]),
2835 "{0}_%language%{1}".format( 2926 "{0}_%language%{1}".format(
2836 os.path.basename(tslist[0]).split("_")[0], 2927 os.path.basename(tslist[0]).split("_")[0],
2837 os.path.splitext(tslist[0])[1], 2928 os.path.splitext(tslist[0])[1],
2838 ), 2929 ),
2849 ), 2940 ),
2850 QLineEdit.EchoMode.Normal, 2941 QLineEdit.EchoMode.Normal,
2851 tslist[0], 2942 tslist[0],
2852 ) 2943 )
2853 if pattern: 2944 if pattern:
2854 self.pdata["TRANSLATIONPATTERN"] = pattern 2945 self.__pdata["TRANSLATIONPATTERN"] = pattern
2855 if self.pdata["TRANSLATIONPATTERN"]: 2946 if self.__pdata["TRANSLATIONPATTERN"]:
2856 self.pdata["TRANSLATIONPATTERN"] = self.getRelativePath( 2947 self.__pdata["TRANSLATIONPATTERN"] = self.getRelativePath(
2857 self.pdata["TRANSLATIONPATTERN"] 2948 self.__pdata["TRANSLATIONPATTERN"]
2858 ) 2949 )
2859 pattern = self.pdata["TRANSLATIONPATTERN"].replace( 2950 pattern = self.__pdata["TRANSLATIONPATTERN"].replace(
2860 "%language%", "*" 2951 "%language%", "*"
2861 ) 2952 )
2862 for ts in tslist: 2953 for ts in tslist:
2863 if fnmatch.fnmatch(ts, pattern): 2954 if fnmatch.fnmatch(ts, pattern):
2864 self.pdata["TRANSLATIONS"].append(ts) 2955 self.__pdata["TRANSLATIONS"].append(ts)
2865 self.projectLanguageAdded.emit(ts) 2956 self.projectLanguageAdded.emit(ts)
2866 if self.pdata["TRANSLATIONSBINPATH"]: 2957 if self.__pdata["TRANSLATIONSBINPATH"]:
2867 tpd = os.path.join( 2958 tpd = os.path.join(
2868 self.ppath, self.pdata["TRANSLATIONSBINPATH"] 2959 self.ppath, self.__pdata["TRANSLATIONSBINPATH"]
2869 ) 2960 )
2870 pattern = os.path.basename( 2961 pattern = os.path.basename(
2871 self.pdata["TRANSLATIONPATTERN"] 2962 self.__pdata["TRANSLATIONPATTERN"]
2872 ).replace("%language%", "*") 2963 ).replace("%language%", "*")
2873 pattern = self.__binaryTranslationFile(pattern) 2964 pattern = self.__binaryTranslationFile(pattern)
2874 qmlist = Utilities.direntries(tpd, True, pattern) 2965 qmlist = Utilities.direntries(tpd, True, pattern)
2875 for qm in qmlist: 2966 for qm in qmlist:
2876 self.pdata["TRANSLATIONS"].append(qm) 2967 self.__pdata["TRANSLATIONS"].append(qm)
2877 self.projectLanguageAdded.emit(qm) 2968 self.projectLanguageAdded.emit(qm)
2878 if not self.pdata["MAINSCRIPT"] and bool(mainscriptname): 2969 if not self.__pdata["MAINSCRIPT"] and bool(mainscriptname):
2879 if self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]: 2970 if self.__pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]:
2880 self.pdata["MAINSCRIPT"] = "{0}.py".format(mainscriptname) 2971 self.__pdata["MAINSCRIPT"] = "{0}.py".format(mainscriptname)
2881 elif self.pdata["PROGLANGUAGE"] == "Ruby": 2972 elif self.__pdata["PROGLANGUAGE"] == "Ruby":
2882 self.pdata["MAINSCRIPT"] = "{0}.rb".format(mainscriptname) 2973 self.__pdata["MAINSCRIPT"] = "{0}.rb".format(mainscriptname)
2883 self.setDirty(True) 2974 self.setDirty(True)
2884 2975
2885 def __showProperties(self): 2976 def __showProperties(self):
2886 """ 2977 """
2887 Private slot to display the properties dialog. 2978 Private slot to display the properties dialog.
2888 """ 2979 """
2889 from .PropertiesDialog import PropertiesDialog 2980 from .PropertiesDialog import PropertiesDialog
2890 2981
2891 dlg = PropertiesDialog(self, False) 2982 dlg = PropertiesDialog(self, False)
2892 if dlg.exec() == QDialog.DialogCode.Accepted: 2983 if dlg.exec() == QDialog.DialogCode.Accepted:
2893 projectType = self.pdata["PROJECTTYPE"] 2984 projectType = self.__pdata["PROJECTTYPE"]
2894 dlg.storeData() 2985 dlg.storeData()
2895 self.setDirty(True) 2986 self.setDirty(True)
2896 if self.pdata["MAINSCRIPT"]: 2987 if self.__pdata["MAINSCRIPT"]:
2897 if not os.path.isabs(self.pdata["MAINSCRIPT"]): 2988 if not os.path.isabs(self.__pdata["MAINSCRIPT"]):
2898 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) 2989 ms = os.path.join(self.ppath, self.__pdata["MAINSCRIPT"])
2899 else: 2990 else:
2900 ms = self.pdata["MAINSCRIPT"] 2991 ms = self.__pdata["MAINSCRIPT"]
2901 if os.path.exists(ms): 2992 if os.path.exists(ms):
2902 self.appendFile(ms) 2993 self.appendFile(ms)
2903 2994
2904 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: 2995 if self.__pdata["MAKEPARAMS"]["MakeEnabled"]:
2905 mf = self.pdata["MAKEPARAMS"]["MakeFile"] 2996 mf = self.__pdata["MAKEPARAMS"]["MakeFile"]
2906 if mf: 2997 if mf:
2907 if not os.path.isabs(mf): 2998 if not os.path.isabs(mf):
2908 mf = os.path.join(self.ppath, mf) 2999 mf = os.path.join(self.ppath, mf)
2909 else: 3000 else:
2910 mf = os.path.join(self.ppath, Project.DefaultMakefile) 3001 mf = os.path.join(self.ppath, Project.DefaultMakefile)
2921 " be created.<br/>Reason: {1}</p>" 3012 " be created.<br/>Reason: {1}</p>"
2922 ).format(mf, str(err)), 3013 ).format(mf, str(err)),
2923 ) 3014 )
2924 self.appendFile(mf) 3015 self.appendFile(mf)
2925 3016
2926 if self.pdata["PROJECTTYPE"] != projectType: 3017 if self.__pdata["PROJECTTYPE"] != projectType:
2927 # reinitialize filetype associations 3018 # reinitialize filetype associations
2928 self.initFileTypes() 3019 self.initFileTypes()
2929 3020
2930 if self.translationsRoot: 3021 if self.translationsRoot:
2931 tp = os.path.join(self.ppath, self.translationsRoot) 3022 tp = os.path.join(self.ppath, self.translationsRoot)
2936 if not os.path.isdir(tp): 3027 if not os.path.isdir(tp):
2937 os.makedirs(tp) 3028 os.makedirs(tp)
2938 if tp != self.ppath and tp not in self.subdirs: 3029 if tp != self.ppath and tp not in self.subdirs:
2939 self.subdirs.append(tp) 3030 self.subdirs.append(tp)
2940 3031
2941 if self.pdata["TRANSLATIONSBINPATH"]: 3032 if self.__pdata["TRANSLATIONSBINPATH"]:
2942 tp = os.path.join(self.ppath, self.pdata["TRANSLATIONSBINPATH"]) 3033 tp = os.path.join(self.ppath, self.__pdata["TRANSLATIONSBINPATH"])
2943 if not os.path.isdir(tp): 3034 if not os.path.isdir(tp):
2944 os.makedirs(tp) 3035 os.makedirs(tp)
2945 if tp != self.ppath and tp not in self.subdirs: 3036 if tp != self.ppath and tp not in self.subdirs:
2946 self.subdirs.append(tp) 3037 self.subdirs.append(tp)
2947 3038
2948 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"] in ["E7Plugin"]) 3039 self.pluginGrp.setEnabled(self.__pdata["PROJECTTYPE"] in ["E7Plugin"])
2949 3040
2950 self.__model.projectPropertiesChanged() 3041 self.__model.projectPropertiesChanged()
2951 self.projectPropertiesChanged.emit() 3042 self.projectPropertiesChanged.emit()
2952 3043
2953 if self.pdata["PROJECTTYPE"] != projectType: 3044 if self.__pdata["PROJECTTYPE"] != projectType:
2954 self.__reorganizeFiles() 3045 self.__reorganizeFiles()
2955 3046
2956 if self.pdata["EMBEDDED_VENV"] and not self.__findEmbeddedEnvironment(): 3047 if self.__pdata["EMBEDDED_VENV"] and not self.__findEmbeddedEnvironment():
2957 self.__createEmbeddedEnvironment() 3048 self.__createEmbeddedEnvironment()
2958 3049
2959 def __showUserProperties(self): 3050 def __showUserProperties(self):
2960 """ 3051 """
2961 Private slot to display the user specific properties dialog. 3052 Private slot to display the user specific properties dialog.
2962 """ 3053 """
2963 from .UserPropertiesDialog import UserPropertiesDialog 3054 from .UserPropertiesDialog import UserPropertiesDialog
2964 3055
2965 vcsSystem = self.pdata["VCS"] or None 3056 vcsSystem = self.__pdata["VCS"] or None
2966 vcsSystemOverride = self.pudata["VCSOVERRIDE"] or None 3057 vcsSystemOverride = self.pudata["VCSOVERRIDE"] or None
2967 3058
2968 dlg = UserPropertiesDialog(self) 3059 dlg = UserPropertiesDialog(self)
2969 if dlg.exec() == QDialog.DialogCode.Accepted: 3060 if dlg.exec() == QDialog.DialogCode.Accepted:
2970 dlg.storeData() 3061 dlg.storeData()
2971 3062
2972 if ( 3063 if (
2973 (self.pdata["VCS"] and self.pdata["VCS"] != vcsSystem) 3064 (self.__pdata["VCS"] and self.__pdata["VCS"] != vcsSystem)
2974 or ( 3065 or (
2975 self.pudata["VCSOVERRIDE"] 3066 self.pudata["VCSOVERRIDE"]
2976 and self.pudata["VCSOVERRIDE"] != vcsSystemOverride 3067 and self.pudata["VCSOVERRIDE"] != vcsSystemOverride
2977 ) 3068 )
2978 or (vcsSystemOverride is not None and not self.pudata["VCSOVERRIDE"]) 3069 or (vcsSystemOverride is not None and not self.pudata["VCSOVERRIDE"])
3021 @return list of file patterns for the given type 3112 @return list of file patterns for the given type
3022 @rtype list of str 3113 @rtype list of str
3023 """ 3114 """
3024 return [ 3115 return [
3025 assoc 3116 assoc
3026 for assoc in self.pdata["FILETYPES"] 3117 for assoc in self.__pdata["FILETYPES"]
3027 if self.pdata["FILETYPES"][assoc] == associationType 3118 if self.__pdata["FILETYPES"][assoc] == associationType
3028 ] 3119 ]
3029 3120
3030 def __showLexerAssociations(self): 3121 def __showLexerAssociations(self):
3031 """ 3122 """
3032 Private slot to display the lexer association dialog. 3123 Private slot to display the lexer association dialog.
3046 @param filename filename used to determine the associated lexer 3137 @param filename filename used to determine the associated lexer
3047 language (string) 3138 language (string)
3048 @return the requested lexer language (string) 3139 @return the requested lexer language (string)
3049 """ 3140 """
3050 # try user settings first 3141 # try user settings first
3051 for pattern, language in list(self.pdata["LEXERASSOCS"].items()): 3142 for pattern, language in list(self.__pdata["LEXERASSOCS"].items()):
3052 if fnmatch.fnmatch(filename, pattern): 3143 if fnmatch.fnmatch(filename, pattern):
3053 return language 3144 return language
3054 3145
3055 # try project type specific defaults next 3146 # try project type specific defaults next
3056 projectType = self.pdata["PROJECTTYPE"] 3147 projectType = self.__pdata["PROJECTTYPE"]
3057 with contextlib.suppress(KeyError): 3148 with contextlib.suppress(KeyError):
3058 if self.__lexerAssociationCallbacks[projectType] is not None: 3149 if self.__lexerAssociationCallbacks[projectType] is not None:
3059 return self.__lexerAssociationCallbacks[projectType](filename) 3150 return self.__lexerAssociationCallbacks[projectType](filename)
3060 3151
3061 # return empty string to signal to use the global setting 3152 # return empty string to signal to use the global setting
3096 if fn and self.closeProject(): 3187 if fn and self.closeProject():
3097 with EricOverrideCursor(): 3188 with EricOverrideCursor():
3098 ok = self.__readProject(fn) 3189 ok = self.__readProject(fn)
3099 if ok: 3190 if ok:
3100 self.opened = True 3191 self.opened = True
3101 if not self.pdata["FILETYPES"]: 3192 if not self.__pdata["FILETYPES"]:
3102 self.initFileTypes() 3193 self.initFileTypes()
3103 else: 3194 else:
3104 self.updateFileTypes() 3195 self.updateFileTypes()
3105 3196
3106 try: 3197 try:
3153 vcsSystem = "None" 3244 vcsSystem = "None"
3154 else: 3245 else:
3155 vcsSystem = "None" 3246 vcsSystem = "None"
3156 else: 3247 else:
3157 vcsSystem = vcsData[0][0] 3248 vcsSystem = vcsData[0][0]
3158 self.pdata["VCS"] = vcsSystem 3249 self.__pdata["VCS"] = vcsSystem
3159 self.vcs = self.initVCS() 3250 self.vcs = self.initVCS()
3160 self.setDirty(True) 3251 self.setDirty(True)
3161 if self.vcs is not None and ( 3252 if self.vcs is not None and (
3162 self.vcs.vcsRegisteredState(self.ppath) 3253 self.vcs.vcsRegisteredState(self.ppath)
3163 != self.vcs.canBeCommitted 3254 != self.vcs.canBeCommitted
3164 ): 3255 ):
3165 self.pdata["VCS"] = "None" 3256 self.__pdata["VCS"] = "None"
3166 self.vcs = self.initVCS() 3257 self.vcs = self.initVCS()
3167 self.closeAct.setEnabled(True) 3258 self.closeAct.setEnabled(True)
3168 self.saveasAct.setEnabled(True) 3259 self.saveasAct.setEnabled(True)
3169 self.actGrp2.setEnabled(True) 3260 self.actGrp2.setEnabled(True)
3170 self.propsAct.setEnabled(True) 3261 self.propsAct.setEnabled(True)
3178 self.menuCheckAct.setEnabled(True) 3269 self.menuCheckAct.setEnabled(True)
3179 self.menuShowAct.setEnabled(True) 3270 self.menuShowAct.setEnabled(True)
3180 self.menuDiagramAct.setEnabled(True) 3271 self.menuDiagramAct.setEnabled(True)
3181 self.menuApidocAct.setEnabled(True) 3272 self.menuApidocAct.setEnabled(True)
3182 self.menuPackagersAct.setEnabled(True) 3273 self.menuPackagersAct.setEnabled(True)
3183 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"] in ["E7Plugin"]) 3274 self.pluginGrp.setEnabled(
3275 self.__pdata["PROJECTTYPE"] in ["E7Plugin"]
3276 )
3184 self.addLanguageAct.setEnabled( 3277 self.addLanguageAct.setEnabled(
3185 bool(self.pdata["TRANSLATIONPATTERN"]) 3278 bool(self.__pdata["TRANSLATIONPATTERN"])
3186 ) 3279 )
3187 self.makeGrp.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) 3280 self.makeGrp.setEnabled(self.__pdata["MAKEPARAMS"]["MakeEnabled"])
3188 self.menuMakeAct.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) 3281 self.menuMakeAct.setEnabled(
3282 self.__pdata["MAKEPARAMS"]["MakeEnabled"]
3283 )
3189 self.menuOtherToolsAct.setEnabled(True) 3284 self.menuOtherToolsAct.setEnabled(True)
3190 self.menuFormattingAct.setEnabled(True) 3285 self.menuFormattingAct.setEnabled(True)
3191 3286
3192 # open a project debugger properties file being quiet 3287 # open a project debugger properties file being quiet
3193 # about errors 3288 # about errors
3194 if Preferences.getProject("AutoLoadDbgProperties"): 3289 if Preferences.getProject("AutoLoadDbgProperties"):
3195 self.__readDebugProperties(True) 3290 self.__readDebugProperties(True)
3196 3291
3197 self.__model.projectOpened() 3292 self.__model.projectOpened()
3198 3293
3199 if self.pdata["EMBEDDED_VENV"]: 3294 if self.__pdata["EMBEDDED_VENV"]:
3200 envPath = self.__findEmbeddedEnvironment() 3295 envPath = self.__findEmbeddedEnvironment()
3201 if bool(envPath): 3296 if bool(envPath):
3202 self.__loadEnvironmentConfiguration() 3297 self.__loadEnvironmentConfiguration()
3203 if not bool( 3298 if not bool(
3204 self.__venvConfiguration["interpreter"] 3299 self.__venvConfiguration["interpreter"]
3206 self.__venvConfiguration["interpreter"], os.X_OK 3301 self.__venvConfiguration["interpreter"], os.X_OK
3207 ): 3302 ):
3208 self.__configureEnvironment(envPath) 3303 self.__configureEnvironment(envPath)
3209 else: 3304 else:
3210 self.__createEmbeddedEnvironment() 3305 self.__createEmbeddedEnvironment()
3211 self.menuEnvironmentAct.setEnabled(self.pdata["EMBEDDED_VENV"]) 3306 self.menuEnvironmentAct.setEnabled(self.__pdata["EMBEDDED_VENV"])
3212 3307
3213 self.projectOpenedHooks.emit() 3308 self.projectOpenedHooks.emit()
3214 self.projectOpened.emit() 3309 self.projectOpened.emit()
3215 3310
3216 if Preferences.getProject("SearchNewFiles"): 3311 if Preferences.getProject("SearchNewFiles"):
3223 if Preferences.getProject("TasksProjectRescanOnOpen"): 3318 if Preferences.getProject("TasksProjectRescanOnOpen"):
3224 ericApp().getObject("TaskViewer").regenerateProjectTasks(quiet=True) 3319 ericApp().getObject("TaskViewer").regenerateProjectTasks(quiet=True)
3225 3320
3226 if restoreSession: 3321 if restoreSession:
3227 # open the main script 3322 # open the main script
3228 if self.pdata["MAINSCRIPT"]: 3323 if self.__pdata["MAINSCRIPT"]:
3229 if not os.path.isabs(self.pdata["MAINSCRIPT"]): 3324 if not os.path.isabs(self.__pdata["MAINSCRIPT"]):
3230 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) 3325 ms = os.path.join(self.ppath, self.__pdata["MAINSCRIPT"])
3231 else: 3326 else:
3232 ms = self.pdata["MAINSCRIPT"] 3327 ms = self.__pdata["MAINSCRIPT"]
3233 self.sourceFile.emit(ms) 3328 self.sourceFile.emit(ms)
3234 3329
3235 # open a project session file being quiet about errors 3330 # open a project session file being quiet about errors
3236 if reopen: 3331 if reopen:
3237 self.__readSession(quiet=True, indicator="_tmp") 3332 self.__readSession(quiet=True, indicator="_tmp")
3483 vm = ericApp().getObject("ViewManager") 3578 vm = ericApp().getObject("ViewManager")
3484 success = True 3579 success = True
3485 filesWithSyntaxErrors = 0 3580 filesWithSyntaxErrors = 0
3486 for fn in vm.getOpenFilenames(): 3581 for fn in vm.getOpenFilenames():
3487 rfn = self.getRelativePath(fn) 3582 rfn = self.getRelativePath(fn)
3488 if rfn in self.pdata["SOURCES"] or rfn in self.pdata["OTHERS"]: 3583 if rfn in self.__pdata["SOURCES"] or rfn in self.__pdata["OTHERS"]:
3489 editor = vm.getOpenEditor(fn) 3584 editor = vm.getOpenEditor(fn)
3490 success &= vm.saveEditorEd(editor) 3585 success &= vm.saveEditorEd(editor)
3491 if reportSyntaxErrors and editor.hasSyntaxErrors(): 3586 if reportSyntaxErrors and editor.hasSyntaxErrors():
3492 filesWithSyntaxErrors += 1 3587 filesWithSyntaxErrors += 1
3493 3588
3517 vm = ericApp().getObject("ViewManager") 3612 vm = ericApp().getObject("ViewManager")
3518 success = True 3613 success = True
3519 filesWithSyntaxErrors = 0 3614 filesWithSyntaxErrors = 0
3520 for fn in vm.getOpenFilenames(): 3615 for fn in vm.getOpenFilenames():
3521 rfn = self.getRelativePath(fn) 3616 rfn = self.getRelativePath(fn)
3522 if rfn in self.pdata["SOURCES"] or rfn in self.pdata["OTHERS"]: 3617 if rfn in self.__pdata["SOURCES"] or rfn in self.__pdata["OTHERS"]:
3523 editor = vm.getOpenEditor(fn) 3618 editor = vm.getOpenEditor(fn)
3524 success &= editor.checkDirty() 3619 success &= editor.checkDirty()
3525 if reportSyntaxErrors and editor.hasSyntaxErrors(): 3620 if reportSyntaxErrors and editor.hasSyntaxErrors():
3526 filesWithSyntaxErrors += 1 3621 filesWithSyntaxErrors += 1
3527 3622
3549 @param normalized flag indicating a normalized filename is wanted 3644 @param normalized flag indicating a normalized filename is wanted
3550 @type bool 3645 @type bool
3551 @return filename of the projects main script 3646 @return filename of the projects main script
3552 @rtype str 3647 @rtype str
3553 """ 3648 """
3554 if self.pdata["MAINSCRIPT"]: 3649 if self.__pdata["MAINSCRIPT"]:
3555 if normalized: 3650 if normalized:
3556 return os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) 3651 return os.path.join(self.ppath, self.__pdata["MAINSCRIPT"])
3557 else: 3652 else:
3558 return self.pdata["MAINSCRIPT"] 3653 return self.__pdata["MAINSCRIPT"]
3559 else: 3654 else:
3560 return "" 3655 return ""
3561 3656
3562 def getSources(self, normalized=False): 3657 def getSources(self, normalized=False):
3563 """ 3658 """
3581 @type boolean 3676 @type boolean
3582 @return list of file names 3677 @return list of file names
3583 @rtype list of str 3678 @rtype list of str
3584 @exception ValueError raised when an unsupported file type is given 3679 @exception ValueError raised when an unsupported file type is given
3585 """ 3680 """
3586 if fileType not in [ 3681 if fileType not in self.__knownFileCategories:
3587 "SOURCES", 3682 ##[
3588 "FORMS", 3683 ##"SOURCES",
3589 "RESOURCES", 3684 ##"FORMS",
3590 "INTERFACES", 3685 ##"RESOURCES",
3591 "PROTOCOLS", 3686 ##"INTERFACES",
3592 "OTHERS", 3687 ##"PROTOCOLS",
3593 "TRANSLATIONS", 3688 ##"OTHERS",
3594 ]: 3689 ##"TRANSLATIONS",
3690 ##]:
3595 raise ValueError("Given file type has incorrect value.") 3691 raise ValueError("Given file type has incorrect value.")
3596 3692
3597 if normalized: 3693 if normalized:
3598 return [os.path.join(self.ppath, fn) for fn in self.pdata[fileType]] 3694 return [os.path.join(self.ppath, fn) for fn in self.__pdata[fileType]]
3599 else: 3695 else:
3600 return self.pdata[fileType] 3696 return self.__pdata[fileType]
3601 3697
3602 def getProjectType(self): 3698 def getProjectType(self):
3603 """ 3699 """
3604 Public method to get the type of the project. 3700 Public method to get the type of the project.
3605 3701
3606 @return UI type of the project (string) 3702 @return UI type of the project (string)
3607 """ 3703 """
3608 return self.pdata["PROJECTTYPE"] 3704 return self.__pdata["PROJECTTYPE"]
3609 3705
3610 def getProjectLanguage(self): 3706 def getProjectLanguage(self):
3611 """ 3707 """
3612 Public method to get the project's programming language. 3708 Public method to get the project's programming language.
3613 3709
3614 @return programming language (string) 3710 @return programming language (string)
3615 """ 3711 """
3616 return self.pdata["PROGLANGUAGE"] 3712 return self.__pdata["PROGLANGUAGE"]
3617 3713
3618 def isMixedLanguageProject(self): 3714 def isMixedLanguageProject(self):
3619 """ 3715 """
3620 Public method to check, if this is a mixed language project. 3716 Public method to check, if this is a mixed language project.
3621 3717
3622 @return flag indicating a mixed language project 3718 @return flag indicating a mixed language project
3623 @rtype bool 3719 @rtype bool
3624 """ 3720 """
3625 return self.pdata["MIXEDLANGUAGE"] 3721 return self.__pdata["MIXEDLANGUAGE"]
3626 3722
3627 def isPythonProject(self): 3723 def isPythonProject(self):
3628 """ 3724 """
3629 Public method to check, if this project is a Python3 or MicroPython 3725 Public method to check, if this project is a Python3 or MicroPython
3630 project. 3726 project.
3631 3727
3632 @return flag indicating a Python project (boolean) 3728 @return flag indicating a Python project (boolean)
3633 """ 3729 """
3634 return self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"] 3730 return self.__pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]
3635 3731
3636 def isPy3Project(self): 3732 def isPy3Project(self):
3637 """ 3733 """
3638 Public method to check, if this project is a Python3 project. 3734 Public method to check, if this project is a Python3 project.
3639 3735
3640 @return flag indicating a Python3 project (boolean) 3736 @return flag indicating a Python3 project (boolean)
3641 """ 3737 """
3642 return self.pdata["PROGLANGUAGE"] == "Python3" 3738 return self.__pdata["PROGLANGUAGE"] == "Python3"
3643 3739
3644 def isMicroPythonProject(self): 3740 def isMicroPythonProject(self):
3645 """ 3741 """
3646 Public method to check, if this project is a MicroPython project. 3742 Public method to check, if this project is a MicroPython project.
3647 3743
3648 @return flag indicating a MicroPython project 3744 @return flag indicating a MicroPython project
3649 @rtype bool 3745 @rtype bool
3650 """ 3746 """
3651 return self.pdata["PROGLANGUAGE"] == "MicroPython" 3747 return self.__pdata["PROGLANGUAGE"] == "MicroPython"
3652 3748
3653 def isRubyProject(self): 3749 def isRubyProject(self):
3654 """ 3750 """
3655 Public method to check, if this project is a Ruby project. 3751 Public method to check, if this project is a Ruby project.
3656 3752
3657 @return flag indicating a Ruby project (boolean) 3753 @return flag indicating a Ruby project (boolean)
3658 """ 3754 """
3659 return self.pdata["PROGLANGUAGE"] == "Ruby" 3755 return self.__pdata["PROGLANGUAGE"] == "Ruby"
3660 3756
3661 def isJavaScriptProject(self): 3757 def isJavaScriptProject(self):
3662 """ 3758 """
3663 Public method to check, if this project is a JavaScript project. 3759 Public method to check, if this project is a JavaScript project.
3664 3760
3665 @return flag indicating a JavaScript project (boolean) 3761 @return flag indicating a JavaScript project (boolean)
3666 """ 3762 """
3667 return self.pdata["PROGLANGUAGE"] == "JavaScript" 3763 return self.__pdata["PROGLANGUAGE"] == "JavaScript"
3668 3764
3669 def getProjectSpellLanguage(self): 3765 def getProjectSpellLanguage(self):
3670 """ 3766 """
3671 Public method to get the project's programming language. 3767 Public method to get the project's programming language.
3672 3768
3673 @return programming language (string) 3769 @return programming language (string)
3674 """ 3770 """
3675 return self.pdata["SPELLLANGUAGE"] 3771 return self.__pdata["SPELLLANGUAGE"]
3676 3772
3677 def getProjectDictionaries(self): 3773 def getProjectDictionaries(self):
3678 """ 3774 """
3679 Public method to get the names of the project specific dictionaries. 3775 Public method to get the names of the project specific dictionaries.
3680 3776
3681 @return tuple of two strings giving the absolute path names of the 3777 @return tuple of two strings giving the absolute path names of the
3682 project specific word and exclude list 3778 project specific word and exclude list
3683 """ 3779 """
3684 pwl = "" 3780 pwl = ""
3685 if self.pdata["SPELLWORDS"]: 3781 if self.__pdata["SPELLWORDS"]:
3686 pwl = os.path.join(self.ppath, self.pdata["SPELLWORDS"]) 3782 pwl = os.path.join(self.ppath, self.__pdata["SPELLWORDS"])
3687 if not os.path.isfile(pwl): 3783 if not os.path.isfile(pwl):
3688 pwl = "" 3784 pwl = ""
3689 3785
3690 pel = "" 3786 pel = ""
3691 if self.pdata["SPELLEXCLUDES"]: 3787 if self.__pdata["SPELLEXCLUDES"]:
3692 pel = os.path.join(self.ppath, self.pdata["SPELLEXCLUDES"]) 3788 pel = os.path.join(self.ppath, self.__pdata["SPELLEXCLUDES"])
3693 if not os.path.isfile(pel): 3789 if not os.path.isfile(pel):
3694 pel = "" 3790 pel = ""
3695 3791
3696 return (pwl, pel) 3792 return (pwl, pel)
3697 3793
3700 Public method to get the default extension for the project's 3796 Public method to get the default extension for the project's
3701 programming language. 3797 programming language.
3702 3798
3703 @return default extension (including the dot) (string) 3799 @return default extension (including the dot) (string)
3704 """ 3800 """
3705 lang = self.pdata["PROGLANGUAGE"] 3801 lang = self.__pdata["PROGLANGUAGE"]
3706 if lang in ("", "Python"): 3802 if lang in ("", "Python"):
3707 lang = "Python3" 3803 lang = "Python3"
3708 return self.__sourceExtensions(lang)[0] 3804 return self.__sourceExtensions(lang)[0]
3709 3805
3710 def getProjectPath(self): 3806 def getProjectPath(self):
3776 """ 3872 """
3777 Public method to get the project hash. 3873 Public method to get the project hash.
3778 3874
3779 @return project hash as a hex string (string) 3875 @return project hash as a hex string (string)
3780 """ 3876 """
3781 return self.pdata["HASH"] 3877 return self.__pdata["HASH"]
3782 3878
3783 def getRelativePath(self, path): 3879 def getRelativePath(self, path):
3784 """ 3880 """
3785 Public method to convert a file path to a project relative 3881 Public method to convert a file path to a project relative
3786 file path. 3882 file path.
3833 """ 3929 """
3834 Public method to get the EOL-string to be used by the project. 3930 Public method to get the EOL-string to be used by the project.
3835 3931
3836 @return eol string (string) 3932 @return eol string (string)
3837 """ 3933 """
3838 if self.pdata["EOL"] >= 0: 3934 if self.__pdata["EOL"] >= 0:
3839 return self.eols[self.pdata["EOL"]] 3935 return self.eols[self.__pdata["EOL"]]
3840 else: 3936 else:
3841 eolMode = Preferences.getEditor("EOLMode") 3937 eolMode = Preferences.getEditor("EOLMode")
3842 if eolMode == QsciScintilla.EolMode.EolWindows: 3938 if eolMode == QsciScintilla.EolMode.EolWindows:
3843 eol = "\r\n" 3939 eol = "\r\n"
3844 elif eolMode == QsciScintilla.EolMode.EolUnix: 3940 elif eolMode == QsciScintilla.EolMode.EolUnix:
3853 """ 3949 """
3854 Public method to check, if the project uses the system eol setting. 3950 Public method to check, if the project uses the system eol setting.
3855 3951
3856 @return flag indicating the usage of system eol (boolean) 3952 @return flag indicating the usage of system eol (boolean)
3857 """ 3953 """
3858 return self.pdata["EOL"] == 0 3954 return self.__pdata["EOL"] == 0
3859 3955
3860 def getProjectVersion(self): 3956 def getProjectVersion(self):
3861 """ 3957 """
3862 Public mehod to get the version number of the project. 3958 Public mehod to get the version number of the project.
3863 3959
3864 @return version number 3960 @return version number
3865 @rtype str 3961 @rtype str
3866 """ 3962 """
3867 return self.pdata["VERSION"] 3963 return self.__pdata["VERSION"]
3868 3964
3869 def getProjectAuthor(self): 3965 def getProjectAuthor(self):
3870 """ 3966 """
3871 Public method to get the author of the project. 3967 Public method to get the author of the project.
3872 3968
3873 @return author name 3969 @return author name
3874 @rtype str 3970 @rtype str
3875 """ 3971 """
3876 return self.pdata["AUTHOR"] 3972 return self.__pdata["AUTHOR"]
3877 3973
3878 def getProjectAuthorEmail(self): 3974 def getProjectAuthorEmail(self):
3879 """ 3975 """
3880 Public method to get the email address of the project author. 3976 Public method to get the email address of the project author.
3881 3977
3882 @return project author email 3978 @return project author email
3883 @rtype str 3979 @rtype str
3884 """ 3980 """
3885 return self.pdata["EMAIL"] 3981 return self.__pdata["EMAIL"]
3886 3982
3887 def getProjectDescription(self): 3983 def getProjectDescription(self):
3888 """ 3984 """
3889 Public method to get the description of the project. 3985 Public method to get the description of the project.
3890 3986
3891 @return project description 3987 @return project description
3892 @rtype str 3988 @rtype str
3893 """ 3989 """
3894 return self.pdata["DESCRIPTION"] 3990 return self.__pdata["DESCRIPTION"]
3895 3991
3896 def getProjectVenv(self, resolveDebugger=True): 3992 def getProjectVenv(self, resolveDebugger=True):
3897 """ 3993 """
3898 Public method to get the name of the virtual environment used by the 3994 Public method to get the name of the virtual environment used by the
3899 project. 3995 project.
3904 @return name of the project's virtual environment 4000 @return name of the project's virtual environment
3905 @rtype str 4001 @rtype str
3906 """ 4002 """
3907 venvName = ( 4003 venvName = (
3908 self.__venvConfiguration["name"] 4004 self.__venvConfiguration["name"]
3909 if self.pdata["EMBEDDED_VENV"] and bool(self.__venvConfiguration["name"]) 4005 if self.__pdata["EMBEDDED_VENV"] and bool(self.__venvConfiguration["name"])
3910 else self.getDebugProperty("VIRTUALENV") 4006 else self.getDebugProperty("VIRTUALENV")
3911 ) 4007 )
3912 if ( 4008 if (
3913 not venvName 4009 not venvName
3914 and resolveDebugger 4010 and resolveDebugger
3929 @return path of the project's interpreter 4025 @return path of the project's interpreter
3930 @rtype str 4026 @rtype str
3931 """ 4027 """
3932 interpreter = ( 4028 interpreter = (
3933 self.__venvConfiguration["interpreter"] 4029 self.__venvConfiguration["interpreter"]
3934 if self.pdata["EMBEDDED_VENV"] 4030 if self.__pdata["EMBEDDED_VENV"]
3935 else "" 4031 else ""
3936 ) 4032 )
3937 if not interpreter: 4033 if not interpreter:
3938 venvName = self.getProjectVenv() 4034 venvName = self.getProjectVenv()
3939 if venvName: 4035 if venvName:
3952 Public method to get the executable search path prefix of the project. 4048 Public method to get the executable search path prefix of the project.
3953 4049
3954 @return executable search path prefix 4050 @return executable search path prefix
3955 @rtype str 4051 @rtype str
3956 """ 4052 """
3957 if self.pdata["EMBEDDED_VENV"]: 4053 if self.__pdata["EMBEDDED_VENV"]:
3958 execPath = self.__venvConfiguration["exec_path"] 4054 execPath = self.__venvConfiguration["exec_path"]
3959 else: 4055 else:
3960 execPath = "" 4056 execPath = ""
3961 venvName = self.getProjectVenv() 4057 venvName = self.getProjectVenv()
3962 if venvName: 4058 if venvName:
3974 4070
3975 @return testing framework name of the project 4071 @return testing framework name of the project
3976 @rtype str 4072 @rtype str
3977 """ 4073 """
3978 try: 4074 try:
3979 return self.pdata["TESTING_FRAMEWORK"] 4075 return self.__pdata["TESTING_FRAMEWORK"]
3980 except KeyError: 4076 except KeyError:
3981 return "" 4077 return ""
3982 4078
3983 def getProjectLicense(self): 4079 def getProjectLicense(self):
3984 """ 4080 """
3986 4082
3987 @return license type of the project 4083 @return license type of the project
3988 @rtype str 4084 @rtype str
3989 """ 4085 """
3990 try: 4086 try:
3991 return self.pdata["LICENSE"] 4087 return self.__pdata["LICENSE"]
3992 except KeyError: 4088 except KeyError:
3993 return "" 4089 return ""
3994 4090
3995 def __isInPdata(self, fn): 4091 def __isInPdata(self, fn):
3996 """ 4092 """
4003 @rtype bool 4099 @rtype bool
4004 """ 4100 """
4005 newfn = os.path.abspath(fn) 4101 newfn = os.path.abspath(fn)
4006 newfn = self.getRelativePath(newfn) 4102 newfn = self.getRelativePath(newfn)
4007 return any( 4103 return any(
4008 newfn in self.pdata[group] 4104 newfn in self.__pdata[category]
4009 for group in [ 4105 for category in self.__knownFileCategories
4010 "SOURCES", 4106 ##[
4011 "FORMS", 4107 ##"SOURCES",
4012 "INTERFACES", 4108 ##"FORMS",
4013 "PROTOCOLS", 4109 ##"INTERFACES",
4014 "RESOURCES", 4110 ##"PROTOCOLS",
4015 "TRANSLATIONS", 4111 ##"RESOURCES",
4016 "OTHERS", 4112 ##"TRANSLATIONS",
4017 ] 4113 ##"OTHERS",
4114 ##]
4018 ) 4115 )
4019 4116
4020 def isProjectFile(self, fn): 4117 def isProjectFile(self, fn):
4021 """ 4118 """
4022 Public method used to check, if the passed in filename belongs to the 4119 Public method used to check, if the passed in filename belongs to the
4024 4121
4025 @param fn filename to be checked (string) 4122 @param fn filename to be checked (string)
4026 @return flag indicating membership (boolean) 4123 @return flag indicating membership (boolean)
4027 """ 4124 """
4028 return any( 4125 return any(
4029 self.__checkProjectFileGroup(fn, group) 4126 self.__checkProjectFileGroup(fn, category)
4030 for group in [ 4127 for category in self.__knownFileCategories
4031 "SOURCES", 4128 ##[
4032 "FORMS", 4129 ##"SOURCES",
4033 "INTERFACES", 4130 ##"FORMS",
4034 "PROTOCOLS", 4131 ##"INTERFACES",
4035 "RESOURCES", 4132 ##"PROTOCOLS",
4036 "TRANSLATIONS", 4133 ##"RESOURCES",
4037 "OTHERS", 4134 ##"TRANSLATIONS",
4038 ] 4135 ##"OTHERS",
4136 ##]
4039 ) 4137 )
4040 4138
4041 def __checkProjectFileGroup(self, fn, group): 4139 def __checkProjectFileGroup(self, fn, group):
4042 """ 4140 """
4043 Private method to check, if a file is in a specific file group of the 4141 Private method to check, if a file is in a specific file group of the
4047 @param group group to check (string) 4145 @param group group to check (string)
4048 @return flag indicating membership (boolean) 4146 @return flag indicating membership (boolean)
4049 """ 4147 """
4050 newfn = os.path.abspath(fn) 4148 newfn = os.path.abspath(fn)
4051 newfn = self.getRelativePath(newfn) 4149 newfn = self.getRelativePath(newfn)
4052 if newfn in self.pdata[group] or ( 4150 if newfn in self.__pdata[group] or (
4053 group == "OTHERS" 4151 group == "OTHERS"
4054 and any(newfn.startswith(entry) for entry in self.pdata[group]) 4152 and any(newfn.startswith(entry) for entry in self.__pdata[group])
4055 ): 4153 ):
4056 return True 4154 return True
4057 4155
4058 if Utilities.isWindowsPlatform(): 4156 if Utilities.isWindowsPlatform():
4059 # try the above case-insensitive 4157 # try the above case-insensitive
4060 newfn = newfn.lower() 4158 newfn = newfn.lower()
4061 if any(entry.lower() == newfn for entry in self.pdata[group]): 4159 if any(entry.lower() == newfn for entry in self.__pdata[group]):
4062 return True 4160 return True
4063 4161
4064 elif group == "OTHERS" and any( 4162 elif group == "OTHERS" and any(
4065 newfn.startswith(entry.lower()) for entry in self.pdata[group] 4163 newfn.startswith(entry.lower()) for entry in self.__pdata[group]
4066 ): 4164 ):
4067 return True 4165 return True
4068 4166
4069 return False 4167 return False
4070 4168
4169 # TODO: change the following methods to a more generic logix using fileCategories
4071 def isProjectSource(self, fn): 4170 def isProjectSource(self, fn):
4072 """ 4171 """
4073 Public method used to check, if the passed in filename belongs to the 4172 Public method used to check, if the passed in filename belongs to the
4074 project sources. 4173 project sources.
4075 4174
5390 def __showMenu(self): 5489 def __showMenu(self):
5391 """ 5490 """
5392 Private method to set up the project menu. 5491 Private method to set up the project menu.
5393 """ 5492 """
5394 self.menuRecentAct.setEnabled(len(self.recent) > 0) 5493 self.menuRecentAct.setEnabled(len(self.recent) > 0)
5395 self.menuEnvironmentAct.setEnabled(self.pdata["EMBEDDED_VENV"]) 5494 self.menuEnvironmentAct.setEnabled(self.__pdata["EMBEDDED_VENV"])
5396 5495
5397 self.showMenu.emit("Main", self.__menus["Main"]) 5496 self.showMenu.emit("Main", self.__menus["Main"])
5398 5497
5399 def __syncRecent(self): 5498 def __syncRecent(self):
5400 """ 5499 """
5500 recursiveSearch = Preferences.getProject("SearchNewFilesRecursively") 5599 recursiveSearch = Preferences.getProject("SearchNewFilesRecursively")
5501 newFiles = [] 5600 newFiles = []
5502 5601
5503 ignore_patterns = [ 5602 ignore_patterns = [
5504 pattern 5603 pattern
5505 for pattern, filetype in self.pdata["FILETYPES"].items() 5604 for pattern, filetype in self.__pdata["FILETYPES"].items()
5506 if filetype == "__IGNORE__" 5605 if filetype == "__IGNORE__"
5507 ] 5606 ]
5508 5607
5509 dirs = self.subdirs[:] 5608 dirs = self.subdirs[:]
5510 for directory in dirs: 5609 for directory in dirs:
5520 try: 5619 try:
5521 newSources = os.listdir(curpath) 5620 newSources = os.listdir(curpath)
5522 except OSError: 5621 except OSError:
5523 newSources = [] 5622 newSources = []
5524 pattern = ( 5623 pattern = (
5525 self.pdata["TRANSLATIONPATTERN"].replace("%language%", "*") 5624 self.__pdata["TRANSLATIONPATTERN"].replace("%language%", "*")
5526 if self.pdata["TRANSLATIONPATTERN"] 5625 if self.__pdata["TRANSLATIONPATTERN"]
5527 else "*.ts" 5626 else "*.ts"
5528 ) 5627 )
5529 binpattern = self.__binaryTranslationFile(pattern) 5628 binpattern = self.__binaryTranslationFile(pattern)
5530 for ns in newSources: 5629 for ns in newSources:
5531 # ignore hidden files and directories 5630 # ignore hidden files and directories
5553 dirs.append(d) 5652 dirs.append(d)
5554 continue 5653 continue
5555 5654
5556 filetype = "" 5655 filetype = ""
5557 bfn = os.path.basename(fn) 5656 bfn = os.path.basename(fn)
5558 for pattern in sorted(self.pdata["FILETYPES"].keys(), reverse=True): 5657 for pattern in sorted(self.__pdata["FILETYPES"].keys(), reverse=True):
5559 if fnmatch.fnmatch(bfn, pattern): 5658 if fnmatch.fnmatch(bfn, pattern):
5560 filetype = self.pdata["FILETYPES"][pattern] 5659 filetype = self.__pdata["FILETYPES"][pattern]
5561 break 5660 break
5562 5661
5563 if ( 5662 if (
5564 (filetype == "SOURCES" and fn not in self.pdata["SOURCES"]) 5663 filetype in self.__knownFileCategories
5565 or (filetype == "FORMS" and fn not in self.pdata["FORMS"]) 5664 and fn not in self.__pdata[filetype]
5566 or (filetype == "INTERFACES" and fn not in self.pdata["INTERFACES"]) 5665 and (
5567 or (filetype == "PROTOCOLS" and fn not in self.pdata["PROTOCOLS"]) 5666 filetype != "TRANSLATIONS"
5568 or (filetype == "RESOURCES" and fn not in self.pdata["RESOURCES"]) 5667 or (
5569 or (filetype == "OTHERS" and fn not in self.pdata["OTHERS"]) 5668 filetype == "TRANSLATIONS"
5570 or ( 5669 and (
5571 filetype == "TRANSLATIONS" 5670 fnmatch.fnmatch(ns, pattern)
5572 and fn not in self.pdata["TRANSLATIONS"] 5671 or fnmatch.fnmatch(ns, binpattern)
5573 and ( 5672 )
5574 fnmatch.fnmatch(ns, pattern)
5575 or fnmatch.fnmatch(ns, binpattern)
5576 ) 5673 )
5577 ) 5674 )
5578 ): 5675 ):
5676 ##(filetype == "SOURCES" and fn not in self.__pdata["SOURCES"])
5677 ##or (filetype == "FORMS" and fn not in self.__pdata["FORMS"])
5678 ##or (filetype == "INTERFACES" and fn not in self.__pdata["INTERFACES"])
5679 ##or (filetype == "PROTOCOLS" and fn not in self.__pdata["PROTOCOLS"])
5680 ##or (filetype == "RESOURCES" and fn not in self.__pdata["RESOURCES"])
5681 ##or (filetype == "OTHERS" and fn not in self.__pdata["OTHERS"])
5682 ##or (
5683 ##filetype == "TRANSLATIONS"
5684 ##and fn not in self.__pdata["TRANSLATIONS"]
5685 ##and (
5686 ##fnmatch.fnmatch(ns, pattern)
5687 ##or fnmatch.fnmatch(ns, binpattern)
5688 ##)
5689 ##)
5690 ##):
5579 if autoInclude and AI: 5691 if autoInclude and AI:
5580 self.appendFile(ns) 5692 self.appendFile(ns)
5581 else: 5693 else:
5582 newFiles.append(ns) 5694 newFiles.append(ns)
5583 5695
5693 vcs = None 5805 vcs = None
5694 forProject = True 5806 forProject = True
5695 override = False 5807 override = False
5696 5808
5697 if vcsSystem is None: 5809 if vcsSystem is None:
5698 if self.pdata["VCS"] and self.pdata["VCS"] != "None": 5810 if self.__pdata["VCS"] and self.__pdata["VCS"] != "None":
5699 vcsSystem = self.pdata["VCS"] 5811 vcsSystem = self.__pdata["VCS"]
5700 else: 5812 else:
5701 forProject = False 5813 forProject = False
5702 5814
5703 if ( 5815 if (
5704 forProject 5816 forProject
5705 and self.pdata["VCS"] 5817 and self.__pdata["VCS"]
5706 and self.pdata["VCS"] != "None" 5818 and self.__pdata["VCS"] != "None"
5707 and self.pudata["VCSOVERRIDE"] 5819 and self.pudata["VCSOVERRIDE"]
5708 and not nooverride 5820 and not nooverride
5709 ): 5821 ):
5710 vcsSystem = self.pudata["VCSOVERRIDE"] 5822 vcsSystem = self.pudata["VCSOVERRIDE"]
5711 override = True 5823 override = True
5747 "<p>{1}</p>" 5859 "<p>{1}</p>"
5748 ).format(vcsSystem, msg), 5860 ).format(vcsSystem, msg),
5749 ) 5861 )
5750 vcs = None 5862 vcs = None
5751 if forProject: 5863 if forProject:
5752 self.pdata["VCS"] = "None" 5864 self.__pdata["VCS"] = "None"
5753 self.setDirty(True) 5865 self.setDirty(True)
5754 else: 5866 else:
5755 vcs.vcsInitConfig(self) 5867 vcs.vcsInitConfig(self)
5756 5868
5757 if vcs and forProject: 5869 if vcs and forProject:
5758 # set the vcs options 5870 # set the vcs options
5759 if vcs.vcsSupportCommandOptions(): 5871 if vcs.vcsSupportCommandOptions():
5760 with contextlib.suppress(LookupError): 5872 with contextlib.suppress(LookupError):
5761 vcsopt = copy.deepcopy(self.pdata["VCSOPTIONS"]) 5873 vcsopt = copy.deepcopy(self.__pdata["VCSOPTIONS"])
5762 vcs.vcsSetOptions(vcsopt) 5874 vcs.vcsSetOptions(vcsopt)
5763 # set vcs specific data 5875 # set vcs specific data
5764 with contextlib.suppress(LookupError): 5876 with contextlib.suppress(LookupError):
5765 vcsother = copy.deepcopy(self.pdata["VCSOTHERDATA"]) 5877 vcsother = copy.deepcopy(self.__pdata["VCSOTHERDATA"])
5766 vcs.vcsSetOtherData(vcsother) 5878 vcs.vcsSetOtherData(vcsother)
5767 5879
5768 if forProject: 5880 if forProject:
5769 if vcs is None: 5881 if vcs is None:
5770 self.vcsProjectHelper = VCS.getBasicHelper(self) 5882 self.vcsProjectHelper = VCS.getBasicHelper(self)
5780 5892
5781 def resetVCS(self): 5893 def resetVCS(self):
5782 """ 5894 """
5783 Public method to reset the VCS. 5895 Public method to reset the VCS.
5784 """ 5896 """
5785 self.pdata["VCS"] = "None" 5897 self.__pdata["VCS"] = "None"
5786 self.vcs = self.initVCS() 5898 self.vcs = self.initVCS()
5787 ericApp().getObject("PluginManager").deactivateVcsPlugins() 5899 ericApp().getObject("PluginManager").deactivateVcsPlugins()
5788 5900
5789 def __showContextMenuVCS(self): 5901 def __showContextMenuVCS(self):
5790 """ 5902 """
5869 """ 5981 """
5870 from eric7.DataViews.CodeMetricsDialog import CodeMetricsDialog 5982 from eric7.DataViews.CodeMetricsDialog import CodeMetricsDialog
5871 5983
5872 files = [ 5984 files = [
5873 os.path.join(self.ppath, file) 5985 os.path.join(self.ppath, file)
5874 for file in self.pdata["SOURCES"] 5986 for file in self.__pdata["SOURCES"]
5875 if file.endswith(".py") 5987 if file.endswith(".py")
5876 ] 5988 ]
5877 self.codemetrics = CodeMetricsDialog() 5989 self.codemetrics = CodeMetricsDialog()
5878 self.codemetrics.show() 5990 self.codemetrics.show()
5879 self.codemetrics.prepare(files) 5991 self.codemetrics.prepare(files)
5915 else: 6027 else:
5916 return 6028 return
5917 6029
5918 files = [ 6030 files = [
5919 os.path.join(self.ppath, file) 6031 os.path.join(self.ppath, file)
5920 for file in self.pdata["SOURCES"] 6032 for file in self.__pdata["SOURCES"]
5921 if os.path.splitext(file)[1].startswith(".py") 6033 if os.path.splitext(file)[1].startswith(".py")
5922 ] 6034 ]
5923 self.codecoverage = PyCoverageDialog() 6035 self.codecoverage = PyCoverageDialog()
5924 self.codecoverage.show() 6036 self.codecoverage.show()
5925 self.codecoverage.start(fn, files) 6037 self.codecoverage.start(fn, files)
6143 if not res: 6255 if not res:
6144 return # don't overwrite 6256 return # don't overwrite
6145 6257
6146 # build the list of entries 6258 # build the list of entries
6147 lst_ = [] 6259 lst_ = []
6148 for key in [ 6260 for key in self.__knownFileCategories:
6149 "SOURCES", 6261 ##[
6150 "FORMS", 6262 ##"SOURCES",
6151 "RESOURCES", 6263 ##"FORMS",
6152 "TRANSLATIONS", 6264 ##"RESOURCES",
6153 "INTERFACES", 6265 ##"TRANSLATIONS",
6154 "PROTOCOLS", 6266 ##"INTERFACES",
6155 "OTHERS", 6267 ##"PROTOCOLS",
6156 ]: 6268 ##"OTHERS",
6157 lst_.extend(self.pdata[key]) 6269 ##]:
6270 lst_.extend(self.__pdata[key])
6158 lst = [] 6271 lst = []
6159 for entry in lst_: 6272 for entry in lst_:
6160 if os.path.isdir(self.getAbsolutePath(entry)): 6273 if os.path.isdir(self.getAbsolutePath(entry)):
6161 lst.extend( 6274 lst.extend(
6162 [ 6275 [
6179 " ", 6292 " ",
6180 ] 6293 ]
6181 6294
6182 # write the file 6295 # write the file
6183 try: 6296 try:
6184 newline = None if self.pdata["EOL"] == 0 else self.getEolString() 6297 newline = None if self.__pdata["EOL"] == 0 else self.getEolString()
6185 with open(pkglist, "w", encoding="utf-8", newline=newline) as pkglistFile: 6298 with open(pkglist, "w", encoding="utf-8", newline=newline) as pkglistFile:
6186 pkglistFile.write("\n".join(header) + "\n") 6299 pkglistFile.write("\n".join(header) + "\n")
6187 pkglistFile.write( 6300 pkglistFile.write(
6188 "\n".join([Utilities.fromNativeSeparators(f) for f in lst]) 6301 "\n".join([Utilities.fromNativeSeparators(f) for f in lst])
6189 ) 6302 )
6198 """<p>Reason: {0}</p>""" 6311 """<p>Reason: {0}</p>"""
6199 ).format(str(why)), 6312 ).format(str(why)),
6200 ) 6313 )
6201 return 6314 return
6202 6315
6203 if "PKGLIST" not in self.pdata["OTHERS"]: 6316 if "PKGLIST" not in self.__pdata["OTHERS"]:
6204 self.appendFile("PKGLIST") 6317 self.appendFile("PKGLIST")
6205 6318
6206 @pyqtSlot() 6319 @pyqtSlot()
6207 def __pluginCreateArchives(self, snapshot=False): 6320 def __pluginCreateArchives(self, snapshot=False):
6208 """ 6321 """
6209 Private slot to create eric plugin archives. 6322 Private slot to create eric plugin archives.
6210 6323
6211 @param snapshot flag indicating snapshot archives (boolean) 6324 @param snapshot flag indicating snapshot archives (boolean)
6212 """ 6325 """
6213 if not self.pdata["MAINSCRIPT"]: 6326 if not self.__pdata["MAINSCRIPT"]:
6214 EricMessageBox.critical( 6327 EricMessageBox.critical(
6215 self.ui, 6328 self.ui,
6216 self.tr("Create Plugin Archive"), 6329 self.tr("Create Plugin Archive"),
6217 self.tr( 6330 self.tr(
6218 """The project does not have a main script defined. """ 6331 """The project does not have a main script defined. """
6322 names = sorted(names) 6435 names = sorted(names)
6323 archive = ( 6436 archive = (
6324 os.path.join(self.ppath, archiveName) 6437 os.path.join(self.ppath, archiveName)
6325 if archiveName 6438 if archiveName
6326 else os.path.join( 6439 else os.path.join(
6327 self.ppath, self.pdata["MAINSCRIPT"].replace(".py", ".zip") 6440 self.ppath, self.__pdata["MAINSCRIPT"].replace(".py", ".zip")
6328 ) 6441 )
6329 ) 6442 )
6330 try: 6443 try:
6331 archiveFile = zipfile.ZipFile(archive, "w") 6444 archiveFile = zipfile.ZipFile(archive, "w")
6332 except OSError as why: 6445 except OSError as why:
6344 6457
6345 for name in names: 6458 for name in names:
6346 if name: 6459 if name:
6347 try: 6460 try:
6348 self.__createZipDirEntries(os.path.split(name)[0], archiveFile) 6461 self.__createZipDirEntries(os.path.split(name)[0], archiveFile)
6349 if snapshot and name == self.pdata["MAINSCRIPT"]: 6462 if snapshot and name == self.__pdata["MAINSCRIPT"]:
6350 snapshotSource, version = self.__createSnapshotSource( 6463 snapshotSource, version = self.__createSnapshotSource(
6351 os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) 6464 os.path.join(self.ppath, self.__pdata["MAINSCRIPT"])
6352 ) 6465 )
6353 archiveFile.writestr(name, snapshotSource) 6466 archiveFile.writestr(name, snapshotSource)
6354 else: 6467 else:
6355 archiveFile.write(os.path.join(self.ppath, name), name) 6468 archiveFile.write(os.path.join(self.ppath, name), name)
6356 if name == self.pdata["MAINSCRIPT"]: 6469 if name == self.__pdata["MAINSCRIPT"]:
6357 version = self.__pluginExtractVersion( 6470 version = self.__pluginExtractVersion(
6358 os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) 6471 os.path.join(self.ppath, self.__pdata["MAINSCRIPT"])
6359 ) 6472 )
6360 if archiveVersion and ( 6473 if archiveVersion and (
6361 self.__pluginVersionToTuple(version) 6474 self.__pluginVersionToTuple(version)
6362 < self.__pluginVersionToTuple(archiveVersion) 6475 < self.__pluginVersionToTuple(archiveVersion)
6363 ): 6476 ):
6373 ).format(os.path.join(self.ppath, name), str(why)), 6486 ).format(os.path.join(self.ppath, name), str(why)),
6374 ) 6487 )
6375 archiveFile.writestr("VERSION", version.encode("utf-8")) 6488 archiveFile.writestr("VERSION", version.encode("utf-8"))
6376 archiveFile.close() 6489 archiveFile.close()
6377 6490
6378 if archive not in self.pdata["OTHERS"]: 6491 if archive not in self.__pdata["OTHERS"]:
6379 self.appendFile(archive) 6492 self.appendFile(archive)
6380 6493
6381 progress.setValue(len(selectedLists)) 6494 progress.setValue(len(selectedLists))
6382 6495
6383 if errors: 6496 if errors:
6518 parameters. 6631 parameters.
6519 6632
6520 @return flag indicating default parameter set 6633 @return flag indicating default parameter set
6521 @rtype bool 6634 @rtype bool
6522 """ 6635 """
6523 return self.pdata["MAKEPARAMS"] == { 6636 return self.__pdata["MAKEPARAMS"] == {
6524 "MakeEnabled": False, 6637 "MakeEnabled": False,
6525 "MakeExecutable": "", 6638 "MakeExecutable": "",
6526 "MakeFile": "", 6639 "MakeFile": "",
6527 "MakeTarget": "", 6640 "MakeTarget": "",
6528 "MakeParameters": "", 6641 "MakeParameters": "",
6534 Public method to test, if make is enabled for the project. 6647 Public method to test, if make is enabled for the project.
6535 6648
6536 @return flag indicating enabled make support 6649 @return flag indicating enabled make support
6537 @rtype bool 6650 @rtype bool
6538 """ 6651 """
6539 return self.pdata["MAKEPARAMS"]["MakeEnabled"] 6652 return self.__pdata["MAKEPARAMS"]["MakeEnabled"]
6540 6653
6541 @pyqtSlot() 6654 @pyqtSlot()
6542 def executeMake(self): 6655 def executeMake(self):
6543 """ 6656 """
6544 Public slot to execute a project specific make run (auto-run) 6657 Public slot to execute a project specific make run (auto-run)
6545 (execute or question). 6658 (execute or question).
6546 """ 6659 """
6547 self.__executeMake( 6660 self.__executeMake(
6548 questionOnly=self.pdata["MAKEPARAMS"]["MakeTestOnly"], interactive=False 6661 questionOnly=self.__pdata["MAKEPARAMS"]["MakeTestOnly"], interactive=False
6549 ) 6662 )
6550 6663
6551 @pyqtSlot() 6664 @pyqtSlot()
6552 def __executeMake(self, questionOnly=False, interactive=True): 6665 def __executeMake(self, questionOnly=False, interactive=True):
6553 """ 6666 """
6558 @param interactive flag indicating an interactive invocation (i.e. 6671 @param interactive flag indicating an interactive invocation (i.e.
6559 through a menu action) 6672 through a menu action)
6560 @type bool 6673 @type bool
6561 """ 6674 """
6562 if ( 6675 if (
6563 not self.pdata["MAKEPARAMS"]["MakeEnabled"] 6676 not self.__pdata["MAKEPARAMS"]["MakeEnabled"]
6564 or self.__makeProcess is not None 6677 or self.__makeProcess is not None
6565 ): 6678 ):
6566 return 6679 return
6567 6680
6568 prog = ( 6681 prog = (
6569 self.pdata["MAKEPARAMS"]["MakeExecutable"] 6682 self.__pdata["MAKEPARAMS"]["MakeExecutable"]
6570 if self.pdata["MAKEPARAMS"]["MakeExecutable"] 6683 if self.__pdata["MAKEPARAMS"]["MakeExecutable"]
6571 else Project.DefaultMake 6684 else Project.DefaultMake
6572 ) 6685 )
6573 6686
6574 args = [] 6687 args = []
6575 if self.pdata["MAKEPARAMS"]["MakeParameters"]: 6688 if self.__pdata["MAKEPARAMS"]["MakeParameters"]:
6576 args.extend( 6689 args.extend(
6577 Utilities.parseOptionString(self.pdata["MAKEPARAMS"]["MakeParameters"]) 6690 Utilities.parseOptionString(
6578 ) 6691 self.__pdata["MAKEPARAMS"]["MakeParameters"]
6579 6692 )
6580 if self.pdata["MAKEPARAMS"]["MakeFile"]: 6693 )
6581 args.append("--makefile={0}".format(self.pdata["MAKEPARAMS"]["MakeFile"])) 6694
6695 if self.__pdata["MAKEPARAMS"]["MakeFile"]:
6696 args.append("--makefile={0}".format(self.__pdata["MAKEPARAMS"]["MakeFile"]))
6582 6697
6583 if questionOnly: 6698 if questionOnly:
6584 args.append("--question") 6699 args.append("--question")
6585 6700
6586 if self.pdata["MAKEPARAMS"]["MakeTarget"]: 6701 if self.__pdata["MAKEPARAMS"]["MakeTarget"]:
6587 args.append(self.pdata["MAKEPARAMS"]["MakeTarget"]) 6702 args.append(self.__pdata["MAKEPARAMS"]["MakeTarget"])
6588 6703
6589 self.__makeProcess = QProcess(self) 6704 self.__makeProcess = QProcess(self)
6590 self.__makeProcess.readyReadStandardOutput.connect(self.__makeReadStdOut) 6705 self.__makeProcess.readyReadStandardOutput.connect(self.__makeReadStdOut)
6591 self.__makeProcess.readyReadStandardError.connect(self.__makeReadStdErr) 6706 self.__makeProcess.readyReadStandardError.connect(self.__makeReadStdErr)
6592 self.__makeProcess.finished.connect( 6707 self.__makeProcess.finished.connect(
6655 else: 6770 else:
6656 if questionOnly and exitCode == 1: 6771 if questionOnly and exitCode == 1:
6657 # a rebuild is needed 6772 # a rebuild is needed
6658 title = self.tr("Test for Changes") 6773 title = self.tr("Test for Changes")
6659 6774
6660 if self.pdata["MAKEPARAMS"]["MakeTarget"]: 6775 if self.__pdata["MAKEPARAMS"]["MakeTarget"]:
6661 message = self.tr( 6776 message = self.tr(
6662 """<p>There are changes that require the configured""" 6777 """<p>There are changes that require the configured"""
6663 """ make target <b>{0}</b> to be rebuilt.</p>""" 6778 """ make target <b>{0}</b> to be rebuilt.</p>"""
6664 ).format(self.pdata["MAKEPARAMS"]["MakeTarget"]) 6779 ).format(self.__pdata["MAKEPARAMS"]["MakeTarget"])
6665 else: 6780 else:
6666 message = self.tr( 6781 message = self.tr(
6667 """<p>There are changes that require the default""" 6782 """<p>There are changes that require the default"""
6668 """ make target to be rebuilt.</p>""" 6783 """ make target to be rebuilt.</p>"""
6669 ) 6784 )
6704 parameters. 6819 parameters.
6705 6820
6706 @return flag indicating default parameter set 6821 @return flag indicating default parameter set
6707 @rtype bool 6822 @rtype bool
6708 """ 6823 """
6709 return self.pdata["IDLPARAMS"] == { 6824 return self.__pdata["IDLPARAMS"] == {
6710 "IncludeDirs": [], 6825 "IncludeDirs": [],
6711 "DefinedNames": [], 6826 "DefinedNames": [],
6712 "UndefinedNames": [], 6827 "UndefinedNames": [],
6713 } 6828 }
6714 6829
6722 parameters. 6837 parameters.
6723 6838
6724 @return flag indicating default parameter set 6839 @return flag indicating default parameter set
6725 @rtype bool 6840 @rtype bool
6726 """ 6841 """
6727 return self.pdata["UICPARAMS"] == { 6842 return self.__pdata["UICPARAMS"] == {
6728 "Package": "", 6843 "Package": "",
6729 "RcSuffix": "", 6844 "RcSuffix": "",
6730 "PackagesRoot": "", 6845 "PackagesRoot": "",
6731 } 6846 }
6732 6847
6737 @param name name of the parameter 6852 @param name name of the parameter
6738 @type str 6853 @type str
6739 @return value of the given parameter 6854 @return value of the given parameter
6740 @rtype any, None in case on non-existence 6855 @rtype any, None in case on non-existence
6741 """ 6856 """
6742 if name in self.pdata["UICPARAMS"]: 6857 if name in self.__pdata["UICPARAMS"]:
6743 return self.pdata["UICPARAMS"][name] 6858 return self.__pdata["UICPARAMS"][name]
6744 else: 6859 else:
6745 return None 6860 return None
6746 6861
6747 ######################################################################### 6862 #########################################################################
6748 ## Below are methods implementing some 'RCC' support functions 6863 ## Below are methods implementing some 'RCC' support functions
6754 parameters. 6869 parameters.
6755 6870
6756 @return flag indicating default parameter set 6871 @return flag indicating default parameter set
6757 @rtype bool 6872 @rtype bool
6758 """ 6873 """
6759 return self.pdata["RCCPARAMS"] == self.getDefaultRccCompilerParameters() 6874 return self.__pdata["RCCPARAMS"] == self.getDefaultRccCompilerParameters()
6760 6875
6761 def getDefaultRccCompilerParameters(self): 6876 def getDefaultRccCompilerParameters(self):
6762 """ 6877 """
6763 Public method to get the default rcc compiler parameters. 6878 Public method to get the default rcc compiler parameters.
6764 6879
6782 parameter. 6897 parameter.
6783 6898
6784 @return flag indicating default parameter 6899 @return flag indicating default parameter
6785 @rtype bool 6900 @rtype bool
6786 """ 6901 """
6787 return self.pdata["DOCSTRING"] == "" 6902 return self.__pdata["DOCSTRING"] == ""
6788 6903
6789 def getDocstringType(self): 6904 def getDocstringType(self):
6790 """ 6905 """
6791 Public method to get the configured docstring style. 6906 Public method to get the configured docstring style.
6792 6907
6793 @return configured docstring style 6908 @return configured docstring style
6794 @rtype str 6909 @rtype str
6795 """ 6910 """
6796 return self.pdata["DOCSTRING"] 6911 return self.__pdata["DOCSTRING"]
6797 6912
6798 ######################################################################### 6913 #########################################################################
6799 ## Below are methods implementing the 'SBOM' support 6914 ## Below are methods implementing the 'SBOM' support
6800 ######################################################################### 6915 #########################################################################
6801 6916
6954 Private method to set the embedded environment project configuration. 7069 Private method to set the embedded environment project configuration.
6955 7070
6956 @param value flag indicating an embedded environment 7071 @param value flag indicating an embedded environment
6957 @type bool 7072 @type bool
6958 """ 7073 """
6959 if value != self.pdata["EMBEDDED_VENV"]: 7074 if value != self.__pdata["EMBEDDED_VENV"]:
6960 self.pdata["EMBEDDED_VENV"] = value 7075 self.__pdata["EMBEDDED_VENV"] = value
6961 self.setDirty(True) 7076 self.setDirty(True)
6962 7077
6963 def __initVenvConfiguration(self): 7078 def __initVenvConfiguration(self):
6964 """ 7079 """
6965 Private method to initialize the environment configuration. 7080 Private method to initialize the environment configuration.

eric ide

mercurial