Plugins/VcsPlugins/vcsSubversion/SvnChangeListsDialog.py

changeset 1888
03f59d88a62d
child 2302
f29e9405c851
equal deleted inserted replaced
1886:732f94385668 1888:03f59d88a62d
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to browse the change lists.
8 """
9
10 import os
11
12 from PyQt4.QtCore import pyqtSlot, Qt, QProcess, QRegExp, QTimer
13 from PyQt4.QtGui import QDialog, QDialogButtonBox, QListWidgetItem, QLineEdit
14
15 from E5Gui import E5MessageBox
16
17 from .Ui_SvnChangeListsDialog import Ui_SvnChangeListsDialog
18
19 import Preferences
20
21
22 class SvnChangeListsDialog(QDialog, Ui_SvnChangeListsDialog):
23 """
24 Class implementing a dialog to browse the change lists.
25 """
26 def __init__(self, vcs, parent=None):
27 """
28 Constructor
29
30 @param vcs reference to the vcs object
31 @param parent parent widget (QWidget)
32 """
33 super().__init__(parent)
34 self.setupUi(self)
35
36 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
37 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
38
39 self.process = None
40 self.vcs = vcs
41
42 self.rx_status = \
43 QRegExp('(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+([\\w?]+)\\s+(.+)\\s*')
44 # flags (8 or 9 anything), revision, changed rev, author, path
45 self.rx_status2 = \
46 QRegExp('(.{8,9})\\s+(.+)\\s*')
47 # flags (8 or 9 anything), path
48 self.rx_changelist = \
49 QRegExp('--- \\S+ .([\\w\\s]+).:\\s+')
50 # three dashes, Changelist (translated), quote,
51 # changelist name, quote, :
52
53 @pyqtSlot(QListWidgetItem, QListWidgetItem)
54 def on_changeLists_currentItemChanged(self, current, previous):
55 """
56 Private slot to handle the selection of a new item.
57
58 @param current current item (QListWidgetItem)
59 @param previous previous current item (QListWidgetItem)
60 """
61 self.filesList.clear()
62 if current is not None:
63 changelist = current.text()
64 if changelist in self.changeListsDict:
65 self.filesList.addItems(sorted(self.changeListsDict[changelist]))
66
67 def start(self, path):
68 """
69 Public slot to populate the data.
70
71 @param path directory name to show change lists for (string)
72 """
73 self.changeListsDict = {}
74
75 self.filesLabel.setText(self.trUtf8("Files (relative to {0}):").format(path))
76
77 self.errorGroup.hide()
78 self.intercept = False
79
80 self.path = path
81 self.currentChangelist = ""
82
83 self.process = QProcess()
84 self.process.finished.connect(self.__procFinished)
85 self.process.readyReadStandardOutput.connect(self.__readStdout)
86 self.process.readyReadStandardError.connect(self.__readStderr)
87
88 args = []
89 args.append('status')
90 self.vcs.addArguments(args, self.vcs.options['global'])
91 self.vcs.addArguments(args, self.vcs.options['status'])
92 if '--verbose' not in self.vcs.options['global'] and \
93 '--verbose' not in self.vcs.options['status']:
94 args.append('--verbose')
95 if isinstance(path, list):
96 self.dname, fnames = self.vcs.splitPathList(path)
97 self.vcs.addArguments(args, fnames)
98 else:
99 self.dname, fname = self.vcs.splitPath(path)
100 args.append(fname)
101
102 self.process.setWorkingDirectory(self.dname)
103
104 self.process.start('svn', args)
105 procStarted = self.process.waitForStarted()
106 if not procStarted:
107 self.inputGroup.setEnabled(False)
108 self.inputGroup.hide()
109 E5MessageBox.critical(self,
110 self.trUtf8('Process Generation Error'),
111 self.trUtf8(
112 'The process {0} could not be started. '
113 'Ensure, that it is in the search path.'
114 ).format('svn'))
115 else:
116 self.inputGroup.setEnabled(True)
117 self.inputGroup.show()
118
119 def __finish(self):
120 """
121 Private slot called when the process finished or the user pressed
122 the button.
123 """
124 if self.process is not None and \
125 self.process.state() != QProcess.NotRunning:
126 self.process.terminate()
127 QTimer.singleShot(2000, self.process.kill)
128 self.process.waitForFinished(3000)
129
130 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
131 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
132 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
133
134 self.inputGroup.setEnabled(False)
135 self.inputGroup.hide()
136
137 if len(self.changeListsDict) == 0:
138 self.changeLists.addItem(self.trUtf8("No changelists found"))
139 self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason)
140 else:
141 self.changeLists.addItems(sorted(self.changeListsDict.keys()))
142 self.changeLists.setCurrentRow(0)
143 self.changeLists.setFocus(Qt.OtherFocusReason)
144
145 def on_buttonBox_clicked(self, button):
146 """
147 Private slot called by a button of the button box clicked.
148
149 @param button button that was clicked (QAbstractButton)
150 """
151 if button == self.buttonBox.button(QDialogButtonBox.Close):
152 self.close()
153 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
154 self.__finish()
155
156 def __procFinished(self, exitCode, exitStatus):
157 """
158 Private slot connected to the finished signal.
159
160 @param exitCode exit code of the process (integer)
161 @param exitStatus exit status of the process (QProcess.ExitStatus)
162 """
163 self.__finish()
164
165 def __readStdout(self):
166 """
167 Private slot to handle the readyReadStandardOutput signal.
168
169 It reads the output of the process, formats it and inserts it into
170 the contents pane.
171 """
172 if self.process is not None:
173 self.process.setReadChannel(QProcess.StandardOutput)
174
175 while self.process.canReadLine():
176 s = str(self.process.readLine(),
177 Preferences.getSystem("IOEncoding"),
178 'replace')
179 if self.currentChangelist != "" and self.rx_status.exactMatch(s):
180 file = self.rx_status.cap(5).strip()
181 filename = file.replace(self.path + os.sep, "")
182 if filename not in self.changeListsDict[self.currentChangelist]:
183 self.changeListsDict[self.currentChangelist].append(filename)
184 elif self.currentChangelist != "" and self.rx_status2.exactMatch(s):
185 file = self.rx_status2.cap(2).strip()
186 filename = file.replace(self.path + os.sep, "")
187 if filename not in self.changeListsDict[self.currentChangelist]:
188 self.changeListsDict[self.currentChangelist].append(filename)
189 elif self.rx_changelist.exactMatch(s):
190 self.currentChangelist = self.rx_changelist.cap(1)
191 if self.currentChangelist not in self.changeListsDict:
192 self.changeListsDict[self.currentChangelist] = []
193
194 def __readStderr(self):
195 """
196 Private slot to handle the readyReadStandardError signal.
197
198 It reads the error output of the process and inserts it into the
199 error pane.
200 """
201 if self.process is not None:
202 self.errorGroup.show()
203 s = str(self.process.readAllStandardError(),
204 Preferences.getSystem("IOEncoding"),
205 'replace')
206 self.errors.insertPlainText(s)
207 self.errors.ensureCursorVisible()
208
209 def on_passwordCheckBox_toggled(self, isOn):
210 """
211 Private slot to handle the password checkbox toggled.
212
213 @param isOn flag indicating the status of the check box (boolean)
214 """
215 if isOn:
216 self.input.setEchoMode(QLineEdit.Password)
217 else:
218 self.input.setEchoMode(QLineEdit.Normal)
219
220 @pyqtSlot()
221 def on_sendButton_clicked(self):
222 """
223 Private slot to send the input to the subversion process.
224 """
225 input = self.input.text()
226 input += os.linesep
227
228 if self.passwordCheckBox.isChecked():
229 self.errors.insertPlainText(os.linesep)
230 self.errors.ensureCursorVisible()
231 else:
232 self.errors.insertPlainText(input)
233 self.errors.ensureCursorVisible()
234
235 self.process.write(input)
236
237 self.passwordCheckBox.setChecked(False)
238 self.input.clear()
239
240 def on_input_returnPressed(self):
241 """
242 Private slot to handle the press of the return key in the input field.
243 """
244 self.intercept = True
245 self.on_sendButton_clicked()
246
247 def keyPressEvent(self, evt):
248 """
249 Protected slot to handle a key press event.
250
251 @param evt the key press event (QKeyEvent)
252 """
253 if self.intercept:
254 self.intercept = False
255 evt.accept()
256 return
257 super().keyPressEvent(evt)

eric ide

mercurial