PipxInterface/PipxAppStartDialog.py

changeset 4
097a06104774
child 7
9a98f7260372
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PipxInterface/PipxAppStartDialog.py	Mon Jun 24 19:48:46 2024 +0200
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+
+"""
+Module implementing a dialog to enter the application command line parameters and
+to execute the app.
+"""
+
+import os
+import shlex
+
+from PyQt6.QtCore import QCoreApplication, QProcess, Qt, QTimer, pyqtSlot
+from PyQt6.QtWidgets import QAbstractButton, QDialog, QDialogButtonBox
+
+from eric7 import Preferences
+from eric7.EricGui import EricPixmapCache
+from eric7.EricWidgets import EricMessageBox
+
+from .Ui_PipxAppStartDialog import Ui_PipxAppStartDialog
+
+
+class PipxAppStartDialog(QDialog, Ui_PipxAppStartDialog):
+    """
+    Class implementing a dialog to enter the application command line parameters and
+    to execute the app.
+    """
+
+    def __init__(self, app, parent=None):
+        """
+        Constructor
+
+        @param app path of the application to be executed
+        @type str
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        self.executeButton.setIcon(EricPixmapCache.getIcon("start"))
+
+        self.__process = None
+
+        self.appLabel.setText(app)
+        self.errorGroup.hide()
+
+        self.parametersEdit.returnPressed.connect(self.on_executeButton_clicked)
+
+    def closeEvent(self, e):
+        """
+        Protected slot implementing a close event handler.
+
+        @param e close event
+        @type QCloseEvent
+        """
+        self.__cancel()
+        e.accept()
+
+    def __finish(self):
+        """
+        Private slot called when the process finished or the user pressed
+        the button.
+        """
+        if (
+            self.__process is not None
+            and self.__process.state() != QProcess.ProcessState.NotRunning
+        ):
+            self.__process.terminate()
+            QTimer.singleShot(2000, self.__process.kill)
+            self.__process.waitForFinished(3000)
+
+        self.__process = None
+
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
+        self.executeButton.setEnabled(True)
+
+        self.parametersEdit.setFocus(Qt.FocusReason.OtherFocusReason)
+        self.parametersEdit.selectAll()
+
+    def __cancel(self):
+        """
+        Private slot to cancel the current action.
+        """
+        self.__finish()
+
+    @pyqtSlot(QAbstractButton)
+    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):
+            self.close()
+        elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel):
+            self.__cancel()
+
+    @pyqtSlot(int, QProcess.ExitStatus)
+    def __procFinished(self, _exitCode, _exitStatus):
+        """
+        Private slot connected to the finished signal.
+
+        @param _exitCode exit code of the process (unused)
+        @type int
+        @param _exitStatus exit status of the process (unused)
+        @type QProcess.ExitStatus
+        """
+        self.__finish()
+
+    @pyqtSlot()
+    def on_executeButton_clicked(self):
+        """
+        Private slot to execute the selected app with the entered parameters.
+        """
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
+        self.executeButton.setEnabled(False)
+
+        command = self.parametersEdit.text()
+        args = shlex.split(command)
+
+        self.__process = QProcess()
+        self.__process.finished.connect(self.__procFinished)
+        self.__process.readyReadStandardOutput.connect(self.__readStdout)
+        self.__process.readyReadStandardError.connect(self.__readStderr)
+        self.__process.start(self.appLabel.text(), args)
+        procStarted = self.__process.waitForStarted(5000)
+        if not procStarted:
+            self.buttonBox.setFocus()
+            EricMessageBox.critical(
+                self,
+                self.tr("Process Generation Error"),
+                self.tr("The process {0} could not be started.").format(
+                    os.path.basename(self.appLabel.text())
+                ),
+            )
+
+    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.__process is not None:
+            txt = str(
+                self.__process.readAllStandardOutput(),
+                Preferences.getSystem("IOEncoding"),
+                "replace",
+            )
+            self.__addOutput(txt)
+
+    def __addOutput(self, txt):
+        """
+        Private method to add some text to the output pane.
+
+        @param txt text to be added
+        @type str
+        """
+        self.resultbox.insertPlainText(txt)
+        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.__process is not None:
+            s = str(
+                self.__process.readAllStandardError(),
+                Preferences.getSystem("IOEncoding"),
+                "replace",
+            )
+            self.errorGroup.show()
+            self.errors.insertPlainText(s)
+            self.errors.ensureCursorVisible()
+
+            QCoreApplication.processEvents()

eric ide

mercurial