Plugins/VcsPlugins/vcsMercurial/BookmarksExtension/HgBookmarksInOutDialog.py

changeset 1018
949812411ab8
child 1131
7781e396c903
equal deleted inserted replaced
1017:919147f2b518 1018:949812411ab8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2011 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show a list of incoming or outgoing bookmarks.
8 """
9
10 import os
11
12 from PyQt4.QtCore import pyqtSlot, QProcess, Qt, QTimer
13 from PyQt4.QtGui import QDialog, QDialogButtonBox, QHeaderView, QTreeWidgetItem, \
14 QLineEdit
15
16 from E5Gui import E5MessageBox
17
18 from .Ui_HgBookmarksInOutDialog import Ui_HgBookmarksInOutDialog
19
20 import Preferences
21
22
23 class HgBookmarksInOutDialog(QDialog, Ui_HgBookmarksInOutDialog):
24 """
25 Class implementing a dialog to show a list of incoming or outgoing bookmarks.
26 """
27 INCOMING = 0
28 OUTGOING = 1
29
30 def __init__(self, vcs, mode, parent=None):
31 """
32 Constructor
33
34 @param vcs reference to the vcs object
35 @param mode mode of the dialog (HgBookmarksInOutDialog.INCOMING,
36 HgBookmarksInOutDialog.OUTGOING)
37 @param parent reference to the parent widget (QWidget)
38 """
39 QDialog.__init__(self, parent)
40 self.setupUi(self)
41
42 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
43 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
44
45 if mode not in [self.INCOMING, self.OUTGOING]:
46 raise ValueError("Bad value for mode")
47 if mode == self.INCOMING:
48 self.setWindowTitle(self.trUtf8("Mercurial Incoming Bookmarks"))
49 elif mode == self.OUTGOING:
50 self.setWindowTitle(self.trUtf8("Mercurial Outgoing Bookmarks"))
51
52 self.process = QProcess()
53 self.vcs = vcs
54 self.mode = mode
55
56 self.bookmarksList.headerItem().setText(self.bookmarksList.columnCount(), "")
57 self.bookmarksList.header().setSortIndicator(3, Qt.AscendingOrder)
58
59 self.process.finished.connect(self.__procFinished)
60 self.process.readyReadStandardOutput.connect(self.__readStdout)
61 self.process.readyReadStandardError.connect(self.__readStderr)
62
63 def closeEvent(self, e):
64 """
65 Private slot implementing a close event handler.
66
67 @param e close event (QCloseEvent)
68 """
69 if self.process is not None and \
70 self.process.state() != QProcess.NotRunning:
71 self.process.terminate()
72 QTimer.singleShot(2000, self.process.kill)
73 self.process.waitForFinished(3000)
74
75 e.accept()
76
77 def start(self, path):
78 """
79 Public slot to start the bookmarks command.
80
81 @param path name of directory to be listed (string)
82 """
83 self.errorGroup.hide()
84
85 self.intercept = False
86 self.activateWindow()
87
88 dname, fname = self.vcs.splitPath(path)
89
90 # find the root of the repo
91 repodir = dname
92 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
93 repodir = os.path.dirname(repodir)
94 if repodir == os.sep:
95 return
96
97 args = []
98 if self.mode == self.INCOMING:
99 args.append('incoming')
100 elif self.mode == self.OUTGOING:
101 args.append('outgoing')
102 else:
103 raise ValueError("Bad value for mode")
104 args.append('--bookmarks')
105
106 self.process.kill()
107 self.process.setWorkingDirectory(repodir)
108
109 self.process.start('hg', args)
110 procStarted = self.process.waitForStarted()
111 if not procStarted:
112 self.inputGroup.setEnabled(False)
113 self.inputGroup.hide()
114 E5MessageBox.critical(self,
115 self.trUtf8('Process Generation Error'),
116 self.trUtf8(
117 'The process {0} could not be started. '
118 'Ensure, that it is in the search path.'
119 ).format('hg'))
120 else:
121 self.inputGroup.setEnabled(True)
122 self.inputGroup.show()
123
124 def __finish(self):
125 """
126 Private slot called when the process finished or the user pressed the button.
127 """
128 if self.process is not None and \
129 self.process.state() != QProcess.NotRunning:
130 self.process.terminate()
131 QTimer.singleShot(2000, self.process.kill)
132 self.process.waitForFinished(3000)
133
134 self.inputGroup.setEnabled(False)
135 self.inputGroup.hide()
136
137 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
138 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
139 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
140 self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason)
141
142 self.process = None
143
144 if self.bookmarksList.topLevelItemCount() == 0:
145 # no bookmarks defined
146 self.__generateItem(self.trUtf8("no bookmarks found"), "")
147 self.bookmarksList.doItemsLayout()
148 self.__resizeColumns()
149 self.__resort()
150
151 def on_buttonBox_clicked(self, button):
152 """
153 Private slot called by a button of the button box clicked.
154
155 @param button button that was clicked (QAbstractButton)
156 """
157 if button == self.buttonBox.button(QDialogButtonBox.Close):
158 self.close()
159 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
160 self.__finish()
161
162 def __procFinished(self, exitCode, exitStatus):
163 """
164 Private slot connected to the finished signal.
165
166 @param exitCode exit code of the process (integer)
167 @param exitStatus exit status of the process (QProcess.ExitStatus)
168 """
169 self.__finish()
170
171 def __resort(self):
172 """
173 Private method to resort the tree.
174 """
175 self.bookmarksList.sortItems(self.bookmarksList.sortColumn(),
176 self.bookmarksList.header().sortIndicatorOrder())
177
178 def __resizeColumns(self):
179 """
180 Private method to resize the list columns.
181 """
182 self.bookmarksList.header().resizeSections(QHeaderView.ResizeToContents)
183 self.bookmarksList.header().setStretchLastSection(True)
184
185 def __generateItem(self, changeset, name):
186 """
187 Private method to generate a bookmark item in the bookmarks list.
188
189 @param changeset changeset of the bookmark (string)
190 @param name name of the bookmark (string)
191 """
192 itm = QTreeWidgetItem(self.bookmarksList, [
193 name,
194 changeset])
195 itm.setTextAlignment(1, Qt.AlignRight)
196
197 def __readStdout(self):
198 """
199 Private slot to handle the readyReadStdout signal.
200
201 It reads the output of the process, formats it and inserts it into
202 the contents pane.
203 """
204 self.process.setReadChannel(QProcess.StandardOutput)
205
206 while self.process.canReadLine():
207 s = str(self.process.readLine(),
208 Preferences.getSystem("IOEncoding"),
209 'replace')
210 if s.startswith(" "):
211 l = s.strip().split()
212 changeset = l[-1]
213 del l[-1]
214 name = " ".join(l)
215 self.__generateItem(changeset, name)
216
217 def __readStderr(self):
218 """
219 Private slot to handle the readyReadStderr signal.
220
221 It reads the error output of the process and inserts it into the
222 error pane.
223 """
224 if self.process is not None:
225 self.errorGroup.show()
226 s = str(self.process.readAllStandardError(),
227 Preferences.getSystem("IOEncoding"),
228 'replace')
229 self.errors.insertPlainText(s)
230 self.errors.ensureCursorVisible()
231
232 def on_passwordCheckBox_toggled(self, isOn):
233 """
234 Private slot to handle the password checkbox toggled.
235
236 @param isOn flag indicating the status of the check box (boolean)
237 """
238 if isOn:
239 self.input.setEchoMode(QLineEdit.Password)
240 else:
241 self.input.setEchoMode(QLineEdit.Normal)
242
243 @pyqtSlot()
244 def on_sendButton_clicked(self):
245 """
246 Private slot to send the input to the subversion process.
247 """
248 input = self.input.text()
249 input += os.linesep
250
251 if self.passwordCheckBox.isChecked():
252 self.errors.insertPlainText(os.linesep)
253 self.errors.ensureCursorVisible()
254 else:
255 self.errors.insertPlainText(input)
256 self.errors.ensureCursorVisible()
257
258 self.process.write(input)
259
260 self.passwordCheckBox.setChecked(False)
261 self.input.clear()
262
263 def on_input_returnPressed(self):
264 """
265 Private slot to handle the press of the return key in the input field.
266 """
267 self.intercept = True
268 self.on_sendButton_clicked()
269
270 def keyPressEvent(self, evt):
271 """
272 Protected slot to handle a key press event.
273
274 @param evt the key press event (QKeyEvent)
275 """
276 if self.intercept:
277 self.intercept = False
278 evt.accept()
279 return
280 QDialog.keyPressEvent(self, evt)

eric ide

mercurial