ProjectFlask/FlaskCommandDialog.py

changeset 9
79094fb72c18
child 11
da6ef8ab8268
diff -r cfbd3a2757fd -r 79094fb72c18 ProjectFlask/FlaskCommandDialog.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ProjectFlask/FlaskCommandDialog.py	Sat Nov 14 19:56:06 2020 +0100
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+
+"""
+Module implementing a dialog to run a flask command and show its output.
+"""
+
+from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
+
+from E5Gui import E5MessageBox
+
+from .Ui_FlaskCommandDialog import Ui_FlaskCommandDialog
+
+
+class FlaskCommandDialog(QDialog, Ui_FlaskCommandDialog):
+    """
+    Class implementing a dialog to run a flask command and show its output.
+    """
+    def __init__(self, project, parent=None):
+        """
+        Constructor
+        
+        @param project reference to the project object
+        @type Project
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(FlaskCommandDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.__project = project
+        
+        self.__process = None
+        
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
+    
+    def startCommand(self, command, args=None):
+        """
+        Public method to start a flask command and show its output.
+        
+        @param command flask command to be run
+        @type str
+        @param args list of command line arguments for the command
+        @type list of str
+        @return flag indicating a successful start
+        @rtype bool
+        """
+        workdir, env = self.__project.prepareRuntimeEnvironment()
+        if env is not None:
+            flaskCommand = self.__project.getFlaskCommand()
+            
+            self.__process = QProcess()
+            self.__process.setProcessEnvironment(env)
+            self.__process.setWorkingDirectory(workdir)
+            self.__process.setProcessChannelMode(QProcess.MergedChannels)
+            
+            self.__process.readyReadStandardOutput.connect(self.__readStdOut)
+            self.__process.finished.connect(self.__processFinished)
+            
+            self.outputEdit.clear()
+            
+            flaskArgs = [command]
+            if args:
+                flaskArgs += args
+            
+            self.__process.start(flaskCommand, flaskArgs)
+            ok = self.__process.waitForStarted(10000)
+            if not ok:
+                E5MessageBox.critical(
+                    None,
+                    self.tr("Execute Flask Command"),
+                    self.tr("""The Flask process could not be started."""))
+            else:
+                self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
+                self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
+                self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
+                self.buttonBox.button(QDialogButtonBox.Cancel).setFocus(
+                    Qt.OtherFocusReason)
+        else:
+            ok = False
+        
+        return ok
+    
+    def closeEvent(self, evt):
+        """
+        Protected method handling the close event of the dialog.
+        
+        @param evt reference to the close event object
+        @type QCloseEvent
+        """
+        self.__cancelProcess()
+        evt.accept()
+    
+    @pyqtSlot()
+    def __readStdOut(self):
+        """
+        Private slot to add the server process output to the output pane.
+        """
+        if self.__process is not None:
+            out = str(self.__process.readAllStandardOutput(), "utf-8")
+            self.outputEdit.insertPlainText(out)
+    
+    @pyqtSlot()
+    def __processFinished(self):
+        """
+        Private slot handling the finishing of the server process.
+        """
+        self.__cancelProcess()
+        
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+        self.buttonBox.button(QDialogButtonBox.Close).setFocus(
+            Qt.OtherFocusReason)
+    
+    @pyqtSlot()
+    def __cancelProcess(self):
+        """
+        Private slot to terminate the current process.
+        """
+        if (
+            self.__process is not None and
+            self.__process.state() != QProcess.NotRunning
+        ):
+            self.__process.terminate()
+            QTimer.singleShot(2000, self.__process.kill)
+            self.__process.waitForFinished(3000)
+        
+        self.__process = None
+    
+    @pyqtSlot(QAbstractButton)
+    def on_buttonBox_clicked(self, button):
+        """
+        Slot handling presses of the button box buttons.
+        
+        @param button reference to the button been clicked
+        @type QAbstractButton
+        """
+        if button is self.buttonBox.button(QDialogButtonBox.Close):
+            self.close()
+        elif button is self.buttonBox.button(QDialogButtonBox.Cancel):
+            self.__cancelProcess()

eric ide

mercurial