--- a/src/eric7/Project/ProjectFormsBrowser.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Project/ProjectFormsBrowser.py Wed Jul 13 14:55:47 2022 +0200 @@ -21,8 +21,10 @@ from EricWidgets.EricProgressDialog import EricProgressDialog from .ProjectBrowserModel import ( - ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem, - ProjectBrowserDirectoryItem, ProjectBrowserFormType + ProjectBrowserFileItem, + ProjectBrowserSimpleDirectoryItem, + ProjectBrowserDirectoryItem, + ProjectBrowserFormType, ) from .ProjectBaseBrowser import ProjectBaseBrowser @@ -39,7 +41,7 @@ class ProjectFormsBrowser(ProjectBaseBrowser): """ A class used to display the forms part of the project. - + @signal appendStderr(str) emitted after something was received from a QProcess on stderr @signal uipreview(str) emitted to preview a forms file @@ -48,46 +50,62 @@ @signal menusAboutToBeCreated() emitted when the context menus are about to be created. This is the right moment to add or remove hook methods. """ + appendStderr = pyqtSignal(str) uipreview = pyqtSignal(str) showMenu = pyqtSignal(str, QMenu) menusAboutToBeCreated = pyqtSignal() - + Pyuic5IndentDefault = 4 Pyuic6IndentDefault = 4 - + def __init__(self, project, parent=None): """ Constructor - + @param project reference to the project object @param parent parent widget of this browser (QWidget) """ - ProjectBaseBrowser.__init__(self, project, ProjectBrowserFormType, - parent) - - self.selectedItemsFilter = [ProjectBrowserFileItem, - ProjectBrowserSimpleDirectoryItem] - - self.setWindowTitle(self.tr('Forms')) + ProjectBaseBrowser.__init__(self, project, ProjectBrowserFormType, parent) + + self.selectedItemsFilter = [ + ProjectBrowserFileItem, + ProjectBrowserSimpleDirectoryItem, + ] + + self.setWindowTitle(self.tr("Forms")) - self.setWhatsThis(self.tr( - """<b>Project Forms Browser</b>""" - """<p>This allows to easily see all forms contained in the""" - """ current project. Several actions can be executed via the""" - """ context menu.</p>""" - )) - + self.setWhatsThis( + self.tr( + """<b>Project Forms Browser</b>""" + """<p>This allows to easily see all forms contained in the""" + """ current project. Several actions can be executed via the""" + """ context menu.</p>""" + ) + ) + # templates for Qt # these two lists have to stay in sync self.templates4 = [ - 'dialog4.tmpl', 'widget4.tmpl', 'mainwindow4.tmpl', - 'dialogbuttonboxbottom4.tmpl', 'dialogbuttonboxright4.tmpl', - 'dialogbuttonsbottom4.tmpl', 'dialogbuttonsbottomcenter4.tmpl', - 'dialogbuttonsright4.tmpl', '', 'wizard4.tmpl', 'wizardpage4.tmpl', - 'qdockwidget4.tmpl', 'qframe4.tmpl', 'qgroupbox4.tmpl', - 'qscrollarea4.tmpl', 'qmdiarea4.tmpl', 'qtabwidget4.tmpl', - 'qtoolbox4.tmpl', 'qstackedwidget4.tmpl' + "dialog4.tmpl", + "widget4.tmpl", + "mainwindow4.tmpl", + "dialogbuttonboxbottom4.tmpl", + "dialogbuttonboxright4.tmpl", + "dialogbuttonsbottom4.tmpl", + "dialogbuttonsbottomcenter4.tmpl", + "dialogbuttonsright4.tmpl", + "", + "wizard4.tmpl", + "wizardpage4.tmpl", + "qdockwidget4.tmpl", + "qframe4.tmpl", + "qgroupbox4.tmpl", + "qscrollarea4.tmpl", + "qmdiarea4.tmpl", + "qtabwidget4.tmpl", + "qtoolbox4.tmpl", + "qstackedwidget4.tmpl", ] self.templateTypes4 = [ self.tr("Dialog"), @@ -98,7 +116,7 @@ self.tr("Dialog with Buttons (Bottom)"), self.tr("Dialog with Buttons (Bottom-Center)"), self.tr("Dialog with Buttons (Right)"), - '', + "", self.tr("QWizard"), self.tr("QWizardPage"), self.tr("QDockWidget"), @@ -110,13 +128,13 @@ self.tr("QToolBox"), self.tr("QStackedWidget"), ] - + self.compileProc = None self.__uicompiler = "" - + self.project.projectClosed.connect(self.__resetUiCompiler) self.project.projectPropertiesChanged.connect(self.__resetUiCompiler) - + def _createPopupMenus(self): """ Protected overloaded method to generate the popup menu. @@ -125,286 +143,274 @@ self.multiMenuActions = [] self.dirMenuActions = [] self.dirMultiMenuActions = [] - + self.menusAboutToBeCreated.emit() - + projectType = self.project.getProjectType() - + self.menu = QMenu(self) if projectType in ["PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6"]: - self.menu.addAction( - self.tr('Compile form'), self.__compileForm) + self.menu.addAction(self.tr("Compile form"), self.__compileForm) + self.menu.addAction(self.tr("Compile all forms"), self.__compileAllForms) self.menu.addAction( - self.tr('Compile all forms'), - self.__compileAllForms) - self.menu.addAction( - self.tr('Generate Dialog Code...'), - self.__generateDialogCode) + self.tr("Generate Dialog Code..."), self.__generateDialogCode + ) self.menu.addSeparator() self.__pyuicConfigAct = self.menu.addAction( - self.tr('Configure uic Compiler'), - self.__configureUicCompiler) + self.tr("Configure uic Compiler"), self.__configureUicCompiler + ) self.menu.addSeparator() - self.menu.addAction( - self.tr('Open in Qt-Designer'), self.__openFile) - self.menu.addAction( - self.tr('Open in Editor'), self.__openFileInEditor) + self.menu.addAction(self.tr("Open in Qt-Designer"), self.__openFile) + self.menu.addAction(self.tr("Open in Editor"), self.__openFileInEditor) self.menu.addSeparator() - self.menu.addAction(self.tr('Preview form'), self.__UIPreview) - self.menu.addAction( - self.tr('Preview translations'), self.__TRPreview) + self.menu.addAction(self.tr("Preview form"), self.__UIPreview) + self.menu.addAction(self.tr("Preview translations"), self.__TRPreview) else: if self.hooks["compileForm"] is not None: self.menu.addAction( - self.hooksMenuEntries.get( - "compileForm", - self.tr('Compile form')), self.__compileForm) + self.hooksMenuEntries.get("compileForm", self.tr("Compile form")), + self.__compileForm, + ) if self.hooks["compileAllForms"] is not None: self.menu.addAction( self.hooksMenuEntries.get( - "compileAllForms", - self.tr('Compile all forms')), - self.__compileAllForms) + "compileAllForms", self.tr("Compile all forms") + ), + self.__compileAllForms, + ) if self.hooks["generateDialogCode"] is not None: self.menu.addAction( self.hooksMenuEntries.get( - "generateDialogCode", - self.tr('Generate Dialog Code...')), - self.__generateDialogCode) + "generateDialogCode", self.tr("Generate Dialog Code...") + ), + self.__generateDialogCode, + ) if ( - self.hooks["compileForm"] is not None or - self.hooks["compileAllForms"] is not None or - self.hooks["generateDialogCode"] is not None + self.hooks["compileForm"] is not None + or self.hooks["compileAllForms"] is not None + or self.hooks["generateDialogCode"] is not None ): self.menu.addSeparator() if self.hooks["open"] is not None: self.menu.addAction( - self.hooksMenuEntries.get("open", self.tr('Open')), - self.__openFile) - self.menu.addAction(self.tr('Open'), self.__openFileInEditor) + self.hooksMenuEntries.get("open", self.tr("Open")), self.__openFile + ) + self.menu.addAction(self.tr("Open"), self.__openFileInEditor) self.menu.addSeparator() - act = self.menu.addAction(self.tr('Rename file'), self._renameFile) + act = self.menu.addAction(self.tr("Rename file"), self._renameFile) self.menuActions.append(act) - act = self.menu.addAction( - self.tr('Remove from project'), self._removeFile) + act = self.menu.addAction(self.tr("Remove from project"), self._removeFile) self.menuActions.append(act) - act = self.menu.addAction(self.tr('Delete'), self.__deleteFile) + act = self.menu.addAction(self.tr("Delete"), self.__deleteFile) self.menuActions.append(act) self.menu.addSeparator() if projectType in ["PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6"]: - self.menu.addAction(self.tr('New form...'), self.__newForm) + self.menu.addAction(self.tr("New form..."), self.__newForm) else: if self.hooks["newForm"] is not None: self.menu.addAction( - self.hooksMenuEntries.get( - "newForm", self.tr('New form...')), self.__newForm) - self.menu.addAction(self.tr('Add forms...'), self.__addFormFiles) - self.menu.addAction( - self.tr('Add forms directory...'), self.__addFormsDirectory) + self.hooksMenuEntries.get("newForm", self.tr("New form...")), + self.__newForm, + ) + self.menu.addAction(self.tr("Add forms..."), self.__addFormFiles) + self.menu.addAction(self.tr("Add forms directory..."), self.__addFormsDirectory) self.menu.addSeparator() - self.menu.addAction( - self.tr('Copy Path to Clipboard'), self._copyToClipboard) + self.menu.addAction(self.tr("Copy Path to Clipboard"), self._copyToClipboard) self.menu.addSeparator() - self.menu.addAction( - self.tr('Expand all directories'), self._expandAllDirs) - self.menu.addAction( - self.tr('Collapse all directories'), self._collapseAllDirs) + self.menu.addAction(self.tr("Expand all directories"), self._expandAllDirs) + self.menu.addAction(self.tr("Collapse all directories"), self._collapseAllDirs) self.menu.addSeparator() - self.menu.addAction(self.tr('Configure...'), self._configure) + self.menu.addAction(self.tr("Configure..."), self._configure) self.backMenu = QMenu(self) if ( - projectType in [ - "PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6" - ] or self.hooks["compileAllForms"] is not None + projectType in ["PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6"] + or self.hooks["compileAllForms"] is not None ): self.backMenu.addAction( - self.tr('Compile all forms'), self.__compileAllForms) + self.tr("Compile all forms"), self.__compileAllForms + ) self.backMenu.addSeparator() self.__pyuicBackConfigAct = self.backMenu.addAction( - self.tr('Configure uic Compiler'), - self.__configureUicCompiler) + self.tr("Configure uic Compiler"), self.__configureUicCompiler + ) self.backMenu.addSeparator() - self.backMenu.addAction(self.tr('New form...'), self.__newForm) + self.backMenu.addAction(self.tr("New form..."), self.__newForm) else: if self.hooks["newForm"] is not None: self.backMenu.addAction( - self.hooksMenuEntries.get( - "newForm", self.tr('New form...')), self.__newForm) + self.hooksMenuEntries.get("newForm", self.tr("New form...")), + self.__newForm, + ) + self.backMenu.addAction(self.tr("Add forms..."), self.project.addUiFiles) self.backMenu.addAction( - self.tr('Add forms...'), self.project.addUiFiles) - self.backMenu.addAction( - self.tr('Add forms directory...'), self.project.addUiDir) + self.tr("Add forms directory..."), self.project.addUiDir + ) self.backMenu.addSeparator() - self.backMenu.addAction( - self.tr('Expand all directories'), self._expandAllDirs) + self.backMenu.addAction(self.tr("Expand all directories"), self._expandAllDirs) self.backMenu.addAction( - self.tr('Collapse all directories'), self._collapseAllDirs) + self.tr("Collapse all directories"), self._collapseAllDirs + ) self.backMenu.addSeparator() - self.backMenu.addAction(self.tr('Configure...'), self._configure) + self.backMenu.addAction(self.tr("Configure..."), self._configure) self.backMenu.setEnabled(False) # create the menu for multiple selected files self.multiMenu = QMenu(self) if projectType in ["PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6"]: self.multiMenu.addAction( - self.tr('Compile forms'), self.__compileSelectedForms) + self.tr("Compile forms"), self.__compileSelectedForms + ) self.multiMenu.addSeparator() self.__pyuicMultiConfigAct = self.multiMenu.addAction( - self.tr('Configure uic Compiler'), - self.__configureUicCompiler) + self.tr("Configure uic Compiler"), self.__configureUicCompiler + ) self.multiMenu.addSeparator() - self.multiMenu.addAction( - self.tr('Open in Qt-Designer'), self.__openFile) - self.multiMenu.addAction( - self.tr('Open in Editor'), self.__openFileInEditor) + self.multiMenu.addAction(self.tr("Open in Qt-Designer"), self.__openFile) + self.multiMenu.addAction(self.tr("Open in Editor"), self.__openFileInEditor) self.multiMenu.addSeparator() - self.multiMenu.addAction( - self.tr('Preview translations'), self.__TRPreview) + self.multiMenu.addAction(self.tr("Preview translations"), self.__TRPreview) else: if self.hooks["compileSelectedForms"] is not None: act = self.multiMenu.addAction( self.hooksMenuEntries.get( - "compileSelectedForms", - self.tr('Compile forms')), - self.__compileSelectedForms) + "compileSelectedForms", self.tr("Compile forms") + ), + self.__compileSelectedForms, + ) self.multiMenu.addSeparator() if self.hooks["open"] is not None: self.multiMenu.addAction( - self.hooksMenuEntries.get("open", self.tr('Open')), - self.__openFile) - self.multiMenu.addAction( - self.tr('Open'), self.__openFileInEditor) + self.hooksMenuEntries.get("open", self.tr("Open")), self.__openFile + ) + self.multiMenu.addAction(self.tr("Open"), self.__openFileInEditor) self.multiMenu.addSeparator() - act = self.multiMenu.addAction( - self.tr('Remove from project'), self._removeFile) + act = self.multiMenu.addAction(self.tr("Remove from project"), self._removeFile) self.multiMenuActions.append(act) - act = self.multiMenu.addAction( - self.tr('Delete'), self.__deleteFile) + act = self.multiMenu.addAction(self.tr("Delete"), self.__deleteFile) self.multiMenuActions.append(act) self.multiMenu.addSeparator() - self.multiMenu.addAction( - self.tr('Expand all directories'), self._expandAllDirs) + self.multiMenu.addAction(self.tr("Expand all directories"), self._expandAllDirs) self.multiMenu.addAction( - self.tr('Collapse all directories'), self._collapseAllDirs) + self.tr("Collapse all directories"), self._collapseAllDirs + ) self.multiMenu.addSeparator() - self.multiMenu.addAction(self.tr('Configure...'), self._configure) + self.multiMenu.addAction(self.tr("Configure..."), self._configure) self.dirMenu = QMenu(self) if projectType in ["PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6"]: - self.dirMenu.addAction( - self.tr('Compile all forms'), self.__compileAllForms) + self.dirMenu.addAction(self.tr("Compile all forms"), self.__compileAllForms) self.dirMenu.addSeparator() self.__pyuicDirConfigAct = self.dirMenu.addAction( - self.tr('Configure uic Compiler'), - self.__configureUicCompiler) + self.tr("Configure uic Compiler"), self.__configureUicCompiler + ) self.dirMenu.addSeparator() else: if self.hooks["compileAllForms"] is not None: self.dirMenu.addAction( self.hooksMenuEntries.get( - "compileAllForms", - self.tr('Compile all forms')), - self.__compileAllForms) + "compileAllForms", self.tr("Compile all forms") + ), + self.__compileAllForms, + ) self.dirMenu.addSeparator() - act = self.dirMenu.addAction( - self.tr('Remove from project'), self._removeDir) + act = self.dirMenu.addAction(self.tr("Remove from project"), self._removeDir) self.dirMenuActions.append(act) - act = self.dirMenu.addAction( - self.tr('Delete'), self._deleteDirectory) + act = self.dirMenu.addAction(self.tr("Delete"), self._deleteDirectory) self.dirMenuActions.append(act) self.dirMenu.addSeparator() if projectType in ["PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6"]: - self.dirMenu.addAction(self.tr('New form...'), self.__newForm) + self.dirMenu.addAction(self.tr("New form..."), self.__newForm) else: if self.hooks["newForm"] is not None: self.dirMenu.addAction( - self.hooksMenuEntries.get( - "newForm", - self.tr('New form...')), self.__newForm) - self.dirMenu.addAction( - self.tr('Add forms...'), self.__addFormFiles) - self.dirMenu.addAction( - self.tr('Add forms directory...'), self.__addFormsDirectory) - self.dirMenu.addSeparator() + self.hooksMenuEntries.get("newForm", self.tr("New form...")), + self.__newForm, + ) + self.dirMenu.addAction(self.tr("Add forms..."), self.__addFormFiles) self.dirMenu.addAction( - self.tr('Copy Path to Clipboard'), self._copyToClipboard) + self.tr("Add forms directory..."), self.__addFormsDirectory + ) self.dirMenu.addSeparator() - self.dirMenu.addAction( - self.tr('Expand all directories'), self._expandAllDirs) + self.dirMenu.addAction(self.tr("Copy Path to Clipboard"), self._copyToClipboard) + self.dirMenu.addSeparator() + self.dirMenu.addAction(self.tr("Expand all directories"), self._expandAllDirs) self.dirMenu.addAction( - self.tr('Collapse all directories'), self._collapseAllDirs) + self.tr("Collapse all directories"), self._collapseAllDirs + ) self.dirMenu.addSeparator() - self.dirMenu.addAction(self.tr('Configure...'), self._configure) - + self.dirMenu.addAction(self.tr("Configure..."), self._configure) + self.dirMultiMenu = QMenu(self) if projectType in ["PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6"]: self.dirMultiMenu.addAction( - self.tr('Compile all forms'), self.__compileAllForms) + self.tr("Compile all forms"), self.__compileAllForms + ) self.dirMultiMenu.addSeparator() self.__pyuicDirMultiConfigAct = self.dirMultiMenu.addAction( - self.tr('Configure uic Compiler'), - self.__configureUicCompiler) + self.tr("Configure uic Compiler"), self.__configureUicCompiler + ) self.dirMultiMenu.addSeparator() else: if self.hooks["compileAllForms"] is not None: self.dirMultiMenu.addAction( self.hooksMenuEntries.get( - "compileAllForms", - self.tr('Compile all forms')), - self.__compileAllForms) + "compileAllForms", self.tr("Compile all forms") + ), + self.__compileAllForms, + ) self.dirMultiMenu.addSeparator() + self.dirMultiMenu.addAction(self.tr("Add forms..."), self.project.addUiFiles) self.dirMultiMenu.addAction( - self.tr('Add forms...'), self.project.addUiFiles) - self.dirMultiMenu.addAction( - self.tr('Add forms directory...'), self.project.addUiDir) + self.tr("Add forms directory..."), self.project.addUiDir + ) self.dirMultiMenu.addSeparator() self.dirMultiMenu.addAction( - self.tr('Expand all directories'), self._expandAllDirs) + self.tr("Expand all directories"), self._expandAllDirs + ) self.dirMultiMenu.addAction( - self.tr('Collapse all directories'), self._collapseAllDirs) + self.tr("Collapse all directories"), self._collapseAllDirs + ) self.dirMultiMenu.addSeparator() - self.dirMultiMenu.addAction( - self.tr('Configure...'), self._configure) - + self.dirMultiMenu.addAction(self.tr("Configure..."), self._configure) + self.menu.aboutToShow.connect(self.__showContextMenu) self.multiMenu.aboutToShow.connect(self.__showContextMenuMulti) self.dirMenu.aboutToShow.connect(self.__showContextMenuDir) self.dirMultiMenu.aboutToShow.connect(self.__showContextMenuDirMulti) self.backMenu.aboutToShow.connect(self.__showContextMenuBack) self.mainMenu = self.menu - + def _contextMenuRequested(self, coord): """ Protected slot to show the context menu. - + @param coord the position of the mouse pointer (QPoint) """ if not self.project.isOpen(): return - - enable = ( - self.project.getProjectType() in ("PyQt5", "PyQt6", "E7Plugin") - ) + + enable = self.project.getProjectType() in ("PyQt5", "PyQt6", "E7Plugin") self.__pyuicConfigAct.setEnabled(enable) self.__pyuicMultiConfigAct.setEnabled(enable) self.__pyuicDirConfigAct.setEnabled(enable) self.__pyuicDirMultiConfigAct.setEnabled(enable) self.__pyuicBackConfigAct.setEnabled(enable) - + with contextlib.suppress(Exception): categories = self.getSelectedItemsCountCategorized( - [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]) + [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem] + ) cnt = categories["sum"] if cnt <= 1: index = self.indexAt(coord) if index.isValid(): self._selectSingleItem(index) categories = self.getSelectedItemsCountCategorized( - [ProjectBrowserFileItem, - ProjectBrowserSimpleDirectoryItem]) + [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem] + ) cnt = categories["sum"] - + bfcnt = categories[str(ProjectBrowserFileItem)] sdcnt = categories[str(ProjectBrowserSimpleDirectoryItem)] if cnt > 1 and cnt == bfcnt: @@ -422,47 +428,47 @@ self.backMenu.popup(self.mapToGlobal(coord)) else: self.backMenu.popup(self.mapToGlobal(coord)) - + def __showContextMenu(self): """ Private slot called by the menu aboutToShow signal. """ ProjectBaseBrowser._showContextMenu(self, self.menu) - + self.showMenu.emit("Main", self.menu) - + def __showContextMenuMulti(self): """ Private slot called by the multiMenu aboutToShow signal. """ ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu) - + self.showMenu.emit("MainMulti", self.multiMenu) - + def __showContextMenuDir(self): """ Private slot called by the dirMenu aboutToShow signal. """ ProjectBaseBrowser._showContextMenuDir(self, self.dirMenu) - + self.showMenu.emit("MainDir", self.dirMenu) - + def __showContextMenuDirMulti(self): """ Private slot called by the dirMultiMenu aboutToShow signal. """ ProjectBaseBrowser._showContextMenuDirMulti(self, self.dirMultiMenu) - + self.showMenu.emit("MainDirMulti", self.dirMultiMenu) - + def __showContextMenuBack(self): """ Private slot called by the backMenu aboutToShow signal. """ ProjectBaseBrowser._showContextMenuBack(self, self.backMenu) - + self.showMenu.emit("MainBack", self.backMenu) - + def __addFormFiles(self): """ Private method to add form files to the project. @@ -471,14 +477,13 @@ if isinstance(itm, ProjectBrowserFileItem): dn = os.path.dirname(itm.fileName()) elif isinstance( - itm, - (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem) + itm, (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem) ): dn = itm.dirName() else: dn = None - self.project.addFiles('form', dn) - + self.project.addFiles("form", dn) + def __addFormsDirectory(self): """ Private method to add form files of a directory to the project. @@ -487,14 +492,13 @@ if isinstance(itm, ProjectBrowserFileItem): dn = os.path.dirname(itm.fileName()) elif isinstance( - itm, - (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem) + itm, (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem) ): dn = itm.dirName() else: dn = None - self.project.addDirectory('form', dn) - + self.project.addDirectory("form", dn) + def __openFile(self): """ Private slot to handle the Open menu action. @@ -508,7 +512,7 @@ self.hooks["open"](itm.fileName()) else: self.designerFile.emit(itm.fileName()) - + def __openFileInEditor(self): """ Private slot to handle the Open in Editor menu action. @@ -516,7 +520,7 @@ itmList = self.getSelectedItems() for itm in itmList[:]: self.sourceFile.emit(itm.fileName()) - + def _openItem(self): """ Protected slot to handle the open popup menu entry. @@ -528,14 +532,14 @@ self.designerFile.emit(itm.fileName()) else: self.sourceFile.emit(itm.fileName()) - + def __UIPreview(self): """ Private slot to handle the Preview menu action. """ itmList = self.getSelectedItems() self.uipreview.emit(itmList[0].fileName()) - + def __TRPreview(self): """ Private slot to handle the Preview translations action. @@ -544,11 +548,15 @@ for itm in self.getSelectedItems(): fileNames.append(itm.fileName()) trfiles = sorted(self.project.pdata["TRANSLATIONS"][:]) - fileNames.extend([os.path.join(self.project.ppath, trfile) - for trfile in trfiles - if trfile.endswith('.qm')]) + fileNames.extend( + [ + os.path.join(self.project.ppath, trfile) + for trfile in trfiles + if trfile.endswith(".qm") + ] + ) self.trpreview[list].emit(fileNames) - + def __newForm(self): """ Private slot to handle the New Form menu action. @@ -564,20 +572,24 @@ path = itm.dirName() except AttributeError: path = os.path.join(self.project.ppath, itm.data(0)) - + if self.hooks["newForm"] is not None: self.hooks["newForm"](path) else: if self.project.getProjectType() in [ - "PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6" + "PyQt5", + "PyQt6", + "E7Plugin", + "PySide2", + "PySide6", ]: self.__newUiForm(path) - + def __newUiForm(self, path): """ Private slot to handle the New Form menu action for Qt-related projects. - + @param path full directory path for the new form file (string) """ selectedForm, ok = QInputDialog.getItem( @@ -585,27 +597,31 @@ self.tr("New Form"), self.tr("Select a form type:"), self.templateTypes4, - 0, False) + 0, + False, + ) if not ok or not selectedForm: # user pressed cancel return - + templateIndex = self.templateTypes4.index(selectedForm) templateFile = os.path.join( - getConfig('ericTemplatesDir'), self.templates4[templateIndex]) - + getConfig("ericTemplatesDir"), self.templates4[templateIndex] + ) + fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( self, self.tr("New Form"), path, self.tr("Qt User-Interface Files (*.ui);;All Files (*)"), "", - EricFileDialog.DontConfirmOverwrite) - + EricFileDialog.DontConfirmOverwrite, + ) + if not fname: # user aborted or didn't enter a filename return - + fpath = pathlib.Path(fname) if not fpath.suffix: ex = selectedFilter.split("(*")[1].split(")")[0] @@ -616,11 +632,12 @@ self, self.tr("New Form"), self.tr("The file already exists! Overwrite it?"), - icon=EricMessageBox.Warning) + icon=EricMessageBox.Warning, + ) if not res: # user selected to not overwrite return - + try: shutil.copy(templateFile, fpath) except OSError as err: @@ -629,18 +646,20 @@ self.tr("New Form"), self.tr( "<p>The new form file <b>{0}</b> could not be created.<br>" - "Problem: {1}</p>").format(fpath, str(err))) + "Problem: {1}</p>" + ).format(fpath, str(err)), + ) return - + self.project.appendFile(str(fpath)) self.designerFile.emit(str(fpath)) - + def __deleteFile(self): """ Private method to delete a form file from the project. """ itmList = self.getSelectedItems() - + files = [] fullNames = [] for itm in itmList: @@ -648,64 +667,65 @@ fullNames.append(fn2) fn = self.project.getRelativePath(fn2) files.append(fn) - - from UI.DeleteFilesConfirmationDialog import ( - DeleteFilesConfirmationDialog - ) + + from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog + dlg = DeleteFilesConfirmationDialog( self.parent(), self.tr("Delete forms"), - self.tr( - "Do you really want to delete these forms from the project?"), - files) - + self.tr("Do you really want to delete these forms from the project?"), + files, + ) + if dlg.exec() == QDialog.DialogCode.Accepted: for fn2, fn in zip(fullNames, files): self.closeSourceWindow.emit(fn2) self.project.deleteFile(fn) - + ########################################################################### ## Methods to handle the various compile commands ########################################################################### - + def __resetUiCompiler(self): """ Private slot to reset the determined UI compiler executable. """ self.__uicompiler = "" - + def __determineUiCompiler(self): """ Private method to determine the UI compiler for the project. """ self.__resetUiCompiler() - + if self.project.getProjectLanguage() == "Python3": if self.project.getProjectType() in ["PyQt5"]: self.__uicompiler = Utilities.generatePyQtToolPath( - 'pyuic5', ["py3uic5"]) + "pyuic5", ["py3uic5"] + ) elif self.project.getProjectType() in ["PyQt6", "E7Plugin"]: - self.__uicompiler = Utilities.generatePyQtToolPath( - 'pyuic6') + self.__uicompiler = Utilities.generatePyQtToolPath("pyuic6") elif self.project.getProjectType() == "PySide2": self.__uicompiler = Utilities.generatePySideToolPath( - 'pyside2-uic', variant=2) + "pyside2-uic", variant=2 + ) elif self.project.getProjectType() == "PySide6": self.__uicompiler = Utilities.generatePySideToolPath( - 'pyside6-uic', variant=6) - + "pyside6-uic", variant=6 + ) + def getUiCompiler(self): """ Public method to get the UI compiler executable of the project. - + @return UI compiler executable @rtype str """ if not self.__uicompiler: self.__determineUiCompiler() - + return self.__uicompiler - + def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal of the @@ -714,11 +734,10 @@ if self.compileProc is None: return self.compileProc.setReadChannel(QProcess.ProcessChannel.StandardOutput) - + while self.compileProc and self.compileProc.canReadLine(): - self.buf += str(self.compileProc.readLine(), - "utf-8", 'replace') - + self.buf += str(self.compileProc.readLine(), "utf-8", "replace") + def __readStderr(self): """ Private slot to handle the readyReadStandardError signal of the @@ -726,36 +745,32 @@ """ if self.compileProc is None: return - + ioEncoding = Preferences.getSystem("IOEncoding") - + self.compileProc.setReadChannel(QProcess.ProcessChannel.StandardError) while self.compileProc and self.compileProc.canReadLine(): - s = self.__uicompiler + ': ' - error = str(self.compileProc.readLine(), - ioEncoding, 'replace') + s = self.__uicompiler + ": " + error = str(self.compileProc.readLine(), ioEncoding, "replace") s += error self.appendStderr.emit(s) - + def __compileUIDone(self, exitCode, exitStatus): """ Private slot to handle the finished signal of the pyuic/rbuic process. - + @param exitCode exit code of the process (integer) @param exitStatus exit status of the process (QProcess.ExitStatus) """ self.compileRunning = False ericApp().getObject("ViewManager").enableEditorsCheckFocusIn(True) ui = ericApp().getObject("UserInterface") - if ( - exitStatus == QProcess.ExitStatus.NormalExit and - exitCode == 0 and - self.buf - ): + if exitStatus == QProcess.ExitStatus.NormalExit and exitCode == 0 and self.buf: ofn = os.path.join(self.project.ppath, self.compiledFile) try: - newline = (None if self.project.useSystemEol() - else self.project.getEolString()) + newline = ( + None if self.project.useSystemEol() else self.project.getEolString() + ) with open(ofn, "w", encoding="utf-8", newline=newline) as f: for line in self.buf.splitlines(): f.write(line + "\n") @@ -764,8 +779,8 @@ ui.showNotification( UI.PixmapCache.getPixmap("designer48"), self.tr("Form Compilation"), - self.tr("The compilation of the form file" - " was successful.")) + self.tr("The compilation of the form file" " was successful."), + ) self.project.projectFormCompiled.emit(self.compiledFile) except OSError as msg: ui.showNotification( @@ -773,22 +788,25 @@ self.tr("Form Compilation"), self.tr( "<p>The compilation of the form file failed.</p>" - "<p>Reason: {0}</p>").format(str(msg)), + "<p>Reason: {0}</p>" + ).format(str(msg)), kind=NotificationTypes.CRITICAL, - timeout=0) + timeout=0, + ) else: ui.showNotification( UI.PixmapCache.getPixmap("designer48"), self.tr("Form Compilation"), self.tr("The compilation of the form file failed."), kind=NotificationTypes.CRITICAL, - timeout=0) + timeout=0, + ) self.compileProc = None - + def __compileUI(self, fn, noDialog=False, progress=None): """ Private method to compile a .ui file to a .py/.rb file. - + @param fn filename of the .ui file to be compiled @param noDialog flag indicating silent operations @param progress reference to the progress dialog @@ -797,18 +815,18 @@ self.compileProc = QProcess() args = [] self.buf = "" - + uicompiler = self.getUiCompiler() if not uicompiler: return None - + ofn, ext = os.path.splitext(fn) fn = os.path.join(self.project.ppath, fn) - + if self.project.getProjectLanguage() == "Python3": dirname, filename = os.path.split(ofn) self.compiledFile = os.path.join(dirname, "Ui_" + filename + ".py") - + if self.project.getProjectType() == "PySide2": # PySide2 if Preferences.getQt("PySide2FromImports"): @@ -831,26 +849,29 @@ indentWidth = Preferences.getQt("PyuicIndent") if indentWidth != self.Pyuic5IndentDefault: args.append("--indent={0}".format(indentWidth)) - if ( - 'uic5' in uicompiler and - self.project.pdata["UICPARAMS"]["Package"] - ): - args.append("--import-from={0}".format( - self.project.pdata["UICPARAMS"]["Package"])) + if "uic5" in uicompiler and self.project.pdata["UICPARAMS"]["Package"]: + args.append( + "--import-from={0}".format( + self.project.pdata["UICPARAMS"]["Package"] + ) + ) elif Preferences.getQt("PyuicFromImports"): args.append("--from-imports") if self.project.pdata["UICPARAMS"]["RcSuffix"]: - args.append("--resource-suffix={0}".format( - self.project.pdata["UICPARAMS"]["RcSuffix"])) + args.append( + "--resource-suffix={0}".format( + self.project.pdata["UICPARAMS"]["RcSuffix"] + ) + ) elif self.project.getProjectLanguage() == "Ruby": - self.compiledFile = ofn + '.rb' - args.append('-x') - + self.compiledFile = ofn + ".rb" + args.append("-x") + args.append(fn) self.compileProc.finished.connect(self.__compileUIDone) self.compileProc.readyReadStandardOutput.connect(self.__readStdout) self.compileProc.readyReadStandardError.connect(self.__readStderr) - + self.noDialog = noDialog self.compileProc.setWorkingDirectory(self.project.getProjectPath()) self.compileProc.start(uicompiler, args) @@ -865,38 +886,38 @@ progress.cancel() EricMessageBox.critical( self, - self.tr('Process Generation Error'), + self.tr("Process Generation Error"), self.tr( - 'Could not start {0}.<br>' - 'Ensure that it is in the search path.' - ).format(uicompiler)) + "Could not start {0}.<br>" "Ensure that it is in the search path." + ).format(uicompiler), + ) return None - + def __generateDialogCode(self): """ Private method to generate dialog code for the form (Qt only). """ itm = self.model().item(self.currentIndex()) fn = itm.fileName() - + if self.hooks["generateDialogCode"] is not None: self.hooks["generateDialogCode"](fn) else: from .CreateDialogCodeDialog import CreateDialogCodeDialog - + # change environment sys.path.insert(0, self.project.getProjectPath()) cwd = os.getcwd() os.chdir(os.path.dirname(os.path.abspath(fn))) - + dlg = CreateDialogCodeDialog(fn, self.project, self) if not dlg.initError(): dlg.exec() - + # reset the environment os.chdir(cwd) del sys.path[0] - + def __compileForm(self): """ Private method to compile a form to a source file. @@ -908,7 +929,7 @@ self.hooks["compileForm"](fn) else: self.__compileUI(fn) - + def __compileAllForms(self): """ Private method to compile all forms to source files. @@ -919,17 +940,21 @@ numForms = len(self.project.pdata["FORMS"]) progress = EricProgressDialog( self.tr("Compiling forms..."), - self.tr("Abort"), 0, numForms, - self.tr("%v/%m Forms"), self) + self.tr("Abort"), + 0, + numForms, + self.tr("%v/%m Forms"), + self, + ) progress.setModal(True) progress.setMinimumDuration(0) progress.setWindowTitle(self.tr("Forms")) - + for prog, fn in enumerate(self.project.pdata["FORMS"]): progress.setValue(prog) if progress.wasCanceled(): break - + proc = self.__compileUI(fn, True, progress) if proc is not None: while proc.state() == QProcess.ProcessState.Running: @@ -938,32 +963,35 @@ else: break progress.setValue(numForms) - + def __compileSelectedForms(self): """ Private method to compile selected forms to source files. """ items = self.getSelectedItems() - files = [self.project.getRelativePath(itm.fileName()) - for itm in items] - + files = [self.project.getRelativePath(itm.fileName()) for itm in items] + if self.hooks["compileSelectedForms"] is not None: self.hooks["compileSelectedForms"](files) else: numForms = len(files) progress = EricProgressDialog( self.tr("Compiling forms..."), - self.tr("Abort"), 0, numForms, - self.tr("%v/%m Forms"), self) + self.tr("Abort"), + 0, + numForms, + self.tr("%v/%m Forms"), + self, + ) progress.setModal(True) progress.setMinimumDuration(0) progress.setWindowTitle(self.tr("Forms")) - + for prog, fn in enumerate(files): progress.setValue(prog) if progress.wasCanceled(): break - + proc = self.__compileUI(fn, True, progress) if proc is not None: while proc.state() == QProcess.ProcessState.Running: @@ -972,7 +1000,7 @@ else: break progress.setValue(numForms) - + def compileChangedForms(self): """ Public method to compile all changed forms to source files. @@ -981,45 +1009,53 @@ self.hooks["compileChangedForms"](self.project.pdata["FORMS"]) else: if self.project.getProjectType() not in [ - "PyQt5", "PyQt6", "E7Plugin", "PySide2", "PySide6" + "PyQt5", + "PyQt6", + "E7Plugin", + "PySide2", + "PySide6", ]: # ignore the request for non Qt GUI projects return - + if len(self.project.pdata["FORMS"]) == 0: # The project does not contain form files. return - + progress = EricProgressDialog( self.tr("Determining changed forms..."), - self.tr("Abort"), 0, 100, self.tr("%v/%m Forms"), self) + self.tr("Abort"), + 0, + 100, + self.tr("%v/%m Forms"), + self, + ) progress.setMinimumDuration(0) progress.setWindowTitle(self.tr("Forms")) - + # get list of changed forms changedForms = [] progress.setMaximum(len(self.project.pdata["FORMS"])) for prog, fn in enumerate(self.project.pdata["FORMS"]): progress.setValue(prog) QApplication.processEvents() - + ifn = os.path.join(self.project.ppath, fn) if self.project.getProjectLanguage() == "Python3": dirname, filename = os.path.split(os.path.splitext(ifn)[0]) ofn = os.path.join(dirname, "Ui_" + filename + ".py") elif self.project.getProjectLanguage() == "Ruby": - ofn = os.path.splitext(ifn)[0] + '.rb' + ofn = os.path.splitext(ifn)[0] + ".rb" if ( - not os.path.exists(ofn) or - os.stat(ifn).st_mtime > os.stat(ofn).st_mtime + not os.path.exists(ofn) + or os.stat(ifn).st_mtime > os.stat(ofn).st_mtime ): changedForms.append(fn) progress.setValue(len(self.project.pdata["FORMS"])) QApplication.processEvents() - + if changedForms: - progress.setLabelText( - self.tr("Compiling changed forms...")) + progress.setLabelText(self.tr("Compiling changed forms...")) progress.setMaximum(len(changedForms)) progress.setValue(prog) QApplication.processEvents() @@ -1027,7 +1063,7 @@ progress.setValue(prog) if progress.wasCanceled(): break - + proc = self.__compileUI(fn, True, progress) if proc is not None: while proc.state() == QProcess.ProcessState.Running: @@ -1038,23 +1074,23 @@ break progress.setValue(len(changedForms)) QApplication.processEvents() - + def handlePreferencesChanged(self): """ Public slot used to handle the preferencesChanged signal. """ ProjectBaseBrowser.handlePreferencesChanged(self) - + self.__resetUiCompiler() - + def __configureUicCompiler(self): """ Private slot to configure some non-common uic compiler options. """ from .UicCompilerOptionsDialog import UicCompilerOptionsDialog - + params = self.project.pdata["UICPARAMS"] - + if self.project.getProjectType() in ["PyQt5", "PyQt6", "E7Plugin"]: dlg = UicCompilerOptionsDialog(params, self.getUiCompiler()) if dlg.exec() == QDialog.DialogCode.Accepted: @@ -1068,15 +1104,15 @@ if root != params["PackagesRoot"]: params["PackagesRoot"] = root self.project.setDirty(True) - + ########################################################################### ## Support for hooks below ########################################################################### - + def _initHookMethods(self): """ Protected method to initialize the hooks dictionary. - + Supported hook methods are: <ul> <li>compileForm: takes filename as parameter</li> @@ -1087,7 +1123,7 @@ <li>newForm: takes full directory path of new file as parameter</li> <li>open: takes a filename as parameter</li> </ul> - + <b>Note</b>: Filenames are relative to the project directory, if not specified differently. """