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()