src/eric7/Plugins/VcsPlugins/vcsSubversion/SvnDialog.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) 2003 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog starting a process and showing its output.
8 """
9
10 import os
11
12 from PyQt6.QtCore import QTimer, QProcess, pyqtSlot, Qt, QProcessEnvironment
13 from PyQt6.QtWidgets import QLineEdit, QDialog, QDialogButtonBox
14
15 from EricWidgets import EricMessageBox
16
17 from .Ui_SvnDialog import Ui_SvnDialog
18
19 import Preferences
20 from Globals import strToQByteArray
21
22
23 class SvnDialog(QDialog, Ui_SvnDialog):
24 """
25 Class implementing a dialog starting a process and showing its output.
26
27 It starts a QProcess and displays a dialog that
28 shows the output of the process. The dialog is modal,
29 which causes a synchronized execution of the process.
30 """
31 def __init__(self, text, parent=None):
32 """
33 Constructor
34
35 @param text text to be shown by the label (string)
36 @param parent parent widget (QWidget)
37 """
38 super().__init__(parent)
39 self.setupUi(self)
40 self.setWindowFlags(Qt.WindowType.Window)
41
42 self.buttonBox.button(
43 QDialogButtonBox.StandardButton.Close).setEnabled(False)
44 self.buttonBox.button(
45 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
46
47 self.process = None
48 self.username = ''
49 self.password = ''
50
51 self.outputGroup.setTitle(text)
52
53 def __finish(self):
54 """
55 Private slot called when the process finished or the user pressed the
56 button.
57 """
58 if (
59 self.process is not None and
60 self.process.state() != QProcess.ProcessState.NotRunning
61 ):
62 self.process.terminate()
63 QTimer.singleShot(2000, self.process.kill)
64 self.process.waitForFinished(3000)
65
66 self.buttonBox.button(
67 QDialogButtonBox.StandardButton.Close).setEnabled(True)
68 self.buttonBox.button(
69 QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
70 self.buttonBox.button(
71 QDialogButtonBox.StandardButton.Close).setDefault(True)
72
73 self.inputGroup.setEnabled(False)
74 self.inputGroup.hide()
75
76 self.process = None
77
78 self.buttonBox.button(
79 QDialogButtonBox.StandardButton.Close).setEnabled(True)
80 self.buttonBox.button(
81 QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
82 self.buttonBox.button(
83 QDialogButtonBox.StandardButton.Close).setDefault(True)
84 self.buttonBox.button(
85 QDialogButtonBox.StandardButton.Close).setFocus(
86 Qt.FocusReason.OtherFocusReason)
87
88 if (
89 Preferences.getVCS("AutoClose") and
90 self.normal and
91 self.errors.toPlainText() == ""
92 ):
93 self.accept()
94
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 (QAbstractButton)
100 """
101 if button == self.buttonBox.button(
102 QDialogButtonBox.StandardButton.Close
103 ):
104 self.close()
105 elif button == self.buttonBox.button(
106 QDialogButtonBox.StandardButton.Cancel
107 ):
108 self.__finish()
109
110 def __procFinished(self, exitCode, exitStatus):
111 """
112 Private slot connected to the finished signal.
113
114 @param exitCode exit code of the process (integer)
115 @param exitStatus exit status of the process (QProcess.ExitStatus)
116 """
117 self.normal = (
118 exitStatus == QProcess.ExitStatus.NormalExit and
119 exitCode == 0
120 )
121 self.__finish()
122
123 def startProcess(self, args, workingDir=None, setLanguage=False):
124 """
125 Public slot used to start the process.
126
127 @param args list of arguments for the process (list of strings)
128 @param workingDir working directory for the process (string)
129 @param setLanguage flag indicating to set the language to "C" (boolean)
130 @return flag indicating a successful start of the process
131 """
132 self.errorGroup.hide()
133 self.normal = False
134 self.intercept = False
135
136 self.__hasAddOrDelete = False
137
138 self.process = QProcess()
139 if setLanguage:
140 env = QProcessEnvironment.systemEnvironment()
141 env.insert("LANG", "C")
142 self.process.setProcessEnvironment(env)
143 nargs = []
144 lastWasPwd = False
145 for arg in args:
146 if lastWasPwd:
147 lastWasPwd = True
148 continue
149 nargs.append(arg)
150 if arg == '--password':
151 lastWasPwd = True
152 nargs.append('*****')
153
154 self.resultbox.append(' '.join(nargs))
155 self.resultbox.append('')
156
157 self.process.finished.connect(self.__procFinished)
158 self.process.readyReadStandardOutput.connect(self.__readStdout)
159 self.process.readyReadStandardError.connect(self.__readStderr)
160
161 if workingDir:
162 self.process.setWorkingDirectory(workingDir)
163 self.process.start('svn', args)
164 procStarted = self.process.waitForStarted(5000)
165 if not procStarted:
166 self.buttonBox.setFocus()
167 self.inputGroup.setEnabled(False)
168 self.inputGroup.hide()
169 EricMessageBox.critical(
170 self,
171 self.tr('Process Generation Error'),
172 self.tr(
173 'The process {0} could not be started. '
174 'Ensure, that it is in the search path.'
175 ).format('svn'))
176 else:
177 self.inputGroup.setEnabled(True)
178 self.inputGroup.show()
179 return procStarted
180
181 def normalExit(self):
182 """
183 Public method to check for a normal process termination.
184
185 @return flag indicating normal process termination (boolean)
186 """
187 return self.normal
188
189 def __readStdout(self):
190 """
191 Private slot to handle the readyReadStdout signal.
192
193 It reads the output of the process, formats it and inserts it into
194 the contents pane.
195 """
196 if self.process is not None:
197 s = str(self.process.readAllStandardOutput(),
198 Preferences.getSystem("IOEncoding"),
199 'replace')
200 self.resultbox.insertPlainText(s)
201 self.resultbox.ensureCursorVisible()
202 if not self.__hasAddOrDelete and len(s) > 0:
203 # check the output
204 for line in s.split(os.linesep):
205 if (
206 '.epj' in line or
207 '.e4p' in line
208 ):
209 self.__hasAddOrDelete = True
210 break
211 if line and line[0:2].strip() in ['A', 'D']:
212 self.__hasAddOrDelete = True
213 break
214
215 def __readStderr(self):
216 """
217 Private slot to handle the readyReadStderr signal.
218
219 It reads the error output of the process and inserts it into the
220 error pane.
221 """
222 if self.process is not None:
223 self.errorGroup.show()
224 s = str(self.process.readAllStandardError(),
225 Preferences.getSystem("IOEncoding"),
226 'replace')
227 self.errors.insertPlainText(s)
228 self.errors.ensureCursorVisible()
229
230 def on_passwordCheckBox_toggled(self, isOn):
231 """
232 Private slot to handle the password checkbox toggled.
233
234 @param isOn flag indicating the status of the check box (boolean)
235 """
236 if isOn:
237 self.input.setEchoMode(QLineEdit.EchoMode.Password)
238 else:
239 self.input.setEchoMode(QLineEdit.EchoMode.Normal)
240
241 @pyqtSlot()
242 def on_sendButton_clicked(self):
243 """
244 Private slot to send the input to the subversion process.
245 """
246 inputTxt = self.input.text()
247 inputTxt += os.linesep
248
249 if self.passwordCheckBox.isChecked():
250 self.errors.insertPlainText(os.linesep)
251 self.errors.ensureCursorVisible()
252 else:
253 self.errors.insertPlainText(inputTxt)
254 self.errors.ensureCursorVisible()
255
256 self.process.write(strToQByteArray(inputTxt))
257
258 self.passwordCheckBox.setChecked(False)
259 self.input.clear()
260
261 def on_input_returnPressed(self):
262 """
263 Private slot to handle the press of the return key in the input field.
264 """
265 self.intercept = True
266 self.on_sendButton_clicked()
267
268 def keyPressEvent(self, evt):
269 """
270 Protected slot to handle a key press event.
271
272 @param evt the key press event (QKeyEvent)
273 """
274 if self.intercept:
275 self.intercept = False
276 evt.accept()
277 return
278 super().keyPressEvent(evt)
279
280 def hasAddOrDelete(self):
281 """
282 Public method to check, if the last action contained an add or delete.
283
284 @return flag indicating the presence of an add or delete (boolean)
285 """
286 return self.__hasAddOrDelete

eric ide

mercurial