src/eric7/PipInterface/PipDialog.py

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

eric ide

mercurial