ProjectFlask/FlaskBabelExtension/PyBabelCommandDialog.py

changeset 17
f31df56510a1
parent 16
dd3f6bfb85f7
child 60
02243723ac17
equal deleted inserted replaced
16:dd3f6bfb85f7 17:f31df56510a1
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to run a flask command and show its output.
8 """
9
10 from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer
11 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
12
13 from E5Gui import E5MessageBox
14
15 from ..Ui_FlaskCommandDialog import Ui_FlaskCommandDialog
16
17
18 class PyBabelCommandDialog(QDialog, Ui_FlaskCommandDialog):
19 """
20 Class implementing a dialog to run a flask command and show its output.
21 """
22 def __init__(self, project, title="", msgSuccess="", msgError="",
23 parent=None):
24 """
25 Constructor
26
27 @param project reference to the project object
28 @type Project
29 @param title window title of the dialog
30 @type str
31 @param msgSuccess success message to be shown
32 @type str
33 @param msgError message to be shown on error
34 @type str
35 @param parent reference to the parent widget
36 @type QWidget
37 """
38 super(PyBabelCommandDialog, self).__init__(parent)
39 self.setupUi(self)
40
41 if title:
42 self.setWindowTitle(title)
43
44 self.__project = project
45 self.__successMessage = msgSuccess
46 self.__errorMessage = msgError
47
48 self.__process = None
49 self.__argsLists = []
50 self.__workdir = ""
51
52 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
53 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
54 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
55
56 def startCommand(self, command, args, workdir, clearOutput=True):
57 """
58 Public method to start a pybabel command and show its output.
59
60 @param command pybabel command to be run
61 @type str
62 @param args list of command line arguments for the command
63 @type list of str
64 @param workdir working directory for the command
65 @type str
66 @param clearOutput flag indicating to clear the output
67 @type bool
68 @return flag indicating a successful start
69 @rtype bool
70 """
71 babelCommand = self.__project.getBabelCommand()
72
73 self.__process = QProcess()
74 self.__process.setWorkingDirectory(workdir)
75 self.__process.setProcessChannelMode(QProcess.MergedChannels)
76
77 self.__process.readyReadStandardOutput.connect(self.__readStdOut)
78 self.__process.finished.connect(self.__processFinished)
79
80 if clearOutput:
81 self.outputEdit.clear()
82
83 babelArgs = [command]
84 if args:
85 babelArgs += args
86
87 self.__process.start(babelCommand, babelArgs)
88 ok = self.__process.waitForStarted(10000)
89 if not ok:
90 E5MessageBox.critical(
91 None,
92 self.tr("Execute PyBabel Command"),
93 self.tr("""The pybabel process could not be started."""))
94 else:
95 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
96 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
97 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
98 self.buttonBox.button(QDialogButtonBox.Cancel).setFocus(
99 Qt.OtherFocusReason)
100
101 return ok
102
103 def startBatchCommand(self, argsLists, workdir):
104 """
105 Public method to start a pybabel command repeatedly with a list of
106 arguments and show the output.
107
108 @param argsLists list of command line arguments for the batch commands
109 @type list of lists of str
110 @param workdir working directory for the command
111 @type str
112 @return flag indicating a successful start of the first process
113 @rtype bool
114 """
115 self.__argsLists = argsLists[:]
116 self.__workdir = workdir
117
118 # start the first process
119 args = self.__argsLists.pop(0)
120 res = self.startCommand(args[0], args[1:], workdir)
121 if not res:
122 self.__argsLists = []
123
124 return res
125
126 def closeEvent(self, evt):
127 """
128 Protected method handling the close event of the dialog.
129
130 @param evt reference to the close event object
131 @type QCloseEvent
132 """
133 self.__argsLists = []
134 self.__cancelProcess()
135 evt.accept()
136
137 @pyqtSlot()
138 def __readStdOut(self):
139 """
140 Private slot to add the server process output to the output pane.
141 """
142 if self.__process is not None:
143 out = str(self.__process.readAllStandardOutput(), "utf-8")
144 self.outputEdit.insertPlainText(out)
145
146 def __processFinished(self, exitCode, exitStatus):
147 """
148 Private slot connected to the finished signal.
149
150 @param exitCode exit code of the process
151 @type int
152 @param exitStatus exit status of the process
153 @type QProcess.ExitStatus
154 """
155 normal = (exitStatus == QProcess.NormalExit) and (exitCode == 0)
156 self.__cancelProcess()
157
158 if self.__argsLists:
159 args = self.__argsLists.pop(0)
160 self.startCommand(args[0], args[1:], self.__workdir,
161 clearOutput=False)
162 return
163
164 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
165 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
166 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
167 self.buttonBox.button(QDialogButtonBox.Close).setFocus(
168 Qt.OtherFocusReason)
169
170 if normal and self.__successMessage:
171 self.outputEdit.insertPlainText(self.__successMessage)
172 elif not normal and self.__errorMessage:
173 self.outputEdit.insertPlainText(self.__errorMessage)
174
175 @pyqtSlot()
176 def __cancelProcess(self):
177 """
178 Private slot to terminate the current process.
179 """
180 if (
181 self.__process is not None and
182 self.__process.state() != QProcess.NotRunning
183 ):
184 self.__process.terminate()
185 QTimer.singleShot(2000, self.__process.kill)
186 self.__process.waitForFinished(3000)
187
188 self.__process = None
189
190 @pyqtSlot(QAbstractButton)
191 def on_buttonBox_clicked(self, button):
192 """
193 Private slot handling presses of the button box buttons.
194
195 @param button reference to the button been clicked
196 @type QAbstractButton
197 """
198 if button is self.buttonBox.button(QDialogButtonBox.Close):
199 self.close()
200 elif button is self.buttonBox.button(QDialogButtonBox.Cancel):
201 self.__argsLists = []
202 self.__cancelProcess()

eric ide

mercurial