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