5 |
5 |
6 """ |
6 """ |
7 Module implementing a dialog to run the Flask server. |
7 Module implementing a dialog to run the Flask server. |
8 """ |
8 """ |
9 |
9 |
10 from PyQt5.QtCore import pyqtSlot, QProcess |
10 import re |
|
11 |
|
12 from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer |
11 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton |
13 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton |
12 |
14 |
13 from E5Gui import E5MessageBox |
15 from E5Gui import E5MessageBox |
14 |
16 |
15 from .Ui_RunServerDialog import Ui_RunServerDialog |
17 from .Ui_RunServerDialog import Ui_RunServerDialog |
29 super(RunServerDialog, self).__init__(parent) |
31 super(RunServerDialog, self).__init__(parent) |
30 self.setupUi(self) |
32 self.setupUi(self) |
31 |
33 |
32 self.__process = None |
34 self.__process = None |
33 |
35 |
|
36 self.__ansiRe = re.compile("(\\x1b\[\d+m)") |
|
37 |
34 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
38 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
35 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
39 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
36 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
40 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
|
41 |
|
42 self.__defaultTextFormat = self.outputEdit.currentCharFormat() |
37 |
43 |
38 def startServer(self, command, workdir, env): |
44 def startServer(self, command, workdir, env): |
39 """ |
45 """ |
40 Public method to start the Flask server process. |
46 Public method to start the Flask server process. |
41 |
47 |
46 @param env environment for the Flask server process |
52 @param env environment for the Flask server process |
47 @type QProcessEnvironment |
53 @type QProcessEnvironment |
48 @return flag indicating a successful start |
54 @return flag indicating a successful start |
49 @rtype bool |
55 @rtype bool |
50 """ |
56 """ |
51 self.errorsEdit.hide() |
|
52 |
|
53 self.__process = QProcess() |
57 self.__process = QProcess() |
54 self.__process.readyReadStandardOutput.connect(self.__readStdOut) |
|
55 self.__process.readyReadStandardError.connect(self.__readStdErr) |
|
56 self.__process.finished.connect(self.__processFinished) |
|
57 self.__process.setProcessEnvironment(env) |
58 self.__process.setProcessEnvironment(env) |
58 self.__process.setWorkingDirectory(workdir) |
59 self.__process.setWorkingDirectory(workdir) |
|
60 self.__process.setProcessChannelMode(QProcess.MergedChannels) |
|
61 |
|
62 self.__process.readyReadStandardOutput.connect(self.__readStdOut) |
|
63 self.__process.finished.connect(self.__processFinished) |
59 |
64 |
60 self.__process.start(command, ["run"]) |
65 self.__process.start(command, ["run"]) |
61 ok = self.__process.waitForStarted(10000) |
66 ok = self.__process.waitForStarted(10000) |
62 if not ok: |
67 if not ok: |
63 E5MessageBox.critical( |
68 E5MessageBox.critical( |
76 Private method handling a close event. |
81 Private method handling a close event. |
77 |
82 |
78 @param evt reference to the close event |
83 @param evt reference to the close event |
79 @type QCloseEvent |
84 @type QCloseEvent |
80 """ |
85 """ |
81 # TODO: not implemented yet |
86 self.__cancel() |
|
87 evt.accept() |
82 |
88 |
83 @pyqtSlot(QAbstractButton) |
89 @pyqtSlot(QAbstractButton) |
84 def on_buttonBox_clicked(self, button): |
90 def on_buttonBox_clicked(self, button): |
85 """ |
91 """ |
86 Private slot handling button presses. |
92 Private slot handling button presses. |
98 """ |
104 """ |
99 Private slot to add the server process output to the output pane. |
105 Private slot to add the server process output to the output pane. |
100 """ |
106 """ |
101 if self.__process is not None: |
107 if self.__process is not None: |
102 out = str(self.__process.readAllStandardOutput(), "utf-8") |
108 out = str(self.__process.readAllStandardOutput(), "utf-8") |
103 self.outputEdit.appendPlainText(out) |
109 for txt in self.__ansiRe.split(out): |
104 |
110 if txt.startswith("\x1b["): |
105 @pyqtSlot() |
111 # TODO: process ANSI escape sequences for coloring |
106 def __readStdErr(self): |
112 pass |
107 """ |
113 else: |
108 Private slot to add the server process errors to the errors pane. |
114 self.outputEdit.insertPlainText(txt) |
109 """ |
|
110 if self.__process is not None: |
|
111 err = str(self.__process.readAllStandardError(), "utf-8") |
|
112 self.errorsEdit.appendPlainText(err) |
|
113 |
|
114 self.errorsEdit.show() |
|
115 |
115 |
116 @pyqtSlot() |
116 @pyqtSlot() |
117 def __processFinished(self): |
117 def __processFinished(self): |
118 # TODO: implement it |
118 """ |
119 pass |
119 Private slot handling the finishing of the server process. |
|
120 """ |
|
121 if ( |
|
122 self.__process is not None and |
|
123 self.__process.state() != QProcess.NotRunning |
|
124 ): |
|
125 self.__process.terminate() |
|
126 QTimer.singleShot(2000, self.__process.kill) |
|
127 self.__process.waitForFinished(3000) |
|
128 |
|
129 self.__process = None |
|
130 |
|
131 |
|
132 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
|
133 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
|
134 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
|
135 self.buttonBox.button(QDialogButtonBox.Close).setFocus( |
|
136 Qt.OtherFocusReason) |
120 |
137 |
121 @pyqtSlot() |
138 @pyqtSlot() |
122 def __cancel(self): |
139 def __cancel(self): |
123 """ |
140 """ |
124 Private slot to cancel the running server. |
141 Private slot to cancel the running server. |
125 """ |
142 """ |
126 # TODO: not implemented yet |
143 self.__processFinished() |