Plugins/VcsPlugins/vcsSubversion/SvnDialog.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2003 - 2009 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 PyQt4.QtCore import *
13 from PyQt4.QtGui import *
14
15 from Ui_SvnDialog import Ui_SvnDialog
16
17 import Preferences
18
19 class SvnDialog(QDialog, Ui_SvnDialog):
20 """
21 Class implementing a dialog starting a process and showing its output.
22
23 It starts a QProcess and displays a dialog that
24 shows the output of the process. The dialog is modal,
25 which causes a synchronized execution of the process.
26 """
27 def __init__(self, text, parent = None):
28 """
29 Constructor
30
31 @param text text to be shown by the label (string)
32 @param parent parent widget (QWidget)
33 """
34 QDialog.__init__(self, parent)
35 self.setupUi(self)
36
37 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
38 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
39
40 self.proc = None
41 self.username = ''
42 self.password = ''
43
44 self.outputGroup.setTitle(text)
45
46 def __finish(self):
47 """
48 Private slot called when the process finished or the user pressed the button.
49 """
50 if self.proc is not None and \
51 self.proc.state() != QProcess.NotRunning:
52 self.proc.terminate()
53 QTimer.singleShot(2000, self.proc, SLOT('kill()'))
54 self.proc.waitForFinished(3000)
55
56 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
57 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
58 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
59
60 self.inputGroup.setEnabled(False)
61
62 self.proc = None
63
64 if Preferences.getVCS("AutoClose") and \
65 self.normal and \
66 self.errors.toPlainText() == "":
67 self.accept()
68
69 def on_buttonBox_clicked(self, button):
70 """
71 Private slot called by a button of the button box clicked.
72
73 @param button button that was clicked (QAbstractButton)
74 """
75 if button == self.buttonBox.button(QDialogButtonBox.Close):
76 self.close()
77 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
78 self.__finish()
79
80 def __procFinished(self, exitCode, exitStatus):
81 """
82 Private slot connected to the finished signal.
83
84 @param exitCode exit code of the process (integer)
85 @param exitStatus exit status of the process (QProcess.ExitStatus)
86 """
87 self.normal = (exitStatus == QProcess.NormalExit) and (exitCode == 0)
88 self.__finish()
89
90 def startProcess(self, args, workingDir = None):
91 """
92 Public slot used to start the process.
93
94 @param args list of arguments for the process (list of strings)
95 @param workingDir working directory for the process (string)
96 @return flag indicating a successful start of the process
97 """
98 self.errorGroup.hide()
99 self.normal = False
100 self.intercept = False
101
102 self.__hasAddOrDelete = False
103
104 self.proc = QProcess()
105 nargs = []
106 lastWasPwd = False
107 for arg in args:
108 if lastWasPwd:
109 lastWasPwd = True
110 continue
111 nargs.append(arg)
112 if arg == '--password':
113 lastWasPwd = True
114 nargs.append('*****')
115
116 self.resultbox.append(' '.join(nargs))
117 self.resultbox.append('')
118
119 self.connect(self.proc, SIGNAL('finished(int, QProcess::ExitStatus)'),
120 self.__procFinished)
121 self.connect(self.proc, SIGNAL('readyReadStandardOutput()'),
122 self.__readStdout)
123 self.connect(self.proc, SIGNAL('readyReadStandardError()'),
124 self.__readStderr)
125
126 if workingDir:
127 self.proc.setWorkingDirectory(workingDir)
128 self.proc.start('svn', args)
129 procStarted = self.proc.waitForStarted()
130 if not procStarted:
131 self.buttonBox.setFocus()
132 self.inputGroup.setEnabled(False)
133 QMessageBox.critical(None,
134 self.trUtf8('Process Generation Error'),
135 self.trUtf8(
136 'The process {0} could not be started. '
137 'Ensure, that it is in the search path.'
138 ).format('svn'))
139 else:
140 self.inputGroup.setEnabled(True)
141 return procStarted
142
143 def normalExit(self):
144 """
145 Public method to check for a normal process termination.
146
147 @return flag indicating normal process termination (boolean)
148 """
149 return self.normal
150
151 def __readStdout(self):
152 """
153 Private slot to handle the readyReadStdout signal.
154
155 It reads the output of the process, formats it and inserts it into
156 the contents pane.
157 """
158 if self.proc is not None:
159 s = unicode(self.proc.readAllStandardOutput())
160 self.resultbox.insertPlainText(s)
161 self.resultbox.ensureCursorVisible()
162 if not self.__hasAddOrDelete and len(s) > 0:
163 # check the output
164 for l in s.split(os.linesep):
165 if l[0].strip() in ['A', 'D']:
166 self.__hasAddOrDelete = True
167 break
168
169 def __readStderr(self):
170 """
171 Private slot to handle the readyReadStderr signal.
172
173 It reads the error output of the process and inserts it into the
174 error pane.
175 """
176 if self.proc is not None:
177 self.errorGroup.show()
178 s = unicode(self.proc.readAllStandardError())
179 self.errors.insertPlainText(s)
180 self.errors.ensureCursorVisible()
181
182 def on_passwordCheckBox_toggled(self, isOn):
183 """
184 Private slot to handle the password checkbox toggled.
185
186 @param isOn flag indicating the status of the check box (boolean)
187 """
188 if isOn:
189 self.input.setEchoMode(QLineEdit.Password)
190 else:
191 self.input.setEchoMode(QLineEdit.Normal)
192
193 @pyqtSlot()
194 def on_sendButton_clicked(self):
195 """
196 Private slot to send the input to the subversion process.
197 """
198 input = self.input.text()
199 input += os.linesep
200
201 if self.passwordCheckBox.isChecked():
202 self.errors.insertPlainText(os.linesep)
203 self.errors.ensureCursorVisible()
204 else:
205 self.errors.insertPlainText(input)
206 self.errors.ensureCursorVisible()
207
208 self.proc.write(input)
209
210 self.passwordCheckBox.setChecked(False)
211 self.input.clear()
212
213 def on_input_returnPressed(self):
214 """
215 Private slot to handle the press of the return key in the input field.
216 """
217 self.intercept = True
218 self.on_sendButton_clicked()
219
220 def keyPressEvent(self, evt):
221 """
222 Protected slot to handle a key press event.
223
224 @param evt the key press event (QKeyEvent)
225 """
226 if self.intercept:
227 self.intercept = False
228 evt.accept()
229 return
230 QDialog.keyPressEvent(self, evt)
231
232 def hasAddOrDelete(self):
233 """
234 Public method to check, if the last action contained an add or delete.
235 """
236 return self.__hasAddOrDelete

eric ide

mercurial