src/eric7/PipInterface/PipDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
5 5
6 """ 6 """
7 Module implementing a dialog showing the output of a pip command. 7 Module implementing a dialog showing the output of a pip command.
8 """ 8 """
9 9
10 from PyQt6.QtCore import ( 10 from PyQt6.QtCore import pyqtSlot, Qt, QCoreApplication, QTimer, QProcess
11 pyqtSlot, Qt, QCoreApplication, QTimer, QProcess
12 )
13 from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton 11 from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
14 12
15 from EricWidgets import EricMessageBox 13 from EricWidgets import EricMessageBox
16 14
17 from .Ui_PipDialog import Ui_PipDialog 15 from .Ui_PipDialog import Ui_PipDialog
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()

eric ide

mercurial