Plugins/VcsPlugins/vcsMercurial/HgBookmarksListDialog.py

changeset 3562
ef3f13a2c599
parent 3484
645c12de6b0c
child 3591
2f2a4a76dd22
equal deleted inserted replaced
3559:8938a2a66dee 3562:ef3f13a2c599
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2011 - 2014 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show a list of bookmarks.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode
13 except NameError:
14 pass
15
16 import os
17
18 from PyQt4.QtCore import pyqtSlot, QProcess, Qt, QTimer, QCoreApplication
19 from PyQt4.QtGui import QDialog, QDialogButtonBox, QHeaderView, \
20 QTreeWidgetItem, QLineEdit
21
22 from E5Gui import E5MessageBox
23
24 from .Ui_HgBookmarksListDialog import Ui_HgBookmarksListDialog
25
26
27 class HgBookmarksListDialog(QDialog, Ui_HgBookmarksListDialog):
28 """
29 Class implementing a dialog to show a list of bookmarks.
30 """
31 def __init__(self, vcs, parent=None):
32 """
33 Constructor
34
35 @param vcs reference to the vcs object
36 @param parent parent widget (QWidget)
37 """
38 super(HgBookmarksListDialog, self).__init__(parent)
39 self.setupUi(self)
40
41 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
42 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
43
44 self.process = QProcess()
45 self.vcs = vcs
46 self.__bookmarksList = None
47 self.__hgClient = vcs.getClient()
48
49 self.bookmarksList.headerItem().setText(
50 self.bookmarksList.columnCount(), "")
51 self.bookmarksList.header().setSortIndicator(3, Qt.AscendingOrder)
52
53 self.process.finished.connect(self.__procFinished)
54 self.process.readyReadStandardOutput.connect(self.__readStdout)
55 self.process.readyReadStandardError.connect(self.__readStderr)
56
57 self.show()
58 QCoreApplication.processEvents()
59
60 def closeEvent(self, e):
61 """
62 Private slot implementing a close event handler.
63
64 @param e close event (QCloseEvent)
65 """
66 if self.__hgClient:
67 if self.__hgClient.isExecuting():
68 self.__hgClient.cancel()
69 else:
70 if self.process is not None and \
71 self.process.state() != QProcess.NotRunning:
72 self.process.terminate()
73 QTimer.singleShot(2000, self.process.kill)
74 self.process.waitForFinished(3000)
75
76 e.accept()
77
78 def start(self, path, bookmarksList):
79 """
80 Public slot to start the bookmarks command.
81
82 @param path name of directory to be listed (string)
83 @param bookmarksList reference to string list receiving the bookmarks
84 (list of strings)
85 """
86 self.errorGroup.hide()
87
88 self.intercept = False
89 self.activateWindow()
90
91 self.__bookmarksList = bookmarksList
92 dname, fname = self.vcs.splitPath(path)
93
94 # find the root of the repo
95 repodir = dname
96 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
97 repodir = os.path.dirname(repodir)
98 if os.path.splitdrive(repodir)[1] == os.sep:
99 return
100
101 args = self.vcs.initCommand("bookmarks")
102
103 if self.__hgClient:
104 self.inputGroup.setEnabled(False)
105 self.inputGroup.hide()
106
107 out, err = self.__hgClient.runcommand(args)
108 if err:
109 self.__showError(err)
110 if out:
111 for line in out.splitlines():
112 self.__processOutputLine(line)
113 if self.__hgClient.wasCanceled():
114 break
115 self.__finish()
116 else:
117 self.process.kill()
118 self.process.setWorkingDirectory(repodir)
119
120 self.process.start('hg', args)
121 procStarted = self.process.waitForStarted(5000)
122 if not procStarted:
123 self.inputGroup.setEnabled(False)
124 self.inputGroup.hide()
125 E5MessageBox.critical(
126 self,
127 self.tr('Process Generation Error'),
128 self.tr(
129 'The process {0} could not be started. '
130 'Ensure, that it is in the search path.'
131 ).format('hg'))
132 else:
133 self.inputGroup.setEnabled(True)
134 self.inputGroup.show()
135
136 def __finish(self):
137 """
138 Private slot called when the process finished or the user pressed
139 the button.
140 """
141 if self.process is not None and \
142 self.process.state() != QProcess.NotRunning:
143 self.process.terminate()
144 QTimer.singleShot(2000, self.process.kill)
145 self.process.waitForFinished(3000)
146
147 self.inputGroup.setEnabled(False)
148 self.inputGroup.hide()
149
150 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
151 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
152 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
153 self.buttonBox.button(QDialogButtonBox.Close).setFocus(
154 Qt.OtherFocusReason)
155
156 self.process = None
157
158 if self.bookmarksList.topLevelItemCount() == 0:
159 # no bookmarks defined
160 self.__generateItem(
161 self.tr("no bookmarks defined"), "", "", "")
162 self.__resizeColumns()
163 self.__resort()
164
165 def on_buttonBox_clicked(self, button):
166 """
167 Private slot called by a button of the button box clicked.
168
169 @param button button that was clicked (QAbstractButton)
170 """
171 if button == self.buttonBox.button(QDialogButtonBox.Close):
172 self.close()
173 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
174 if self.__hgClient:
175 self.__hgClient.cancel()
176 else:
177 self.__finish()
178
179 def __procFinished(self, exitCode, exitStatus):
180 """
181 Private slot connected to the finished signal.
182
183 @param exitCode exit code of the process (integer)
184 @param exitStatus exit status of the process (QProcess.ExitStatus)
185 """
186 self.__finish()
187
188 def __resort(self):
189 """
190 Private method to resort the tree.
191 """
192 self.bookmarksList.sortItems(
193 self.bookmarksList.sortColumn(),
194 self.bookmarksList.header().sortIndicatorOrder())
195
196 def __resizeColumns(self):
197 """
198 Private method to resize the list columns.
199 """
200 self.bookmarksList.header().resizeSections(
201 QHeaderView.ResizeToContents)
202 self.bookmarksList.header().setStretchLastSection(True)
203
204 def __generateItem(self, revision, changeset, status, name):
205 """
206 Private method to generate a bookmark item in the bookmarks list.
207
208 @param revision revision of the bookmark (string)
209 @param changeset changeset of the bookmark (string)
210 @param status of the bookmark (string)
211 @param name name of the bookmark (string)
212 """
213 itm = QTreeWidgetItem(self.bookmarksList)
214 if revision[0].isdecimal():
215 # valid bookmark entry
216 itm.setData(0, Qt.DisplayRole, int(revision))
217 itm.setData(1, Qt.DisplayRole, changeset)
218 itm.setData(2, Qt.DisplayRole, status)
219 itm.setData(3, Qt.DisplayRole, name)
220 itm.setTextAlignment(0, Qt.AlignRight)
221 itm.setTextAlignment(1, Qt.AlignRight)
222 itm.setTextAlignment(2, Qt.AlignHCenter)
223 else:
224 # error message
225 itm.setData(0, Qt.DisplayRole, revision)
226
227 def __readStdout(self):
228 """
229 Private slot to handle the readyReadStdout signal.
230
231 It reads the output of the process, formats it and inserts it into
232 the contents pane.
233 """
234 self.process.setReadChannel(QProcess.StandardOutput)
235
236 while self.process.canReadLine():
237 s = str(self.process.readLine(), self.vcs.getEncoding(),
238 'replace').strip()
239 self.__processOutputLine(s)
240
241 def __processOutputLine(self, line):
242 """
243 Private method to process the lines of output.
244
245 @param line output line to be processed (string)
246 """
247 li = line.split()
248 if li[-1][0] in "1234567890":
249 # last element is a rev:changeset
250 rev, changeset = li[-1].split(":", 1)
251 del li[-1]
252 if li[0] == "*":
253 status = "current"
254 del li[0]
255 else:
256 status = ""
257 name = " ".join(li)
258 self.__generateItem(rev, changeset, status, name)
259 if self.__bookmarksList is not None:
260 self.__bookmarksList.append(name)
261
262 def __readStderr(self):
263 """
264 Private slot to handle the readyReadStderr signal.
265
266 It reads the error output of the process and inserts it into the
267 error pane.
268 """
269 if self.process is not None:
270 s = str(self.process.readAllStandardError(),
271 self.vcs.getEncoding(), 'replace')
272 self.__showError(s)
273
274 def __showError(self, out):
275 """
276 Private slot to show some error.
277
278 @param out error to be shown (string)
279 """
280 self.errorGroup.show()
281 self.errors.insertPlainText(out)
282 self.errors.ensureCursorVisible()
283
284 def on_passwordCheckBox_toggled(self, isOn):
285 """
286 Private slot to handle the password checkbox toggled.
287
288 @param isOn flag indicating the status of the check box (boolean)
289 """
290 if isOn:
291 self.input.setEchoMode(QLineEdit.Password)
292 else:
293 self.input.setEchoMode(QLineEdit.Normal)
294
295 @pyqtSlot()
296 def on_sendButton_clicked(self):
297 """
298 Private slot to send the input to the subversion process.
299 """
300 input = self.input.text()
301 input += os.linesep
302
303 if self.passwordCheckBox.isChecked():
304 self.errors.insertPlainText(os.linesep)
305 self.errors.ensureCursorVisible()
306 else:
307 self.errors.insertPlainText(input)
308 self.errors.ensureCursorVisible()
309
310 self.process.write(input)
311
312 self.passwordCheckBox.setChecked(False)
313 self.input.clear()
314
315 def on_input_returnPressed(self):
316 """
317 Private slot to handle the press of the return key in the input field.
318 """
319 self.intercept = True
320 self.on_sendButton_clicked()
321
322 def keyPressEvent(self, evt):
323 """
324 Protected slot to handle a key press event.
325
326 @param evt the key press event (QKeyEvent)
327 """
328 if self.intercept:
329 self.intercept = False
330 evt.accept()
331 return
332 super(HgBookmarksListDialog, self).keyPressEvent(evt)

eric ide

mercurial