--- a/ProjectPyramid/PyramidDialog.py Thu Dec 30 12:17:44 2021 +0100 +++ b/ProjectPyramid/PyramidDialog.py Wed Sep 21 16:24:54 2022 +0200 @@ -23,17 +23,25 @@ class PyramidDialog(QDialog, Ui_PyramidDialog): """ Class implementing a dialog starting a process and showing its output. - + It starts a QProcess and displays a dialog that shows the output of the process. The dialog is modal, which causes a synchronized execution of the process. """ - def __init__(self, text, fixed=False, linewrap=True, - msgSuccess=None, msgError=None, - combinedOutput=False, parent=None): + + def __init__( + self, + text, + fixed=False, + linewrap=True, + msgSuccess=None, + msgError=None, + combinedOutput=False, + parent=None, + ): """ Constructor - + @param text text to be shown by the label @type str @param fixed flag indicating a fixed font should be used @@ -52,12 +60,10 @@ """ super().__init__(parent) self.setupUi(self) - - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setEnabled(False) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setDefault(True) - + + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) + self.__proc = None self.__argsLists = [] self.__workingDir = None @@ -65,9 +71,9 @@ self.__msgError = msgError self.__combinedOutput = combinedOutput self.__batchMode = False - + self.outputGroup.setTitle(text) - + if fixed: if isWindowsPlatform(): self.resultbox.setFontFamily("Lucida Console") @@ -75,86 +81,76 @@ self.resultbox.setFontFamily("Menlo") else: self.resultbox.setFontFamily("Monospace") - + if not linewrap: self.resultbox.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap) - + self.show() QCoreApplication.processEvents() - + def finish(self): """ Public slot called when the process finished or the user pressed the button. """ if ( - self.__proc is not None and - self.__proc.state() != QProcess.ProcessState.NotRunning + self.__proc is not None + and self.__proc.state() != QProcess.ProcessState.NotRunning ): self.__proc.terminate() QTimer.singleShot(2000, self.__proc.kill) self.__proc.waitForFinished(3000) - + self.inputGroup.setEnabled(False) self.inputGroup.hide() - + self.__proc = None - - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setEnabled(True) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setEnabled(False) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setDefault(True) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setFocus( - Qt.FocusReason.OtherFocusReason) - + + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True) + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setFocus( + Qt.FocusReason.OtherFocusReason + ) + if self.__argsLists: args = self.__argsLists.pop(0)[:] self.startProcess(args[0], args[1:], self.__workingDir) - + def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. - + @param button button that was clicked @type QAbstractButton """ - if button == self.buttonBox.button( - QDialogButtonBox.StandardButton.Close - ): + if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): self.close() - elif button == self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel - ): + elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): self.finish() - + def __procFinished(self, exitCode, exitStatus): """ Private slot connected to the finished signal. - + @param exitCode exit code of the process @type int @param exitStatus exit status of the process @type QProcess.ExitStatus """ - self.normal = ( - exitStatus == QProcess.ExitStatus.NormalExit and - exitCode == 0 - ) + self.normal = exitStatus == QProcess.ExitStatus.NormalExit and exitCode == 0 self.finish() - + if self.normal and self.__msgSuccess: self.resultbox.insertPlainText(self.__msgSuccess) elif not self.normal and self.__msgError: self.resultbox.insertPlainText(self.__msgError) self.resultbox.ensureCursorVisible() - + def startProcess(self, command, args, workingDir=None, showArgs=True): """ Public slot used to start the process. - + @param command command to start @type str @param args list of arguments for the process @@ -169,33 +165,31 @@ self.errorGroup.hide() self.normal = False self.intercept = False - - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setEnabled(False) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setEnabled(True) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setDefault(True) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setFocus( - Qt.FocusReason.OtherFocusReason) - + + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setFocus( + Qt.FocusReason.OtherFocusReason + ) + if self.__batchMode: - self.resultbox.append(80 * '#') - + self.resultbox.append(80 * "#") + if showArgs: - self.resultbox.append(command + ' ' + ' '.join(args)) - self.resultbox.append('') - + self.resultbox.append(command + " " + " ".join(args)) + self.resultbox.append("") + self.__proc = QProcess() if self.__combinedOutput: self.__proc.setProcessChannelMode( - QProcess.ProcessChannelMode.MergedChannels) - + QProcess.ProcessChannelMode.MergedChannels + ) + self.__proc.finished.connect(self.__procFinished) self.__proc.readyReadStandardOutput.connect(self.__readStdout) self.__proc.readyReadStandardError.connect(self.__readStderr) - + if workingDir: self.__proc.setWorkingDirectory(workingDir) self.__proc.start(command, args) @@ -205,20 +199,21 @@ self.inputGroup.setEnabled(False) EricMessageBox.critical( self, - self.tr('Process Generation Error'), + self.tr("Process Generation Error"), self.tr( - 'The process {0} could not be started. ' - 'Ensure, that it is in the search path.' - ).format(command)) + "The process {0} could not be started. " + "Ensure, that it is in the search path." + ).format(command), + ) else: self.inputGroup.setEnabled(True) self.inputGroup.show() return procStarted - + def startBatchProcesses(self, argsLists, workingDir=None): """ Public slot used to start a batch of processes. - + @param argsLists list of lists of arguments for the processes @type list of list of str @param workingDir working directory for the process @@ -229,71 +224,75 @@ self.__argsLists = argsLists[:] self.__workingDir = workingDir self.__batchMode = True - + # start the first process args = self.__argsLists.pop(0)[:] res = self.startProcess(args[0], args[1:], self.__workingDir) if not res: self.__argsLists = [] - + return res - + def normalExit(self): """ Public method to check for a normal process termination. - + @return flag indicating normal process termination @rtype bool """ return self.normal - + def normalExitWithoutErrors(self): """ Public method to check for a normal process termination without error messages. - + @return flag indicating normal process termination @rtype bool """ return self.normal and self.errors.toPlainText() == "" - + def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal. - + It reads the output of the process, formats it and inserts it into the contents pane. """ if self.__proc is not None: - out = str(self.__proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace') + out = str( + self.__proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + "replace", + ) self.resultbox.insertPlainText(out) self.resultbox.ensureCursorVisible() - + QCoreApplication.processEvents() - + def __readStderr(self): """ Private slot to handle the readyReadStandardError signal. - + It reads the error output of the process and inserts it into the error pane. """ if self.__proc is not None: - err = str(self.__proc.readAllStandardError(), - Preferences.getSystem("IOEncoding"), - 'replace') + err = str( + self.__proc.readAllStandardError(), + Preferences.getSystem("IOEncoding"), + "replace", + ) self.errorGroup.show() self.errors.insertPlainText(err) self.errors.ensureCursorVisible() - + QCoreApplication.processEvents() - + def on_passwordCheckBox_toggled(self, isOn): """ Private slot to handle the password checkbox toggled. - + @param isOn flag indicating the status of the check box @type bool """ @@ -301,7 +300,7 @@ self.input.setEchoMode(QLineEdit.EchoMode.Password) else: self.input.setEchoMode(QLineEdit.EchoMode.Normal) - + @pyqtSlot() def on_sendButton_clicked(self): """ @@ -309,30 +308,30 @@ """ inputTxt = self.input.text() inputTxt += os.linesep - + if self.passwordCheckBox.isChecked(): self.errors.insertPlainText(os.linesep) self.errors.ensureCursorVisible() else: self.resultbox.insertPlainText(inputTxt) self.resultbox.ensureCursorVisible() - + self.__proc.write(strToQByteArray(inputTxt)) - + self.passwordCheckBox.setChecked(False) self.input.clear() - + def on_input_returnPressed(self): """ Private slot to handle the press of the return key in the input field. """ self.intercept = True self.on_sendButton_clicked() - + def keyPressEvent(self, evt): """ Protected slot to handle a key press event. - + @param evt the key press event @type QKeyEvent """