Tue, 10 Nov 2020 19:38:00 +0100
Continued implementing the "Run Server" function.
# -*- coding: utf-8 -*- # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a dialog to run the Flask server. """ import re from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton from E5Gui import E5MessageBox from .Ui_RunServerDialog import Ui_RunServerDialog class RunServerDialog(QDialog, Ui_RunServerDialog): """ Class implementing a dialog to run the Flask server. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget @type QWidget """ super(RunServerDialog, self).__init__(parent) self.setupUi(self) self.__process = None self.__ansiRe = re.compile("(\\x1b\[\d+m)") self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) self.__defaultTextFormat = self.outputEdit.currentCharFormat() def startServer(self, command, workdir, env): """ Public method to start the Flask server process. @param command path of the flask command @type str @param workdir working directory for the Flask server @type str @param env environment for the Flask server process @type QProcessEnvironment @return flag indicating a successful start @rtype bool """ 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.__process.start(command, ["run"]) ok = self.__process.waitForStarted(10000) if not ok: E5MessageBox.critical( None, self.tr("Run Flask Server"), self.tr("""The Flask server process could not be started.""")) else: self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) return ok def closeEvent(self, evt): """ Private method handling a close event. @param evt reference to the close event @type QCloseEvent """ self.__cancel() evt.accept() @pyqtSlot(QAbstractButton) def on_buttonBox_clicked(self, button): """ Private slot handling button presses. @param button button that was pressed @type QAbstractButton """ if button is self.buttonBox.button(QDialogButtonBox.Cancel): self.__cancel() elif button is self.buttonBox.button(QDialogButtonBox.Close): self.close() @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") for txt in self.__ansiRe.split(out): if txt.startswith("\x1b["): # TODO: process ANSI escape sequences for coloring pass else: self.outputEdit.insertPlainText(txt) @pyqtSlot() def __processFinished(self): """ Private slot handling the finishing of the server 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 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) self.buttonBox.button(QDialogButtonBox.Close).setFocus( Qt.OtherFocusReason) @pyqtSlot() def __cancel(self): """ Private slot to cancel the running server. """ self.__processFinished()