8190:fb0ef164f536 | 8273:698ae46f40a4 |
---|---|
12 import shutil | 12 import shutil |
13 import glob | 13 import glob |
14 import fnmatch | 14 import fnmatch |
15 import copy | 15 import copy |
16 import zipfile | 16 import zipfile |
17 import contextlib | |
17 | 18 |
18 from PyQt5.QtCore import ( | 19 from PyQt5.QtCore import ( |
19 pyqtSlot, QFile, QFileInfo, pyqtSignal, QCryptographicHash, QIODevice, | 20 pyqtSlot, QFile, QFileInfo, pyqtSignal, QCryptographicHash, QIODevice, |
20 QByteArray, QObject, QProcess | 21 QByteArray, QObject, QProcess |
21 ) | 22 ) |
166 Constructor | 167 Constructor |
167 | 168 |
168 @param parent parent widget (usually the ui object) (QWidget) | 169 @param parent parent widget (usually the ui object) (QWidget) |
169 @param filename optional filename of a project file to open (string) | 170 @param filename optional filename of a project file to open (string) |
170 """ | 171 """ |
171 super(Project, self).__init__(parent) | 172 super().__init__(parent) |
172 | 173 |
173 self.ui = parent | 174 self.ui = parent |
174 | 175 |
175 self.__progLanguages = [ | 176 self.__progLanguages = [ |
176 "Python3", | 177 "Python3", |
235 # *.py should always be associated with source files | 236 # *.py should always be associated with source files |
236 for ext in [".py"]: | 237 for ext in [".py"]: |
237 if ext not in extensions: | 238 if ext not in extensions: |
238 extensions.append(ext) | 239 extensions.append(ext) |
239 return extensions | 240 return extensions |
240 elif language == "Ruby": | |
241 return ['.rb'] | |
242 elif language == "JavaScript": | |
243 return ['.js'] | |
244 elif language == "Mixed": | |
245 return (Preferences.getPython("Python3Extensions") + | |
246 ['.rb', '.js']) | |
247 else: | 241 else: |
248 return [""] | 242 return { |
243 "Ruby": [".rb"], | |
244 "JavaScript": [".js"], | |
245 "Mixed": ( | |
246 Preferences.getPython("Python3Extensions") + | |
247 ['.rb', '.js']), | |
248 }.get(language, "") | |
249 | 249 |
250 def getProgrammingLanguages(self): | 250 def getProgrammingLanguages(self): |
251 """ | 251 """ |
252 Public method to get the programming languages supported by project. | 252 Public method to get the programming languages supported by project. |
253 | 253 |
605 "makefile": "OTHERS", | 605 "makefile": "OTHERS", |
606 "Makefile": "OTHERS", | 606 "Makefile": "OTHERS", |
607 } | 607 } |
608 | 608 |
609 # Sources | 609 # Sources |
610 if self.pdata["MIXEDLANGUAGE"]: | 610 sourceKey = ( |
611 sourceKey = "Mixed" | 611 "Mixed" |
612 else: | 612 if self.pdata["MIXEDLANGUAGE"] else |
613 sourceKey = self.pdata["PROGLANGUAGE"] | 613 self.pdata["PROGLANGUAGE"] |
614 ) | |
614 for ext in self.__sourceExtensions(sourceKey): | 615 for ext in self.__sourceExtensions(sourceKey): |
615 self.pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES" | 616 self.pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES" |
616 | 617 |
617 # IDL interfaces | 618 # IDL interfaces |
618 self.pdata["FILETYPES"]["*.idl"] = "INTERFACES" | 619 self.pdata["FILETYPES"]["*.idl"] = "INTERFACES" |
643 "PySide6", "PySide6C"]: | 644 "PySide6", "PySide6C"]: |
644 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" | 645 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" |
645 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" | 646 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" |
646 | 647 |
647 # Project type specific ones | 648 # Project type specific ones |
648 try: | 649 with contextlib.suppress(KeyError): |
649 if self.__fileTypeCallbacks[ | 650 if self.__fileTypeCallbacks[ |
650 self.pdata["PROJECTTYPE"]] is not None: | 651 self.pdata["PROJECTTYPE"]] is not None: |
651 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() | 652 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() |
652 self.pdata["FILETYPES"].update(ftypes) | 653 self.pdata["FILETYPES"].update(ftypes) |
653 except KeyError: | |
654 pass | |
655 | 654 |
656 self.setDirty(True) | 655 self.setDirty(True) |
657 | 656 |
658 def updateFileTypes(self): | 657 def updateFileTypes(self): |
659 """ | 658 """ |
667 "PySide6", "PySide6C"]: | 666 "PySide6", "PySide6C"]: |
668 if "*.ts" not in self.pdata["FILETYPES"]: | 667 if "*.ts" not in self.pdata["FILETYPES"]: |
669 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" | 668 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" |
670 if "*.qm" not in self.pdata["FILETYPES"]: | 669 if "*.qm" not in self.pdata["FILETYPES"]: |
671 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" | 670 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" |
672 try: | 671 with contextlib.suppress(KeyError): |
673 if self.__fileTypeCallbacks[ | 672 if self.__fileTypeCallbacks[ |
674 self.pdata["PROJECTTYPE"]] is not None: | 673 self.pdata["PROJECTTYPE"]] is not None: |
675 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() | 674 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() |
676 for pattern, ftype in list(ftypes.items()): | 675 for pattern, ftype in list(ftypes.items()): |
677 if pattern not in self.pdata["FILETYPES"]: | 676 if pattern not in self.pdata["FILETYPES"]: |
678 self.pdata["FILETYPES"][pattern] = ftype | 677 self.pdata["FILETYPES"][pattern] = ftype |
679 self.setDirty(True) | 678 self.setDirty(True) |
680 except KeyError: | |
681 pass | |
682 | 679 |
683 def __loadRecent(self): | 680 def __loadRecent(self): |
684 """ | 681 """ |
685 Private method to load the recently opened project filenames. | 682 Private method to load the recently opened project filenames. |
686 """ | 683 """ |
1490 langFile = self.getRelativePath(langFile) | 1487 langFile = self.getRelativePath(langFile) |
1491 qmFile = self.__binaryTranslationFile(langFile) | 1488 qmFile = self.__binaryTranslationFile(langFile) |
1492 self.pdata["TRANSLATIONS"].remove(langFile) | 1489 self.pdata["TRANSLATIONS"].remove(langFile) |
1493 self.__model.removeItem(langFile) | 1490 self.__model.removeItem(langFile) |
1494 if qmFile: | 1491 if qmFile: |
1495 try: | 1492 with contextlib.suppress(ValueError): |
1496 if self.pdata["TRANSLATIONSBINPATH"]: | 1493 if self.pdata["TRANSLATIONSBINPATH"]: |
1497 qmFile = self.getRelativePath( | 1494 qmFile = self.getRelativePath( |
1498 os.path.join(self.pdata["TRANSLATIONSBINPATH"], | 1495 os.path.join(self.pdata["TRANSLATIONSBINPATH"], |
1499 os.path.basename(qmFile))) | 1496 os.path.basename(qmFile))) |
1500 self.pdata["TRANSLATIONS"].remove(qmFile) | 1497 self.pdata["TRANSLATIONS"].remove(qmFile) |
1501 self.__model.removeItem(qmFile) | 1498 self.__model.removeItem(qmFile) |
1502 except ValueError: | |
1503 pass | |
1504 self.setDirty(True) | 1499 self.setDirty(True) |
1505 | 1500 |
1506 def deleteLanguageFile(self, langFile): | 1501 def deleteLanguageFile(self, langFile): |
1507 """ | 1502 """ |
1508 Public slot to delete a translation from the project directory. | 1503 Public slot to delete a translation from the project directory. |
1509 | 1504 |
1510 @param langFile the translation file to be removed (string) | 1505 @param langFile the translation file to be removed (string) |
1511 """ | 1506 """ |
1512 try: | 1507 try: |
1513 from ThirdParty.Send2Trash.send2trash import send2trash as s2t | 1508 from send2trash import send2trash as s2t |
1514 except ImportError: | 1509 except ImportError: |
1515 s2t = os.remove | 1510 s2t = os.remove |
1516 | 1511 |
1517 langFile = self.getRelativePath(langFile) | 1512 langFile = self.getRelativePath(langFile) |
1518 qmFile = self.__binaryTranslationFile(langFile) | 1513 qmFile = self.__binaryTranslationFile(langFile) |
1563 @param updateModel flag indicating an update of the model is | 1558 @param updateModel flag indicating an update of the model is |
1564 requested (boolean) | 1559 requested (boolean) |
1565 """ | 1560 """ |
1566 dirty = False | 1561 dirty = False |
1567 | 1562 |
1568 if os.path.isabs(fn): | 1563 # make it relative to the project root, if it starts with that path |
1569 # make it relative to the project root, if it starts with that path | 1564 # assume relative paths are relative to the project root |
1570 newfn = self.getRelativePath(fn) | 1565 newfn = self.getRelativePath(fn) if os.path.isabs(fn) else fn |
1571 else: | |
1572 # assume relative paths are relative to the project root | |
1573 newfn = fn | |
1574 newdir = os.path.dirname(newfn) | 1566 newdir = os.path.dirname(newfn) |
1575 | 1567 |
1576 if isSourceFile: | 1568 if isSourceFile: |
1577 filetype = "SOURCES" | 1569 filetype = "SOURCES" |
1578 else: | 1570 else: |
2216 dn = self.getRelativePath(dn) | 2208 dn = self.getRelativePath(dn) |
2217 for entry in self.pdata["OTHERS"][:]: | 2209 for entry in self.pdata["OTHERS"][:]: |
2218 if entry.startswith(dn): | 2210 if entry.startswith(dn): |
2219 self.pdata["OTHERS"].remove(entry) | 2211 self.pdata["OTHERS"].remove(entry) |
2220 dirty = True | 2212 dirty = True |
2221 if not dn.endswith(os.sep): | 2213 dn2 = dn if dn.endswith(os.sep) else dn + os.sep |
2222 dn2 = dn + os.sep | |
2223 else: | |
2224 dn2 = dn | |
2225 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 2214 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", |
2226 "TRANSLATIONS", ]: | 2215 "TRANSLATIONS", ]: |
2227 for entry in self.pdata[key][:]: | 2216 for entry in self.pdata[key][:]: |
2228 if entry.startswith(dn2): | 2217 if entry.startswith(dn2): |
2229 self.pdata[key].remove(entry) | 2218 self.pdata[key].remove(entry) |
2239 | 2228 |
2240 @param fn filename to be deleted from the project | 2229 @param fn filename to be deleted from the project |
2241 @return flag indicating success (boolean) | 2230 @return flag indicating success (boolean) |
2242 """ | 2231 """ |
2243 try: | 2232 try: |
2244 from ThirdParty.Send2Trash.send2trash import send2trash as s2t | 2233 from send2trash import send2trash as s2t |
2245 except ImportError: | 2234 except ImportError: |
2246 s2t = os.remove | 2235 s2t = os.remove |
2247 | 2236 |
2248 try: | 2237 try: |
2249 s2t(os.path.join(self.ppath, fn)) | 2238 s2t(os.path.join(self.ppath, fn)) |
2286 """ | 2275 """ |
2287 if not os.path.isabs(dn): | 2276 if not os.path.isabs(dn): |
2288 dn = os.path.join(self.ppath, dn) | 2277 dn = os.path.join(self.ppath, dn) |
2289 try: | 2278 try: |
2290 try: | 2279 try: |
2291 from ThirdParty.Send2Trash.send2trash import send2trash | 2280 from send2trash import send2trash |
2292 send2trash(dn) | 2281 send2trash(dn) |
2293 except ImportError: | 2282 except ImportError: |
2294 shutil.rmtree(dn, True) | 2283 shutil.rmtree(dn, True) |
2295 except OSError as err: | 2284 except OSError as err: |
2296 E5MessageBox.critical( | 2285 E5MessageBox.critical( |
2310 | 2299 |
2311 @param fn filename to be checked (string) | 2300 @param fn filename to be checked (string) |
2312 @return flag indicating, if the project contains the file (boolean) | 2301 @return flag indicating, if the project contains the file (boolean) |
2313 """ | 2302 """ |
2314 fn = self.getRelativePath(fn) | 2303 fn = self.getRelativePath(fn) |
2315 if ( | 2304 return ( |
2316 fn in self.pdata["SOURCES"] or | 2305 fn in self.pdata["SOURCES"] or |
2317 fn in self.pdata["FORMS"] or | 2306 fn in self.pdata["FORMS"] or |
2318 fn in self.pdata["INTERFACES"] or | 2307 fn in self.pdata["INTERFACES"] or |
2319 fn in self.pdata["PROTOCOLS"] or | 2308 fn in self.pdata["PROTOCOLS"] or |
2320 fn in self.pdata["RESOURCES"] or | 2309 fn in self.pdata["RESOURCES"] or |
2321 fn in self.pdata["OTHERS"] | 2310 fn in self.pdata["OTHERS"] |
2322 ): | 2311 ) |
2323 return True | |
2324 else: | |
2325 return False | |
2326 | 2312 |
2327 def createNewProject(self): | 2313 def createNewProject(self): |
2328 """ | 2314 """ |
2329 Public slot to built a new project. | 2315 Public slot to built a new project. |
2330 | 2316 |
2928 if fnmatch.fnmatch(filename, pattern): | 2914 if fnmatch.fnmatch(filename, pattern): |
2929 return language | 2915 return language |
2930 | 2916 |
2931 # try project type specific defaults next | 2917 # try project type specific defaults next |
2932 projectType = self.pdata["PROJECTTYPE"] | 2918 projectType = self.pdata["PROJECTTYPE"] |
2933 try: | 2919 with contextlib.suppress(KeyError): |
2934 if self.__lexerAssociationCallbacks[projectType] is not None: | 2920 if self.__lexerAssociationCallbacks[projectType] is not None: |
2935 return self.__lexerAssociationCallbacks[projectType](filename) | 2921 return self.__lexerAssociationCallbacks[projectType](filename) |
2936 except KeyError: | |
2937 pass | |
2938 | 2922 |
2939 # return empty string to signal to use the global setting | 2923 # return empty string to signal to use the global setting |
2940 return "" | 2924 return "" |
2941 | 2925 |
2942 @pyqtSlot() | 2926 @pyqtSlot() |
2961 Utilities.getHomeDir(), | 2945 Utilities.getHomeDir(), |
2962 self.tr("Project Files (*.epj);;XML Project Files (*.e4p)")) | 2946 self.tr("Project Files (*.epj);;XML Project Files (*.e4p)")) |
2963 | 2947 |
2964 QApplication.processEvents() | 2948 QApplication.processEvents() |
2965 | 2949 |
2966 if fn: | 2950 if fn and self.closeProject(): |
2967 if self.closeProject(): | 2951 with E5OverrideCursor(): |
2952 ok = self.__readProject(fn) | |
2953 if ok: | |
2954 self.opened = True | |
2955 if not self.pdata["FILETYPES"]: | |
2956 self.initFileTypes() | |
2957 else: | |
2958 self.updateFileTypes() | |
2959 | |
2960 try: | |
2961 # create management directory if not present | |
2962 self.createProjectManagementDir() | |
2963 except OSError: | |
2964 E5MessageBox.critical( | |
2965 self.ui, | |
2966 self.tr("Create project management directory"), | |
2967 self.tr( | |
2968 "<p>The project directory <b>{0}</b> is not" | |
2969 " writable.</p>") | |
2970 .format(self.ppath)) | |
2971 return | |
2972 | |
2973 # read a user specific project file | |
2974 self.__readUserProperties() | |
2975 | |
2968 with E5OverrideCursor(): | 2976 with E5OverrideCursor(): |
2969 ok = self.__readProject(fn) | 2977 oldState = self.isDirty() |
2970 if ok: | 2978 self.vcs = self.initVCS() |
2971 self.opened = True | 2979 if self.vcs is None and self.isDirty() == oldState: |
2972 if not self.pdata["FILETYPES"]: | 2980 # check, if project is version controlled |
2973 self.initFileTypes() | 2981 pluginManager = e5App().getObject("PluginManager") |
2974 else: | 2982 for indicator, vcsData in ( |
2975 self.updateFileTypes() | 2983 pluginManager.getVcsSystemIndicators().items() |
2976 | 2984 ): |
2977 try: | 2985 if os.path.exists( |
2978 # create management directory if not present | 2986 os.path.join(self.ppath, indicator)): |
2979 self.createProjectManagementDir() | 2987 if len(vcsData) > 1: |
2980 except OSError: | 2988 vcsList = [] |
2981 E5MessageBox.critical( | 2989 for ( |
2982 self.ui, | 2990 _vcsSystemStr, vcsSystemDisplay |
2983 self.tr("Create project management directory"), | 2991 ) in vcsData: |
2984 self.tr( | 2992 vcsList.append(vcsSystemDisplay) |
2985 "<p>The project directory <b>{0}</b> is not" | 2993 with E5OverridenCursor(): |
2986 " writable.</p>") | 2994 res, vcs_ok = QInputDialog.getItem( |
2987 .format(self.ppath)) | 2995 None, |
2988 return | 2996 self.tr("New Project"), |
2989 | 2997 self.tr( |
2990 # read a user specific project file | 2998 "Select Version Control" |
2991 self.__readUserProperties() | 2999 " System"), |
2992 | 3000 vcsList, |
2993 with E5OverrideCursor(): | 3001 0, False) |
2994 oldState = self.isDirty() | 3002 if vcs_ok: |
2995 self.vcs = self.initVCS() | |
2996 if self.vcs is None and self.isDirty() == oldState: | |
2997 # check, if project is version controlled | |
2998 pluginManager = e5App().getObject("PluginManager") | |
2999 for indicator, vcsData in ( | |
3000 pluginManager.getVcsSystemIndicators().items() | |
3001 ): | |
3002 if os.path.exists( | |
3003 os.path.join(self.ppath, indicator)): | |
3004 if len(vcsData) > 1: | |
3005 vcsList = [] | |
3006 for ( | 3003 for ( |
3007 _vcsSystemStr, vcsSystemDisplay | 3004 vcsSystemStr, vcsSystemDisplay |
3008 ) in vcsData: | 3005 ) in vcsData: |
3009 vcsList.append(vcsSystemDisplay) | 3006 if res == vcsSystemDisplay: |
3010 with E5OverridenCursor(): | 3007 vcsSystem = vcsSystemStr |
3011 res, vcs_ok = QInputDialog.getItem( | 3008 break |
3012 None, | |
3013 self.tr("New Project"), | |
3014 self.tr( | |
3015 "Select Version Control" | |
3016 " System"), | |
3017 vcsList, | |
3018 0, False) | |
3019 if vcs_ok: | |
3020 for ( | |
3021 vcsSystemStr, vcsSystemDisplay | |
3022 ) in vcsData: | |
3023 if res == vcsSystemDisplay: | |
3024 vcsSystem = vcsSystemStr | |
3025 break | |
3026 else: | |
3027 vcsSystem = "None" | |
3028 else: | 3009 else: |
3029 vcsSystem = "None" | 3010 vcsSystem = "None" |
3030 else: | 3011 else: |
3031 vcsSystem = vcsData[0][0] | 3012 vcsSystem = "None" |
3032 self.pdata["VCS"] = vcsSystem | 3013 else: |
3033 self.vcs = self.initVCS() | 3014 vcsSystem = vcsData[0][0] |
3034 self.setDirty(True) | 3015 self.pdata["VCS"] = vcsSystem |
3035 if ( | 3016 self.vcs = self.initVCS() |
3036 self.vcs is not None and | 3017 self.setDirty(True) |
3037 (self.vcs.vcsRegisteredState(self.ppath) != | 3018 if ( |
3038 self.vcs.canBeCommitted) | 3019 self.vcs is not None and |
3039 ): | 3020 (self.vcs.vcsRegisteredState(self.ppath) != |
3040 self.pdata["VCS"] = 'None' | 3021 self.vcs.canBeCommitted) |
3041 self.vcs = self.initVCS() | 3022 ): |
3042 self.closeAct.setEnabled(True) | 3023 self.pdata["VCS"] = 'None' |
3043 self.saveasAct.setEnabled(True) | 3024 self.vcs = self.initVCS() |
3044 self.actGrp2.setEnabled(True) | 3025 self.closeAct.setEnabled(True) |
3045 self.propsAct.setEnabled(True) | 3026 self.saveasAct.setEnabled(True) |
3046 self.userPropsAct.setEnabled(True) | 3027 self.actGrp2.setEnabled(True) |
3047 self.filetypesAct.setEnabled(True) | 3028 self.propsAct.setEnabled(True) |
3048 self.lexersAct.setEnabled(True) | 3029 self.userPropsAct.setEnabled(True) |
3049 self.sessActGrp.setEnabled(True) | 3030 self.filetypesAct.setEnabled(True) |
3050 self.dbgActGrp.setEnabled(True) | 3031 self.lexersAct.setEnabled(True) |
3051 self.menuDebuggerAct.setEnabled(True) | 3032 self.sessActGrp.setEnabled(True) |
3052 self.menuSessionAct.setEnabled(True) | 3033 self.dbgActGrp.setEnabled(True) |
3053 self.menuCheckAct.setEnabled(True) | 3034 self.menuDebuggerAct.setEnabled(True) |
3054 self.menuShowAct.setEnabled(True) | 3035 self.menuSessionAct.setEnabled(True) |
3055 self.menuDiagramAct.setEnabled(True) | 3036 self.menuCheckAct.setEnabled(True) |
3056 self.menuApidocAct.setEnabled(True) | 3037 self.menuShowAct.setEnabled(True) |
3057 self.menuPackagersAct.setEnabled(True) | 3038 self.menuDiagramAct.setEnabled(True) |
3058 self.pluginGrp.setEnabled( | 3039 self.menuApidocAct.setEnabled(True) |
3059 self.pdata["PROJECTTYPE"] in ["E6Plugin"]) | 3040 self.menuPackagersAct.setEnabled(True) |
3060 self.addLanguageAct.setEnabled( | 3041 self.pluginGrp.setEnabled( |
3061 bool(self.pdata["TRANSLATIONPATTERN"])) | 3042 self.pdata["PROJECTTYPE"] in ["E6Plugin"]) |
3062 self.makeGrp.setEnabled( | 3043 self.addLanguageAct.setEnabled( |
3063 self.pdata["MAKEPARAMS"]["MakeEnabled"]) | 3044 bool(self.pdata["TRANSLATIONPATTERN"])) |
3064 self.menuMakeAct.setEnabled( | 3045 self.makeGrp.setEnabled( |
3065 self.pdata["MAKEPARAMS"]["MakeEnabled"]) | 3046 self.pdata["MAKEPARAMS"]["MakeEnabled"]) |
3066 | 3047 self.menuMakeAct.setEnabled( |
3067 # open a project debugger properties file being quiet | 3048 self.pdata["MAKEPARAMS"]["MakeEnabled"]) |
3068 # about errors | |
3069 if Preferences.getProject("AutoLoadDbgProperties"): | |
3070 self.__readDebugProperties(True) | |
3071 | |
3072 self.__model.projectOpened() | |
3073 self.projectOpenedHooks.emit() | |
3074 self.projectOpened.emit() | |
3075 | 3049 |
3076 if Preferences.getProject("SearchNewFiles"): | 3050 # open a project debugger properties file being quiet |
3077 self.__doSearchNewFiles() | 3051 # about errors |
3052 if Preferences.getProject("AutoLoadDbgProperties"): | |
3053 self.__readDebugProperties(True) | |
3078 | 3054 |
3079 # read a project tasks file | 3055 self.__model.projectOpened() |
3080 self.__readTasks() | 3056 self.projectOpenedHooks.emit() |
3081 self.ui.taskViewer.setProjectOpen(True) | 3057 self.projectOpened.emit() |
3082 # rescan project tasks | 3058 |
3083 if Preferences.getProject("TasksProjectRescanOnOpen"): | 3059 if Preferences.getProject("SearchNewFiles"): |
3084 e5App().getObject("TaskViewer" | 3060 self.__doSearchNewFiles() |
3085 ).regenerateProjectTasks(quiet=True) | 3061 |
3062 # read a project tasks file | |
3063 self.__readTasks() | |
3064 self.ui.taskViewer.setProjectOpen(True) | |
3065 # rescan project tasks | |
3066 if Preferences.getProject("TasksProjectRescanOnOpen"): | |
3067 e5App().getObject("TaskViewer" | |
3068 ).regenerateProjectTasks(quiet=True) | |
3069 | |
3070 if restoreSession: | |
3071 # open the main script | |
3072 if self.pdata["MAINSCRIPT"]: | |
3073 if not os.path.isabs(self.pdata["MAINSCRIPT"]): | |
3074 ms = os.path.join( | |
3075 self.ppath, self.pdata["MAINSCRIPT"]) | |
3076 else: | |
3077 ms = self.pdata["MAINSCRIPT"] | |
3078 self.sourceFile.emit(ms) | |
3086 | 3079 |
3087 if restoreSession: | 3080 # open a project session file being quiet about errors |
3088 # open the main script | 3081 if reopen: |
3089 if self.pdata["MAINSCRIPT"]: | 3082 self.__readSession(quiet=True, indicator="_tmp") |
3090 if not os.path.isabs(self.pdata["MAINSCRIPT"]): | 3083 elif Preferences.getProject("AutoLoadSession"): |
3091 ms = os.path.join( | 3084 self.__readSession(quiet=True) |
3092 self.ppath, self.pdata["MAINSCRIPT"]) | 3085 |
3093 else: | 3086 # start the VCS monitor thread |
3094 ms = self.pdata["MAINSCRIPT"] | 3087 if self.vcs is not None: |
3095 self.sourceFile.emit(ms) | 3088 self.vcs.startStatusMonitor(self) |
3096 | 3089 self.vcs.vcsStatusMonitorData.connect( |
3097 # open a project session file being quiet about errors | 3090 self.__model.changeVCSStates) |
3098 if reopen: | 3091 self.vcs.vcsStatusMonitorStatus.connect( |
3099 self.__readSession(quiet=True, indicator="_tmp") | 3092 self.__statusMonitorStatus) |
3100 elif Preferences.getProject("AutoLoadSession"): | 3093 self.vcs.vcsStatusMonitorInfo.connect( |
3101 self.__readSession(quiet=True) | 3094 self.vcsStatusMonitorInfo) |
3102 | 3095 self.vcs.vcsStatusChanged.connect( |
3103 # start the VCS monitor thread | 3096 self.__vcsStatusChanged) |
3104 if self.vcs is not None: | |
3105 self.vcs.startStatusMonitor(self) | |
3106 self.vcs.vcsStatusMonitorData.connect( | |
3107 self.__model.changeVCSStates) | |
3108 self.vcs.vcsStatusMonitorStatus.connect( | |
3109 self.__statusMonitorStatus) | |
3110 self.vcs.vcsStatusMonitorInfo.connect( | |
3111 self.vcsStatusMonitorInfo) | |
3112 self.vcs.vcsStatusChanged.connect( | |
3113 self.__vcsStatusChanged) | |
3114 | 3097 |
3115 def reopenProject(self): | 3098 def reopenProject(self): |
3116 """ | 3099 """ |
3117 Public slot to reopen the current project. | 3100 Public slot to reopen the current project. |
3118 """ | 3101 """ |
3146 Public slot to save the current project to a different file. | 3129 Public slot to save the current project to a different file. |
3147 | 3130 |
3148 @return flag indicating success (boolean) | 3131 @return flag indicating success (boolean) |
3149 """ | 3132 """ |
3150 defaultFilter = self.tr("Project Files (*.epj)") | 3133 defaultFilter = self.tr("Project Files (*.epj)") |
3151 if self.ppath: | 3134 defaultPath = ( |
3152 defaultPath = self.ppath | 3135 self.ppath |
3153 else: | 3136 if self.ppath else |
3154 defaultPath = ( | 3137 (Preferences.getMultiProject("Workspace") or |
3155 Preferences.getMultiProject("Workspace") or | 3138 Utilities.getHomeDir()) |
3156 Utilities.getHomeDir() | 3139 ) |
3157 ) | |
3158 fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( | 3140 fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( |
3159 self.parent(), | 3141 self.parent(), |
3160 self.tr("Save project as"), | 3142 self.tr("Save project as"), |
3161 defaultPath, | 3143 defaultPath, |
3162 self.tr("Project Files (*.epj);;" | 3144 self.tr("Project Files (*.epj);;" |
3542 programming language. | 3524 programming language. |
3543 | 3525 |
3544 @return default extension (including the dot) (string) | 3526 @return default extension (including the dot) (string) |
3545 """ | 3527 """ |
3546 lang = self.pdata["PROGLANGUAGE"] | 3528 lang = self.pdata["PROGLANGUAGE"] |
3547 if lang == "": | 3529 if lang in ("", "Python"): |
3548 lang = "Python3" | |
3549 elif lang == "Python": | |
3550 lang = "Python3" | 3530 lang = "Python3" |
3551 return self.__sourceExtensions(lang)[0] | 3531 return self.__sourceExtensions(lang)[0] |
3552 | 3532 |
3553 def getProjectPath(self): | 3533 def getProjectPath(self): |
3554 """ | 3534 """ |
3560 | 3540 |
3561 def startswithProjectPath(self, path): | 3541 def startswithProjectPath(self, path): |
3562 """ | 3542 """ |
3563 Public method to check, if a path starts with the project path. | 3543 Public method to check, if a path starts with the project path. |
3564 | 3544 |
3565 @param path path to be checked (string) | 3545 @param path path to be checked |
3546 @type str | |
3566 @return flag indicating that the path starts with the project path | 3547 @return flag indicating that the path starts with the project path |
3567 (boolean) | 3548 @rtype bool |
3568 """ | 3549 """ |
3569 if self.ppath: | 3550 return ( |
3570 if path == self.ppath: | 3551 bool(self.ppath) and |
3571 return True | 3552 (path == self.ppath or |
3572 elif ( | 3553 Utilities.normcasepath(Utilities.toNativeSeparators(path)) |
3573 Utilities.normcasepath(Utilities.toNativeSeparators(path)) | 3554 .startswith(Utilities.normcasepath( |
3574 .startswith(Utilities.normcasepath( | 3555 Utilities.toNativeSeparators(self.ppath + "/"))) |
3575 Utilities.toNativeSeparators(self.ppath + "/"))) | 3556 ) |
3576 ): | 3557 ) |
3577 return True | 3558 |
3578 else: | |
3579 return False | |
3580 else: | |
3581 return False | |
3582 | |
3583 def getProjectFile(self): | 3559 def getProjectFile(self): |
3584 """ | 3560 """ |
3585 Public method to get the path of the project file. | 3561 Public method to get the path of the project file. |
3586 | 3562 |
3587 @return path of the project file (string) | 3563 @return path of the project file (string) |
3767 @return flag indicating membership | 3743 @return flag indicating membership |
3768 @rtype bool | 3744 @rtype bool |
3769 """ | 3745 """ |
3770 newfn = os.path.abspath(fn) | 3746 newfn = os.path.abspath(fn) |
3771 newfn = self.getRelativePath(newfn) | 3747 newfn = self.getRelativePath(newfn) |
3772 for group in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", | 3748 return any( |
3773 "RESOURCES", "TRANSLATIONS", "OTHERS"]: | 3749 newfn in self.pdata[group] |
3774 if newfn in self.pdata[group]: | 3750 for group in [ |
3775 return True | 3751 "SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", |
3776 return False | 3752 "TRANSLATIONS", "OTHERS" |
3753 ] | |
3754 ) | |
3777 | 3755 |
3778 def isProjectFile(self, fn): | 3756 def isProjectFile(self, fn): |
3779 """ | 3757 """ |
3780 Public method used to check, if the passed in filename belongs to the | 3758 Public method used to check, if the passed in filename belongs to the |
3781 project. | 3759 project. |
3782 | 3760 |
3783 @param fn filename to be checked (string) | 3761 @param fn filename to be checked (string) |
3784 @return flag indicating membership (boolean) | 3762 @return flag indicating membership (boolean) |
3785 """ | 3763 """ |
3786 for group in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", | 3764 return any( |
3787 "RESOURCES", "TRANSLATIONS", "OTHERS"]: | 3765 self.__checkProjectFileGroup(fn, group) |
3788 if self.__checkProjectFileGroup(fn, group): | 3766 for group in [ |
3789 return True | 3767 "SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", |
3790 | 3768 "TRANSLATIONS", "OTHERS" |
3791 return False | 3769 ] |
3770 ) | |
3792 | 3771 |
3793 def __checkProjectFileGroup(self, fn, group): | 3772 def __checkProjectFileGroup(self, fn, group): |
3794 """ | 3773 """ |
3795 Private method to check, if a file is in a specific file group of the | 3774 Private method to check, if a file is in a specific file group of the |
3796 project. | 3775 project. |
3799 @param group group to check (string) | 3778 @param group group to check (string) |
3800 @return flag indicating membership (boolean) | 3779 @return flag indicating membership (boolean) |
3801 """ | 3780 """ |
3802 newfn = os.path.abspath(fn) | 3781 newfn = os.path.abspath(fn) |
3803 newfn = self.getRelativePath(newfn) | 3782 newfn = self.getRelativePath(newfn) |
3804 if newfn in self.pdata[group]: | 3783 if ( |
3784 newfn in self.pdata[group] or | |
3785 (group == "OTHERS" and | |
3786 any(newfn.startswith(entry) for entry in self.pdata[group])) | |
3787 ): | |
3805 return True | 3788 return True |
3806 elif group == "OTHERS": | |
3807 for entry in self.pdata[group]: | |
3808 if newfn.startswith(entry): | |
3809 return True | |
3810 | 3789 |
3811 if Utilities.isWindowsPlatform(): | 3790 if Utilities.isWindowsPlatform(): |
3812 # try the above case-insensitive | 3791 # try the above case-insensitive |
3813 newfn = newfn.lower() | 3792 newfn = newfn.lower() |
3814 for entry in self.pdata[group]: | 3793 if any(entry.lower() == newfn for entry in self.pdata[group]): |
3815 if entry.lower() == newfn: | 3794 return True |
3816 return True | 3795 elif ( |
3817 elif group == "OTHERS": | 3796 group == "OTHERS" and |
3818 for entry in self.pdata[group]: | 3797 any(newfn.startswith(entry.lower()) |
3819 if newfn.startswith(entry.lower()): | 3798 for entry in self.pdata[group]) |
3820 return True | 3799 ): |
3800 return True | |
3821 | 3801 |
3822 return False | 3802 return False |
3823 | 3803 |
3824 def isProjectSource(self, fn): | 3804 def isProjectSource(self, fn): |
3825 """ | 3805 """ |
4564 """ | 4544 """ |
4565 self.__loadRecent() | 4545 self.__loadRecent() |
4566 | 4546 |
4567 self.recentMenu.clear() | 4547 self.recentMenu.clear() |
4568 | 4548 |
4569 idx = 1 | 4549 for idx, rp in enumerate(self.recent, start=1): |
4570 for rp in self.recent: | 4550 formatStr = '&{0:d}. {1}' if idx < 10 else '{0:d}. {1}' |
4571 if idx < 10: | |
4572 formatStr = '&{0:d}. {1}' | |
4573 else: | |
4574 formatStr = '{0:d}. {1}' | |
4575 act = self.recentMenu.addAction( | 4551 act = self.recentMenu.addAction( |
4576 formatStr.format( | 4552 formatStr.format( |
4577 idx, | 4553 idx, |
4578 Utilities.compactPath(rp, self.ui.maxMenuFilePathLen))) | 4554 Utilities.compactPath(rp, self.ui.maxMenuFilePathLen))) |
4579 act.setData(rp) | 4555 act.setData(rp) |
4580 act.setEnabled(QFileInfo(rp).exists()) | 4556 act.setEnabled(QFileInfo(rp).exists()) |
4581 idx += 1 | |
4582 | 4557 |
4583 self.recentMenu.addSeparator() | 4558 self.recentMenu.addSeparator() |
4584 self.recentMenu.addAction(self.tr('&Clear'), self.clearRecent) | 4559 self.recentMenu.addAction(self.tr('&Clear'), self.clearRecent) |
4585 | 4560 |
4586 def __openRecent(self, act): | 4561 def __openRecent(self, act): |
4669 curpath = os.path.join(self.ppath, directory) | 4644 curpath = os.path.join(self.ppath, directory) |
4670 try: | 4645 try: |
4671 newSources = os.listdir(curpath) | 4646 newSources = os.listdir(curpath) |
4672 except OSError: | 4647 except OSError: |
4673 newSources = [] | 4648 newSources = [] |
4674 if self.pdata["TRANSLATIONPATTERN"]: | 4649 pattern = ( |
4675 pattern = ( | 4650 self.pdata["TRANSLATIONPATTERN"].replace("%language%", "*") |
4676 self.pdata["TRANSLATIONPATTERN"] | 4651 if self.pdata["TRANSLATIONPATTERN"] else |
4677 .replace("%language%", "*") | 4652 "*.ts" |
4678 ) | 4653 ) |
4679 else: | |
4680 pattern = "*.ts" | |
4681 binpattern = self.__binaryTranslationFile(pattern) | 4654 binpattern = self.__binaryTranslationFile(pattern) |
4682 for ns in newSources: | 4655 for ns in newSources: |
4683 # ignore hidden files and directories | 4656 # ignore hidden files and directories |
4684 if ns.startswith('.'): | 4657 if ns.startswith('.'): |
4685 continue | 4658 continue |
4692 continue | 4665 continue |
4693 | 4666 |
4694 # set fn to project relative name | 4667 # set fn to project relative name |
4695 # then reset ns to fully qualified name for insertion, | 4668 # then reset ns to fully qualified name for insertion, |
4696 # possibly. | 4669 # possibly. |
4697 if directory == "": | 4670 fn = os.path.join(directory, ns) if directory else ns |
4698 fn = ns | |
4699 else: | |
4700 fn = os.path.join(directory, ns) | |
4701 ns = os.path.abspath(os.path.join(curpath, ns)) | 4671 ns = os.path.abspath(os.path.join(curpath, ns)) |
4702 | 4672 |
4703 # do not bother with dirs here... | 4673 # do not bother with dirs here... |
4704 if os.path.isdir(ns): | 4674 if os.path.isdir(ns): |
4705 if recursiveSearch: | 4675 if recursiveSearch: |
4726 (filetype == "PROTOCOLS" and | 4696 (filetype == "PROTOCOLS" and |
4727 fn not in self.pdata["PROTOCOLS"]) or | 4697 fn not in self.pdata["PROTOCOLS"]) or |
4728 (filetype == "RESOURCES" and | 4698 (filetype == "RESOURCES" and |
4729 fn not in self.pdata["RESOURCES"]) or | 4699 fn not in self.pdata["RESOURCES"]) or |
4730 (filetype == "OTHERS" and | 4700 (filetype == "OTHERS" and |
4731 fn not in self.pdata["OTHERS"]) | 4701 fn not in self.pdata["OTHERS"]) or |
4702 (filetype == "TRANSLATIONS" and | |
4703 fn not in self.pdata["TRANSLATIONS"] and | |
4704 (fnmatch.fnmatch(ns, pattern) or | |
4705 fnmatch.fnmatch(ns, binpattern))) | |
4732 ): | 4706 ): |
4733 if autoInclude and AI: | 4707 if autoInclude and AI: |
4734 self.appendFile(ns) | 4708 self.appendFile(ns) |
4735 else: | 4709 else: |
4736 newFiles.append(ns) | 4710 newFiles.append(ns) |
4737 elif ( | |
4738 filetype == "TRANSLATIONS" and | |
4739 fn not in self.pdata["TRANSLATIONS"] | |
4740 ): | |
4741 if ( | |
4742 fnmatch.fnmatch(ns, pattern) or | |
4743 fnmatch.fnmatch(ns, binpattern) | |
4744 ): | |
4745 if autoInclude and AI: | |
4746 self.appendFile(ns) | |
4747 else: | |
4748 newFiles.append(ns) | |
4749 | 4711 |
4750 # if autoInclude is set there is no more work left | 4712 # if autoInclude is set there is no more work left |
4751 if (autoInclude and AI): | 4713 if (autoInclude and AI): |
4752 return | 4714 return |
4753 | 4715 |
4809 Public method to remove actions from the list of actions. | 4771 Public method to remove actions from the list of actions. |
4810 | 4772 |
4811 @param actions list of actions (list of E5Action) | 4773 @param actions list of actions (list of E5Action) |
4812 """ | 4774 """ |
4813 for act in actions: | 4775 for act in actions: |
4814 try: | 4776 with contextlib.suppress(ValueError): |
4815 self.actions.remove(act) | 4777 self.actions.remove(act) |
4816 except ValueError: | |
4817 pass | |
4818 | 4778 |
4819 def getMenu(self, menuName): | 4779 def getMenu(self, menuName): |
4820 """ | 4780 """ |
4821 Public method to get a reference to the main menu or a submenu. | 4781 Public method to get a reference to the main menu or a submenu. |
4822 | 4782 |
4864 if self.pdata["VCS"] and self.pdata["VCS"] != 'None': | 4824 if self.pdata["VCS"] and self.pdata["VCS"] != 'None': |
4865 vcsSystem = self.pdata["VCS"] | 4825 vcsSystem = self.pdata["VCS"] |
4866 else: | 4826 else: |
4867 forProject = False | 4827 forProject = False |
4868 | 4828 |
4869 if forProject and self.pdata["VCS"] and self.pdata["VCS"] != 'None': | 4829 if ( |
4870 if ( | 4830 forProject and |
4871 self.pudata["VCSOVERRIDE"] and | 4831 self.pdata["VCS"] and |
4872 not nooverride | 4832 self.pdata["VCS"] != 'None' and |
4873 ): | 4833 self.pudata["VCSOVERRIDE"] and |
4874 vcsSystem = self.pudata["VCSOVERRIDE"] | 4834 not nooverride |
4875 override = True | 4835 ): |
4836 vcsSystem = self.pudata["VCSOVERRIDE"] | |
4837 override = True | |
4876 | 4838 |
4877 if vcsSystem is not None: | 4839 if vcsSystem is not None: |
4878 import VCS | 4840 import VCS |
4879 try: | 4841 try: |
4880 vcs = VCS.factory(vcsSystem) | 4842 vcs = VCS.factory(vcsSystem) |
4917 vcs.vcsInitConfig(self) | 4879 vcs.vcsInitConfig(self) |
4918 | 4880 |
4919 if vcs and forProject: | 4881 if vcs and forProject: |
4920 # set the vcs options | 4882 # set the vcs options |
4921 if vcs.vcsSupportCommandOptions(): | 4883 if vcs.vcsSupportCommandOptions(): |
4922 try: | 4884 with contextlib.suppress(LookupError): |
4923 vcsopt = copy.deepcopy(self.pdata["VCSOPTIONS"]) | 4885 vcsopt = copy.deepcopy(self.pdata["VCSOPTIONS"]) |
4924 vcs.vcsSetOptions(vcsopt) | 4886 vcs.vcsSetOptions(vcsopt) |
4925 except LookupError: | |
4926 pass | |
4927 # set vcs specific data | 4887 # set vcs specific data |
4928 try: | 4888 with contextlib.suppress(LookupError): |
4929 vcsother = copy.deepcopy(self.pdata["VCSOTHERDATA"]) | 4889 vcsother = copy.deepcopy(self.pdata["VCSOTHERDATA"]) |
4930 vcs.vcsSetOtherData(vcsother) | 4890 vcs.vcsSetOtherData(vcsother) |
4931 except LookupError: | |
4932 pass | |
4933 | 4891 |
4934 if forProject: | 4892 if forProject: |
4935 if vcs is None: | 4893 if vcs is None: |
4936 import VCS | 4894 import VCS |
4937 self.vcsProjectHelper = VCS.getBasicHelper(self) | 4895 self.vcsProjectHelper = VCS.getBasicHelper(self) |
5339 " ", | 5297 " ", |
5340 ] | 5298 ] |
5341 | 5299 |
5342 # write the file | 5300 # write the file |
5343 try: | 5301 try: |
5344 if self.pdata["EOL"] == 0: | 5302 newline = None if self.pdata["EOL"] == 0 else self.getEolString() |
5345 newline = None | |
5346 else: | |
5347 newline = self.getEolString() | |
5348 with open(pkglist, "w", encoding="utf-8", | 5303 with open(pkglist, "w", encoding="utf-8", |
5349 newline=newline) as pkglistFile: | 5304 newline=newline) as pkglistFile: |
5350 pkglistFile.write("\n".join(header) + "\n") | 5305 pkglistFile.write("\n".join(header) + "\n") |
5351 pkglistFile.write( | 5306 pkglistFile.write( |
5352 "\n".join([Utilities.fromNativeSeparators(f) | 5307 "\n".join([Utilities.fromNativeSeparators(f) |
5408 progress = E5ProgressDialog( | 5363 progress = E5ProgressDialog( |
5409 self.tr("Creating plugin archives..."), self.tr("Abort"), | 5364 self.tr("Creating plugin archives..."), self.tr("Abort"), |
5410 0, len(selectedLists), self.tr("%v/%m Archives")) | 5365 0, len(selectedLists), self.tr("%v/%m Archives")) |
5411 progress.setMinimumDuration(0) | 5366 progress.setMinimumDuration(0) |
5412 progress.setWindowTitle(self.tr("Create Plugin Archives")) | 5367 progress.setWindowTitle(self.tr("Create Plugin Archives")) |
5413 count = 0 | |
5414 errors = 0 | 5368 errors = 0 |
5415 for pkglist in selectedLists: | 5369 for count, pkglist in enumerate(selectedLists): |
5416 progress.setValue(count) | 5370 progress.setValue(count) |
5417 if progress.wasCanceled(): | 5371 if progress.wasCanceled(): |
5418 break | 5372 break |
5419 | 5373 |
5420 try: | 5374 try: |
5427 self.tr( | 5381 self.tr( |
5428 """<p>The file <b>{0}</b> could not be read.</p>""" | 5382 """<p>The file <b>{0}</b> could not be read.</p>""" |
5429 """<p>Reason: {1}</p>""").format( | 5383 """<p>Reason: {1}</p>""").format( |
5430 os.path.basename(pkglist), str(why))) | 5384 os.path.basename(pkglist), str(why))) |
5431 errors += 1 | 5385 errors += 1 |
5432 count += 1 | |
5433 continue | 5386 continue |
5434 | 5387 |
5435 lines = names.splitlines() | 5388 lines = names.splitlines() |
5436 archiveName = "" | 5389 archiveName = "" |
5437 archiveVersion = "" | 5390 archiveVersion = "" |
5456 """<p>The file <b>{0}</b> is not ready yet.""" | 5409 """<p>The file <b>{0}</b> is not ready yet.""" |
5457 """</p><p>Please rework it and delete the""" | 5410 """</p><p>Please rework it and delete the""" |
5458 """'; initial_list' line of the header.""" | 5411 """'; initial_list' line of the header.""" |
5459 """</p>""").format(os.path.basename(pkglist))) | 5412 """</p>""").format(os.path.basename(pkglist))) |
5460 errors += 1 | 5413 errors += 1 |
5461 count += 1 | |
5462 listOK = False | 5414 listOK = False |
5463 break | 5415 break |
5464 elif line.strip(): | 5416 elif line.strip(): |
5465 names.append(line.strip()) | 5417 names.append(line.strip()) |
5466 | 5418 |
5467 if not listOK: | 5419 if not listOK: |
5468 continue | 5420 continue |
5469 | 5421 |
5470 names = sorted(names) | 5422 names = sorted(names) |
5471 if archiveName: | 5423 archive = ( |
5472 archive = os.path.join(self.ppath, archiveName) | 5424 os.path.join(self.ppath, archiveName) |
5473 else: | 5425 if archiveName else |
5474 archive = os.path.join( | 5426 os.path.join(self.ppath, |
5475 self.ppath, | 5427 self.pdata["MAINSCRIPT"].replace(".py", ".zip")) |
5476 self.pdata["MAINSCRIPT"].replace(".py", ".zip")) | 5428 ) |
5477 try: | 5429 try: |
5478 archiveFile = zipfile.ZipFile(archive, "w") | 5430 archiveFile = zipfile.ZipFile(archive, "w") |
5479 except OSError as why: | 5431 except OSError as why: |
5480 E5MessageBox.critical( | 5432 E5MessageBox.critical( |
5481 self.ui, | 5433 self.ui, |
5483 self.tr( | 5435 self.tr( |
5484 """<p>The eric plugin archive file <b>{0}</b>""" | 5436 """<p>The eric plugin archive file <b>{0}</b>""" |
5485 """ could not be created.</p>""" | 5437 """ could not be created.</p>""" |
5486 """<p>Reason: {1}</p>""").format(archive, str(why))) | 5438 """<p>Reason: {1}</p>""").format(archive, str(why))) |
5487 errors += 1 | 5439 errors += 1 |
5488 count += 1 | |
5489 continue | 5440 continue |
5490 | 5441 |
5491 for name in names: | 5442 for name in names: |
5492 if name: | 5443 if name: |
5493 try: | 5444 try: |
5524 archiveFile.writestr("VERSION", version.encode("utf-8")) | 5475 archiveFile.writestr("VERSION", version.encode("utf-8")) |
5525 archiveFile.close() | 5476 archiveFile.close() |
5526 | 5477 |
5527 if archive not in self.pdata["OTHERS"]: | 5478 if archive not in self.pdata["OTHERS"]: |
5528 self.appendFile(archive) | 5479 self.appendFile(archive) |
5529 | |
5530 count += 1 | |
5531 | 5480 |
5532 progress.setValue(len(selectedLists)) | 5481 progress.setValue(len(selectedLists)) |
5533 | 5482 |
5534 if errors: | 5483 if errors: |
5535 self.ui.showNotification( | 5484 self.ui.showNotification( |
5536 UI.PixmapCache.getPixmap("pluginArchive48"), | 5485 UI.PixmapCache.getPixmap("pluginArchive48"), |
5537 self.tr("Create Plugin Archive"), | 5486 self.tr("Create Plugin Archive"), |
5538 self.tr("<p>The eric plugin archive files were " | 5487 self.tr("<p>The eric plugin archive files were " |
5539 "created with some errors.</p>"), | 5488 "created with some errors.</p>"), |
5540 kind=NotificationTypes.Critical, | 5489 kind=NotificationTypes.CRITICAL, |
5541 timeout=0) | 5490 timeout=0) |
5542 else: | 5491 else: |
5543 self.ui.showNotification( | 5492 self.ui.showNotification( |
5544 UI.PixmapCache.getPixmap("pluginArchive48"), | 5493 UI.PixmapCache.getPixmap("pluginArchive48"), |
5545 self.tr("Create Plugin Archive"), | 5494 self.tr("Create Plugin Archive"), |
5557 Private method to create dir entries in the zip file. | 5506 Private method to create dir entries in the zip file. |
5558 | 5507 |
5559 @param path name of the directory entry to create (string) | 5508 @param path name of the directory entry to create (string) |
5560 @param zipFile open ZipFile object (zipfile.ZipFile) | 5509 @param zipFile open ZipFile object (zipfile.ZipFile) |
5561 """ | 5510 """ |
5562 if path == "" or path == "/" or path == "\\": | 5511 if path in ("", "/", "\\"): |
5563 return | 5512 return |
5564 | 5513 |
5565 if not path.endswith("/") and not path.endswith("\\"): | 5514 if not path.endswith("/") and not path.endswith("\\"): |
5566 path = "{0}/".format(path) | 5515 path = "{0}/".format(path) |
5567 | 5516 |
5705 not self.pdata["MAKEPARAMS"]["MakeEnabled"] or | 5654 not self.pdata["MAKEPARAMS"]["MakeEnabled"] or |
5706 self.__makeProcess is not None | 5655 self.__makeProcess is not None |
5707 ): | 5656 ): |
5708 return | 5657 return |
5709 | 5658 |
5710 if self.pdata["MAKEPARAMS"]["MakeExecutable"]: | 5659 prog = ( |
5711 prog = self.pdata["MAKEPARAMS"]["MakeExecutable"] | 5660 self.pdata["MAKEPARAMS"]["MakeExecutable"] |
5712 else: | 5661 if self.pdata["MAKEPARAMS"]["MakeExecutable"] else |
5713 prog = Project.DefaultMake | 5662 Project.DefaultMake |
5663 ) | |
5714 | 5664 |
5715 args = [] | 5665 args = [] |
5716 if self.pdata["MAKEPARAMS"]["MakeParameters"]: | 5666 if self.pdata["MAKEPARAMS"]["MakeParameters"]: |
5717 args.extend(Utilities.parseOptionString( | 5667 args.extend(Utilities.parseOptionString( |
5718 self.pdata["MAKEPARAMS"]["MakeParameters"])) | 5668 self.pdata["MAKEPARAMS"]["MakeParameters"])) |
5805 | 5755 |
5806 self.ui.showNotification( | 5756 self.ui.showNotification( |
5807 UI.PixmapCache.getPixmap("makefile48"), | 5757 UI.PixmapCache.getPixmap("makefile48"), |
5808 title, | 5758 title, |
5809 message, | 5759 message, |
5810 kind=NotificationTypes.Warning, | 5760 kind=NotificationTypes.WARNING, |
5811 timeout=0) | 5761 timeout=0) |
5812 elif exitCode > 1: | 5762 elif exitCode > 1: |
5813 E5MessageBox.critical( | 5763 E5MessageBox.critical( |
5814 self.ui, | 5764 self.ui, |
5815 self.tr("Execute Make"), | 5765 self.tr("Execute Make"), |