--- a/src/eric7/Preferences/ProgramsDialog.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Preferences/ProgramsDialog.py Wed Jul 13 14:55:47 2022 +0200 @@ -12,7 +12,11 @@ from PyQt6.QtCore import pyqtSlot, Qt, QProcess from PyQt6.QtWidgets import ( - QApplication, QTreeWidgetItem, QHeaderView, QDialog, QDialogButtonBox + QApplication, + QTreeWidgetItem, + QHeaderView, + QDialog, + QDialogButtonBox, ) from EricWidgets.EricApplication import ericApp @@ -29,35 +33,37 @@ """ Class implementing the Programs page. """ + ToolAvailableRole = Qt.ItemDataRole.UserRole + 1 - + def __init__(self, parent=None): """ Constructor - + @param parent The parent widget of this dialog. (QWidget) """ super().__init__(parent) self.setupUi(self) self.setObjectName("ProgramsDialog") self.setWindowFlags(Qt.WindowType.Window) - + self.__hasSearched = False - - self.programsList.headerItem().setText( - self.programsList.columnCount(), "") - + + self.programsList.headerItem().setText(self.programsList.columnCount(), "") + self.searchButton = self.buttonBox.addButton( - self.tr("Search"), QDialogButtonBox.ButtonRole.ActionRole) - self.searchButton.setToolTip( - self.tr("Press to search for programs")) - - self.showComboBox.addItems([ - self.tr("All Supported Tools"), - self.tr("Available Tools Only"), - self.tr("Unavailable Tools Only"), - ]) - + self.tr("Search"), QDialogButtonBox.ButtonRole.ActionRole + ) + self.searchButton.setToolTip(self.tr("Press to search for programs")) + + self.showComboBox.addItems( + [ + self.tr("All Supported Tools"), + self.tr("Available Tools Only"), + self.tr("Unavailable Tools Only"), + ] + ) + def show(self): """ Public slot to show the dialog. @@ -65,16 +71,16 @@ QDialog.show(self) if not self.__hasSearched: self.on_programsSearchButton_clicked() - + def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. - + @param button button that was clicked (QAbstractButton) """ if button == self.searchButton: self.on_programsSearchButton_clicked() - + @pyqtSlot() def on_programsSearchButton_clicked(self): """ @@ -84,124 +90,164 @@ header = self.programsList.header() header.setSortIndicator(0, Qt.SortOrder.AscendingOrder) header.setSortIndicatorShown(False) - + with EricOverrideCursor(): # 1. do the Qt programs # 1a. Translation Converter exe = ( - Utilities.isWindowsPlatform() and - "{0}.exe".format(Utilities.generateQtToolName("lrelease")) or - Utilities.generateQtToolName("lrelease") + Utilities.isWindowsPlatform() + and "{0}.exe".format(Utilities.generateQtToolName("lrelease")) + or Utilities.generateQtToolName("lrelease") ) exe = os.path.join(Utilities.getQtBinariesPath(), exe) version = self.__createProgramEntry( - self.tr("Translation Converter (Qt)"), exe, '-version', - 'lrelease', -1) + self.tr("Translation Converter (Qt)"), exe, "-version", "lrelease", -1 + ) # 1b. Qt Designer if Utilities.isWindowsPlatform(): exe = os.path.join( Utilities.getQtBinariesPath(), - "{0}.exe".format(Utilities.generateQtToolName("designer"))) + "{0}.exe".format(Utilities.generateQtToolName("designer")), + ) elif Utilities.isMacPlatform(): exe = Utilities.getQtMacBundle("designer") else: exe = os.path.join( Utilities.getQtBinariesPath(), - Utilities.generateQtToolName("designer")) - self.__createProgramEntry( - self.tr("Qt Designer"), exe, version=version) + Utilities.generateQtToolName("designer"), + ) + self.__createProgramEntry(self.tr("Qt Designer"), exe, version=version) # 1c. Qt Linguist if Utilities.isWindowsPlatform(): exe = os.path.join( Utilities.getQtBinariesPath(), - "{0}.exe".format(Utilities.generateQtToolName("linguist"))) + "{0}.exe".format(Utilities.generateQtToolName("linguist")), + ) elif Utilities.isMacPlatform(): exe = Utilities.getQtMacBundle("linguist") else: exe = os.path.join( Utilities.getQtBinariesPath(), - Utilities.generateQtToolName("linguist")) - self.__createProgramEntry( - self.tr("Qt Linguist"), exe, version=version) + Utilities.generateQtToolName("linguist"), + ) + self.__createProgramEntry(self.tr("Qt Linguist"), exe, version=version) # 1d. Qt Assistant if Utilities.isWindowsPlatform(): exe = os.path.join( Utilities.getQtBinariesPath(), - "{0}.exe".format( - Utilities.generateQtToolName("assistant"))) + "{0}.exe".format(Utilities.generateQtToolName("assistant")), + ) elif Utilities.isMacPlatform(): exe = Utilities.getQtMacBundle("assistant") else: exe = os.path.join( Utilities.getQtBinariesPath(), - Utilities.generateQtToolName("assistant")) - self.__createProgramEntry( - self.tr("Qt Assistant"), exe, version=version) - + Utilities.generateQtToolName("assistant"), + ) + self.__createProgramEntry(self.tr("Qt Assistant"), exe, version=version) + # 2. do the PyQt programs # 2.1 do the PyQt5 programs # 2.1a. Translation Extractor PyQt5 self.__createProgramEntry( self.tr("Translation Extractor (Python, PyQt5)"), Utilities.generatePyQtToolPath("pylupdate5"), - '-version', 'pylupdate', -1) + "-version", + "pylupdate", + -1, + ) # 2.1b. Forms Compiler PyQt5 self.__createProgramEntry( self.tr("Forms Compiler (Python, PyQt5)"), Utilities.generatePyQtToolPath("pyuic5", ["py3uic5"]), - '--version', 'Python User', 4) + "--version", + "Python User", + 4, + ) # 2.1c. Resource Compiler PyQt5 self.__createProgramEntry( self.tr("Resource Compiler (Python, PyQt5)"), Utilities.generatePyQtToolPath("pyrcc5"), - '-version', '', -1, versionRe='Resource Compiler|pyrcc5') - + "-version", + "", + -1, + versionRe="Resource Compiler|pyrcc5", + ) + # 2.2 do the PyQt6 programs # 2.2a. Translation Extractor PyQt6 self.__createProgramEntry( self.tr("Translation Extractor (Python, PyQt6)"), Utilities.generatePyQtToolPath("pylupdate6"), - '--version', versionPosition=0) + "--version", + versionPosition=0, + ) # 2.2b. Forms Compiler PyQt6 self.__createProgramEntry( self.tr("Forms Compiler (Python, PyQt6)"), Utilities.generatePyQtToolPath("pyuic6"), - '--version', versionPosition=0) - + "--version", + versionPosition=0, + ) + # 3. do the PySide programs # 3.1 do the PySide2 programs # 3.1a. Translation Extractor PySide2 self.__createProgramEntry( self.tr("Translation Extractor (Python, PySide2)"), Utilities.generatePySideToolPath("pyside2-lupdate", variant=2), - '-version', '', -1, versionRe='lupdate') + "-version", + "", + -1, + versionRe="lupdate", + ) # 3.1b. Forms Compiler PySide2 self.__createProgramEntry( self.tr("Forms Compiler (Python, PySide2)"), Utilities.generatePySideToolPath("pyside2-uic", variant=2), - '--version', '', -1, versionRe='uic') + "--version", + "", + -1, + versionRe="uic", + ) # 3.1c Resource Compiler PySide2 self.__createProgramEntry( self.tr("Resource Compiler (Python, PySide2)"), Utilities.generatePySideToolPath("pyside2-rcc", variant=2), - '-version', '', -1, versionRe='rcc') + "-version", + "", + -1, + versionRe="rcc", + ) # 3.2 do the PySide5 programs # 3.2a. Translation Extractor PySide6 self.__createProgramEntry( self.tr("Translation Extractor (Python, PySide6)"), Utilities.generatePySideToolPath("pyside6-lupdate", variant=6), - '-version', '', -1, versionRe='lupdate') + "-version", + "", + -1, + versionRe="lupdate", + ) # 3.2b. Forms Compiler PySide6 self.__createProgramEntry( self.tr("Forms Compiler (Python, PySide6)"), Utilities.generatePySideToolPath("pyside6-uic", variant=6), - '--version', '', -1, versionRe='uic') + "--version", + "", + -1, + versionRe="uic", + ) # 3.2c Resource Compiler PySide6 self.__createProgramEntry( self.tr("Resource Compiler (Python, PySide6)"), Utilities.generatePySideToolPath("pyside6-rcc", variant=6), - '--version', '', -1, versionRe='rcc') - + "--version", + "", + -1, + versionRe="rcc", + ) + # 4. do the Conda program(s) exe = Preferences.getConda("CondaExecutable") if not exe: @@ -209,17 +255,22 @@ if Utilities.isWindowsPlatform(): exe += ".exe" self.__createProgramEntry( - self.tr("conda Manager"), exe, '--version', 'conda', -1) - + self.tr("conda Manager"), exe, "--version", "conda", -1 + ) + # 5. do the pip program(s) virtualenvManager = ericApp().getObject("VirtualEnvManager") for venvName in virtualenvManager.getVirtualenvNames(): - interpreter = virtualenvManager.getVirtualenvInterpreter( - venvName) + interpreter = virtualenvManager.getVirtualenvInterpreter(venvName) self.__createProgramEntry( - self.tr("PyPI Package Management"), interpreter, - '--version', 'pip', 1, exeModule=["-m", "pip"]) - + self.tr("PyPI Package Management"), + interpreter, + "--version", + "pip", + 1, + exeModule=["-m", "pip"], + ) + # 6. do the CORBA and Protobuf programs # 6a. omniORB exe = Preferences.getCorba("omniidl") @@ -228,7 +279,8 @@ if Utilities.isWindowsPlatform(): exe += ".exe" self.__createProgramEntry( - self.tr("CORBA IDL Compiler"), exe, '-V', 'omniidl', -1) + self.tr("CORBA IDL Compiler"), exe, "-V", "omniidl", -1 + ) # 6b. protobuf exe = Preferences.getProtobuf("protoc") if not exe: @@ -236,19 +288,25 @@ if Utilities.isWindowsPlatform(): exe += ".exe" self.__createProgramEntry( - self.tr("Protobuf Compiler"), exe, '--version', 'libprotoc', - -1) + self.tr("Protobuf Compiler"), exe, "--version", "libprotoc", -1 + ) # 6c. grpc exe = Preferences.getProtobuf("grpcPython") if not exe: exe = Globals.getPythonExecutable() self.__createProgramEntry( - self.tr("gRPC Compiler"), exe, '--version', 'libprotoc', -1, - exeModule=['-m', 'grpc_tools.protoc']) - + self.tr("gRPC Compiler"), + exe, + "--version", + "libprotoc", + -1, + exeModule=["-m", "grpc_tools.protoc"], + ) + # 7. do the spell checking entry try: import enchant + try: text = os.path.dirname(enchant.__file__) except AttributeError: @@ -260,12 +318,12 @@ except (ImportError, AttributeError, OSError): text = "enchant" version = "" - self.__createEntry( - self.tr("Spell Checker - PyEnchant"), text, version) - + self.__createEntry(self.tr("Spell Checker - PyEnchant"), text, version) + # 8. do the pygments entry try: import pygments + try: text = os.path.dirname(pygments.__file__) except AttributeError: @@ -277,30 +335,42 @@ except (ImportError, AttributeError, OSError): text = "pygments" version = "" - self.__createEntry( - self.tr("Source Highlighter - Pygments"), text, version) - + self.__createEntry(self.tr("Source Highlighter - Pygments"), text, version) + # 9. do the MicroPython related entries exe = Preferences.getMicroPython("MpyCrossCompiler") if not exe: exe = "mpy-cross" self.__createProgramEntry( - self.tr("MicroPython - MPY Cross Compiler"), exe, '--version', - 'MicroPython', 1) + self.tr("MicroPython - MPY Cross Compiler"), + exe, + "--version", + "MicroPython", + 1, + ) self.__createProgramEntry( self.tr("MicroPython - ESP Tool"), - Globals.getPythonExecutable(), 'version', - 'esptool', -1, exeModule=['-m', 'esptool']) + Globals.getPythonExecutable(), + "version", + "esptool", + -1, + exeModule=["-m", "esptool"], + ) exe = Preferences.getMicroPython("DfuUtilPath") if not exe: exe = "dfu-util" self.__createProgramEntry( - self.tr("MicroPython - PyBoard Flasher"), exe, '--version', - 'dfu-util', -1) - + self.tr("MicroPython - PyBoard Flasher"), + exe, + "--version", + "dfu-util", + -1, + ) + # 10. do the jedi related entries try: import jedi + try: text = os.path.dirname(jedi.__file__) except AttributeError: @@ -312,9 +382,8 @@ except (ImportError, AttributeError, OSError): text = "jedi" version = "" - self.__createEntry( - self.tr("Code Assistant - Jedi"), text, version) - + self.__createEntry(self.tr("Code Assistant - Jedi"), text, version) + # 11. do the plugin related programs pm = ericApp().getObject("PluginManager") for info in pm.getPluginExeDisplayData(): @@ -335,26 +404,28 @@ exeModule=info["exeModule"], ) else: - self.__createEntry( - info["header"], - info["text"], - info["version"] - ) - + self.__createEntry(info["header"], info["text"], info["version"]) + self.programsList.sortByColumn(0, Qt.SortOrder.AscendingOrder) - self.on_showComboBox_currentIndexChanged( - self.showComboBox.currentIndex()) - + self.on_showComboBox_currentIndexChanged(self.showComboBox.currentIndex()) + self.__hasSearched = True - def __createProgramEntry(self, description, exe, - versionCommand="", versionStartsWith="", - versionPosition=None, version="", - versionCleanup=None, versionRe=None, - exeModule=None): + def __createProgramEntry( + self, + description, + exe, + versionCommand="", + versionStartsWith="", + versionPosition=None, + version="", + versionCleanup=None, + versionRe=None, + exeModule=None, + ): """ Private method to generate a program entry. - + @param description descriptive text (string) @param exe name of the executable program (string) @param versionCommand command line switch to get the version info @@ -374,11 +445,10 @@ @return version string of detected or given version (string) """ itmList = self.programsList.findItems( - description, Qt.MatchFlag.MatchCaseSensitive) + description, Qt.MatchFlag.MatchCaseSensitive + ) itm = ( - itmList[0] - if itmList else - QTreeWidgetItem(self.programsList, [description]) + itmList[0] if itmList else QTreeWidgetItem(self.programsList, [description]) ) font = itm.font(0) font.setBold(True) @@ -397,7 +467,8 @@ if versionCommand and versionPosition is not None: proc = QProcess() proc.setProcessChannelMode( - QProcess.ProcessChannelMode.MergedChannels) + QProcess.ProcessChannelMode.MergedChannels + ) if exeModule: args = exeModule[:] + [versionCommand] else: @@ -405,36 +476,36 @@ proc.start(exe, args) finished = proc.waitForFinished(10000) if finished: - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace') + output = str( + proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + "replace", + ) if ( - exeModule and - exeModule[0] == "-m" and - ("ImportError:" in output or - "ModuleNotFoundError:" in output or - proc.exitCode() != 0) + exeModule + and exeModule[0] == "-m" + and ( + "ImportError:" in output + or "ModuleNotFoundError:" in output + or proc.exitCode() != 0 + ) ): version = self.tr("(module not found)") available = False elif not versionStartsWith and not versionRe: # assume output is just one line try: - version = ( - output.strip().split()[versionPosition] - ) + version = output.strip().split()[versionPosition] if versionCleanup: version = version[ - versionCleanup[0]: - versionCleanup[1] + versionCleanup[0] : versionCleanup[1] ] except IndexError: version = self.tr("(unknown)") available = False else: if versionRe is None: - versionRe = "^{0}".format( - re.escape(versionStartsWith)) + versionRe = "^{0}".format(re.escape(versionStartsWith)) versionRe = re.compile(versionRe, re.UNICODE) for line in output.splitlines(): if versionRe.search(line): @@ -442,8 +513,7 @@ version = line.split()[versionPosition] if versionCleanup: version = version[ - versionCleanup[0]: - versionCleanup[1] + versionCleanup[0] : versionCleanup[1] ] break except IndexError: @@ -456,9 +526,9 @@ version = self.tr("(not executable)") available = False if exeModule: - citm = QTreeWidgetItem(itm, [ - "{0} {1}".format(exe, " ".join(exeModule)), - version]) + citm = QTreeWidgetItem( + itm, ["{0} {1}".format(exe, " ".join(exeModule)), version] + ) else: citm = QTreeWidgetItem(itm, [exe, version]) citm.setData(0, self.ToolAvailableRole, available) @@ -467,20 +537,20 @@ if itm.childCount() == 0: itm.setText(1, self.tr("(not found)")) else: - citm = QTreeWidgetItem( - itm, [rememberedExe, self.tr("(not found)")]) + citm = QTreeWidgetItem(itm, [rememberedExe, self.tr("(not found)")]) citm.setData(0, self.ToolAvailableRole, False) itm.setExpanded(True) QApplication.processEvents() self.programsList.header().resizeSections( - QHeaderView.ResizeMode.ResizeToContents) + QHeaderView.ResizeMode.ResizeToContents + ) self.programsList.header().setStretchLastSection(True) return version - + def __createEntry(self, description, entryText, entryVersion): """ Private method to generate a program entry. - + @param description descriptive text (string) @param entryText text to show (string) @param entryVersion version string to show (string). @@ -489,25 +559,25 @@ font = itm.font(0) font.setBold(True) itm.setFont(0, font) - + if len(entryVersion): citm = QTreeWidgetItem(itm, [entryText, entryVersion]) itm.setExpanded(True) - citm.setData(0, self.ToolAvailableRole, - not entryVersion.startswith("(")) + citm.setData(0, self.ToolAvailableRole, not entryVersion.startswith("(")) # assume version starting with '(' is an unavailability else: itm.setText(1, self.tr("(not found)")) QApplication.processEvents() self.programsList.header().resizeSections( - QHeaderView.ResizeMode.ResizeToContents) + QHeaderView.ResizeMode.ResizeToContents + ) self.programsList.header().setStretchLastSection(True) - + @pyqtSlot(int) def on_showComboBox_currentIndexChanged(self, index): """ Private slot to apply the selected show criteria. - + @param index index of the show criterium @type int """