Plugins/UiExtensionPlugins/PipInterface/PipDialog.py

branch
maintenance
changeset 6826
c6dda2cbe081
parent 6764
d14ddbfbbd36
parent 6825
e659bb96cdfa
child 6827
14680839ad7a
equal deleted inserted replaced
6764:d14ddbfbbd36 6826:c6dda2cbe081
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog showing the output of a pip command.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode # __IGNORE_EXCEPTION__
13 except NameError:
14 pass
15
16 from PyQt5.QtCore import pyqtSlot, Qt, QCoreApplication, QTimer, \
17 QProcess
18 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
19
20 from E5Gui import E5MessageBox
21
22 from .Ui_PipDialog import Ui_PipDialog
23
24 import Preferences
25
26
27 class PipDialog(QDialog, Ui_PipDialog):
28 """
29 Class implementing a dialog showing the output of a 'python -m pip'
30 command.
31 """
32 def __init__(self, text, parent=None):
33 """
34 Constructor
35
36 @param text text to be shown by the label
37 @type str
38 @param parent reference to the parent widget
39 @type QWidget
40 """
41 super(PipDialog, self).__init__(parent)
42 self.setupUi(self)
43
44 self.proc = None
45 self.__processQueue = []
46 self.__ioEncoding = Preferences.getSystem("IOEncoding")
47
48 self.outputGroup.setTitle(text)
49
50 self.show()
51 QCoreApplication.processEvents()
52
53 def closeEvent(self, e):
54 """
55 Protected slot implementing a close event handler.
56
57 @param e close event
58 @type QCloseEvent
59 """
60 self.__processQueue = []
61
62 if self.proc is not None and \
63 self.proc.state() != QProcess.NotRunning:
64 self.proc.terminate()
65 QTimer.singleShot(2000, self.proc.kill)
66 self.proc.waitForFinished(3000)
67
68 self.proc = None
69
70 e.accept()
71
72 def __finish(self):
73 """
74 Private slot called when the process finished or the user pressed
75 the button.
76 """
77 if self.proc is not None and \
78 self.proc.state() != QProcess.NotRunning:
79 self.proc.terminate()
80 QTimer.singleShot(2000, self.proc.kill)
81 self.proc.waitForFinished(3000)
82
83 self.proc = None
84
85 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
86 self.buttonBox.button(QDialogButtonBox.Close).setFocus(
87 Qt.OtherFocusReason)
88
89 if self.__processQueue:
90 cmd, args = self.__processQueue.pop(0)
91 self.__addOutput("\n\n")
92 self.startProcess(cmd, args)
93
94 @pyqtSlot(QAbstractButton)
95 def on_buttonBox_clicked(self, button):
96 """
97 Private slot called by a button of the button box clicked.
98
99 @param button button that was clicked
100 @type QAbstractButton
101 """
102 if button == self.buttonBox.button(QDialogButtonBox.Close):
103 self.close()
104
105 def __procFinished(self, exitCode, exitStatus):
106 """
107 Private slot connected to the finished signal.
108
109 @param exitCode exit code of the process
110 @type int
111 @param exitStatus exit status of the process
112 @type QProcess.ExitStatus
113 """
114 self.__finish()
115
116 def startProcess(self, cmd, args, showArgs=True):
117 """
118 Public slot used to start the process.
119
120 @param cmd name of the pip executable to be used
121 @type str
122 @param args list of arguments for the process
123 @type list of str
124 @keyparam showArgs flag indicating to show the arguments
125 @type bool
126 @return flag indicating a successful start of the process
127 @rtype bool
128 """
129 if len(self.errors.toPlainText()) == 0:
130 self.errorGroup.hide()
131
132 if showArgs:
133 self.resultbox.append(cmd + ' ' + ' '.join(args))
134 self.resultbox.append('')
135
136 self.proc = QProcess()
137 self.proc.finished.connect(self.__procFinished)
138 self.proc.readyReadStandardOutput.connect(self.__readStdout)
139 self.proc.readyReadStandardError.connect(self.__readStderr)
140 self.proc.start(cmd, args)
141 procStarted = self.proc.waitForStarted(5000)
142 if not procStarted:
143 self.buttonBox.setFocus()
144 E5MessageBox.critical(
145 self,
146 self.tr('Process Generation Error'),
147 self.tr(
148 'The process {0} could not be started.'
149 ).format(cmd))
150 return procStarted
151
152 def startProcesses(self, processParams):
153 """
154 Public method to issue a list of commands to be executed.
155
156 @param processParams list of tuples containing the command
157 and arguments
158 @type list of tuples of (str, list of str)
159 @return flag indicating a successful start of the first process
160 @rtype bool
161 """
162 if len(processParams) > 1:
163 for cmd, args in processParams[1:]:
164 self.__processQueue.append((cmd, args[:]))
165 cmd, args = processParams[0]
166 return self.startProcess(cmd, args)
167
168 def __readStdout(self):
169 """
170 Private slot to handle the readyReadStandardOutput signal.
171
172 It reads the output of the process, formats it and inserts it into
173 the contents pane.
174 """
175 if self.proc is not None:
176 txt = str(self.proc.readAllStandardOutput(),
177 self.__ioEncoding, 'replace')
178 self.__addOutput(txt)
179
180 def __addOutput(self, txt):
181 """
182 Private method to add some text to the output pane.
183
184 @param txt text to be added
185 @type str
186 """
187 self.resultbox.insertPlainText(txt)
188 self.resultbox.ensureCursorVisible()
189 QCoreApplication.processEvents()
190
191 def __readStderr(self):
192 """
193 Private slot to handle the readyReadStandardError signal.
194
195 It reads the error output of the process and inserts it into the
196 error pane.
197 """
198 if self.proc is not None:
199 s = str(self.proc.readAllStandardError(),
200 self.__ioEncoding, 'replace')
201 self.errorGroup.show()
202 self.errors.insertPlainText(s)
203 self.errors.ensureCursorVisible()
204
205 QCoreApplication.processEvents()

eric ide

mercurial