Plugins/VcsPlugins/vcsSubversion/SvnBlameDialog.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 to show the output of the svn blame command.
8 """
9
10 import sys
11
12 from PyQt4.QtCore import *
13 from PyQt4.QtGui import *
14
15 from Ui_SvnBlameDialog import Ui_SvnBlameDialog
16
17 import Preferences
18 import Utilities
19
20 class SvnBlameDialog(QDialog, Ui_SvnBlameDialog):
21 """
22 Class implementing a dialog to show the output of the svn blame command.
23 """
24 def __init__(self, vcs, parent = None):
25 """
26 Constructor
27
28 @param vcs reference to the vcs object
29 @param parent parent widget (QWidget)
30 """
31 QDialog.__init__(self, parent)
32 self.setupUi(self)
33
34 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
35 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
36
37 self.process = QProcess()
38 self.vcs = vcs
39
40 self.blameList.headerItem().setText(self.blameList.columnCount(), "")
41 font = QFont(self.blameList.font())
42 if Utilities.isWindowsPlatform():
43 font.setFamily("Lucida Console")
44 else:
45 font.setFamily("Monospace")
46 self.blameList.setFont(font)
47
48 self.__ioEncoding = Preferences.getSystem("IOEncoding")
49
50 self.connect(self.process, SIGNAL('finished(int, QProcess::ExitStatus)'),
51 self.__procFinished)
52 self.connect(self.process, SIGNAL('readyReadStandardOutput()'),
53 self.__readStdout)
54 self.connect(self.process, SIGNAL('readyReadStandardError()'),
55 self.__readStderr)
56
57 def closeEvent(self, e):
58 """
59 Private slot implementing a close event handler.
60
61 @param e close event (QCloseEvent)
62 """
63 if self.process is not None and \
64 self.process.state() != QProcess.NotRunning:
65 self.process.terminate()
66 QTimer.singleShot(2000, self.process, SLOT('kill()'))
67 self.process.waitForFinished(3000)
68
69 e.accept()
70
71 def start(self, fn):
72 """
73 Public slot to start the svn status command.
74
75 @param fn filename to show the log for (string)
76 """
77 self.errorGroup.hide()
78 self.intercept = False
79 self.activateWindow()
80 self.lineno = 1
81
82 dname, fname = self.vcs.splitPath(fn)
83
84 self.process.kill()
85
86 args = []
87 args.append('blame')
88 self.vcs.addArguments(args, self.vcs.options['global'])
89 args.append(fname)
90
91
92 self.process.setWorkingDirectory(dname)
93
94 self.process.start('svn', args)
95 procStarted = self.process.waitForStarted()
96 if not procStarted:
97 self.inputGroup.setEnabled(False)
98 QMessageBox.critical(None,
99 self.trUtf8('Process Generation Error'),
100 self.trUtf8(
101 'The process {0} could not be started. '
102 'Ensure, that it is in the search path.'
103 ).format('svn'))
104 else:
105 self.inputGroup.setEnabled(True)
106
107 def __finish(self):
108 """
109 Private slot called when the process finished or the user pressed the button.
110 """
111 if self.process is not None and \
112 self.process.state() != QProcess.NotRunning:
113 self.process.terminate()
114 QTimer.singleShot(2000, self.process, SLOT('kill()'))
115 self.process.waitForFinished(3000)
116
117 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
118 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
119 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
120
121 self.inputGroup.setEnabled(False)
122
123 self.process = None
124
125 self.blameList.doItemsLayout()
126 self.__resizeColumns()
127
128 def on_buttonBox_clicked(self, button):
129 """
130 Private slot called by a button of the button box clicked.
131
132 @param button button that was clicked (QAbstractButton)
133 """
134 if button == self.buttonBox.button(QDialogButtonBox.Close):
135 self.close()
136 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
137 self.__finish()
138
139 def __procFinished(self, exitCode, exitStatus):
140 """
141 Private slot connected to the finished signal.
142
143 @param exitCode exit code of the process (integer)
144 @param exitStatus exit status of the process (QProcess.ExitStatus)
145 """
146 self.__finish()
147
148 def __resizeColumns(self):
149 """
150 Private method to resize the list columns.
151 """
152 self.blameList.header().resizeSections(QHeaderView.ResizeToContents)
153 self.blameList.header().setStretchLastSection(True)
154
155 def __generateItem(self, revision, author, text):
156 """
157 Private method to generate a tag item in the taglist.
158
159 @param revision revision string (string)
160 @param author author of the tag (string)
161 @param date date of the tag (string)
162 @param name name (path) of the tag (string)
163 """
164 itm = QTreeWidgetItem(self.blameList,
165 [revision, author, "%d" % self.lineno, text])
166 self.lineno += 1
167 itm.setTextAlignment(0, Qt.AlignRight)
168 itm.setTextAlignment(2, Qt.AlignRight)
169
170 def __readStdout(self):
171 """
172 Private slot to handle the readyReadStdout signal.
173
174 It reads the output of the process, formats it and inserts it into
175 the contents pane.
176 """
177 self.process.setReadChannel(QProcess.StandardOutput)
178
179 while self.process.canReadLine():
180 s = unicode(self.process.readLine(), self.__ioEncoding, 'replace').strip()
181 rev, s = s.split(None, 1)
182 try:
183 author, text = s.split(' ', 1)
184 except ValueError:
185 author = s.strip()
186 text = ""
187 self.__generateItem(rev, author, text)
188
189 def __readStderr(self):
190 """
191 Private slot to handle the readyReadStderr signal.
192
193 It reads the error output of the process and inserts it into the
194 error pane.
195 """
196 if self.process is not None:
197 self.errorGroup.show()
198 s = unicode(self.process.readAllStandardError())
199 self.errors.insertPlainText(s)
200 self.errors.ensureCursorVisible()
201
202 def on_passwordCheckBox_toggled(self, isOn):
203 """
204 Private slot to handle the password checkbox toggled.
205
206 @param isOn flag indicating the status of the check box (boolean)
207 """
208 if isOn:
209 self.input.setEchoMode(QLineEdit.Password)
210 else:
211 self.input.setEchoMode(QLineEdit.Normal)
212
213 @pyqtSlot()
214 def on_sendButton_clicked(self):
215 """
216 Private slot to send the input to the subversion process.
217 """
218 input = self.input.text()
219 input += os.linesep
220
221 if self.passwordCheckBox.isChecked():
222 self.errors.insertPlainText(os.linesep)
223 self.errors.ensureCursorVisible()
224 else:
225 self.errors.insertPlainText(input)
226 self.errors.ensureCursorVisible()
227
228 self.process.write(input)
229
230 self.passwordCheckBox.setChecked(False)
231 self.input.clear()
232
233 def on_input_returnPressed(self):
234 """
235 Private slot to handle the press of the return key in the input field.
236 """
237 self.intercept = True
238 self.on_sendButton_clicked()
239
240 def keyPressEvent(self, evt):
241 """
242 Protected slot to handle a key press event.
243
244 @param evt the key press event (QKeyEvent)
245 """
246 if self.intercept:
247 self.intercept = False
248 evt.accept()
249 return
250 QDialog.keyPressEvent(self, evt)

eric ide

mercurial