src/eric7/Plugins/VcsPlugins/vcsSubversion/SvnRepoBrowserDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
10 import re 10 import re
11 import os 11 import os
12 12
13 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QProcess 13 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QProcess
14 from PyQt6.QtWidgets import ( 14 from PyQt6.QtWidgets import (
15 QHeaderView, QLineEdit, QDialog, QDialogButtonBox, QTreeWidgetItem 15 QHeaderView,
16 QLineEdit,
17 QDialog,
18 QDialogButtonBox,
19 QTreeWidgetItem,
16 ) 20 )
17 21
18 from EricWidgets import EricMessageBox 22 from EricWidgets import EricMessageBox
19 from EricGui.EricOverrideCursor import EricOverrideCursorProcess 23 from EricGui.EricOverrideCursor import EricOverrideCursorProcess
20 24
28 32
29 class SvnRepoBrowserDialog(QDialog, Ui_SvnRepoBrowserDialog): 33 class SvnRepoBrowserDialog(QDialog, Ui_SvnRepoBrowserDialog):
30 """ 34 """
31 Class implementing the subversion repository browser dialog. 35 Class implementing the subversion repository browser dialog.
32 """ 36 """
37
33 def __init__(self, vcs, mode="browse", parent=None): 38 def __init__(self, vcs, mode="browse", parent=None):
34 """ 39 """
35 Constructor 40 Constructor
36 41
37 @param vcs reference to the vcs object 42 @param vcs reference to the vcs object
38 @param mode mode of the dialog (string, "browse" or "select") 43 @param mode mode of the dialog (string, "browse" or "select")
39 @param parent parent widget (QWidget) 44 @param parent parent widget (QWidget)
40 """ 45 """
41 super().__init__(parent) 46 super().__init__(parent)
42 self.setupUi(self) 47 self.setupUi(self)
43 self.setWindowFlags(Qt.WindowType.Window) 48 self.setWindowFlags(Qt.WindowType.Window)
44 49
45 self.repoTree.headerItem().setText(self.repoTree.columnCount(), "") 50 self.repoTree.headerItem().setText(self.repoTree.columnCount(), "")
46 self.repoTree.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder) 51 self.repoTree.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder)
47 52
48 self.vcs = vcs 53 self.vcs = vcs
49 self.mode = mode 54 self.mode = mode
50 55
51 self.__process = EricOverrideCursorProcess() 56 self.__process = EricOverrideCursorProcess()
52 self.__process.finished.connect(self.__procFinished) 57 self.__process.finished.connect(self.__procFinished)
53 self.__process.readyReadStandardOutput.connect(self.__readStdout) 58 self.__process.readyReadStandardOutput.connect(self.__readStdout)
54 self.__process.readyReadStandardError.connect(self.__readStderr) 59 self.__process.readyReadStandardError.connect(self.__readStderr)
55 60
56 if self.mode == "select": 61 if self.mode == "select":
57 self.buttonBox.button( 62 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False)
58 QDialogButtonBox.StandardButton.Ok).setEnabled(False)
59 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).hide() 63 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).hide()
60 else: 64 else:
61 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).hide() 65 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).hide()
62 self.buttonBox.button( 66 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).hide()
63 QDialogButtonBox.StandardButton.Cancel).hide() 67
64
65 self.__dirIcon = UI.PixmapCache.getIcon("dirClosed") 68 self.__dirIcon = UI.PixmapCache.getIcon("dirClosed")
66 self.__fileIcon = UI.PixmapCache.getIcon("fileMisc") 69 self.__fileIcon = UI.PixmapCache.getIcon("fileMisc")
67 70
68 self.__urlRole = Qt.ItemDataRole.UserRole 71 self.__urlRole = Qt.ItemDataRole.UserRole
69 self.__ignoreExpand = False 72 self.__ignoreExpand = False
70 self.intercept = False 73 self.intercept = False
71 74
72 self.__rx_dir = re.compile( 75 self.__rx_dir = re.compile(
73 r"""\s*([0-9]+)\s+(\w+)\s+""" 76 r"""\s*([0-9]+)\s+(\w+)\s+"""
74 r"""((?:\w+\s+\d+|[0-9.]+\s+\w+)\s+[0-9:]+)\s+(.+)\s*""") 77 r"""((?:\w+\s+\d+|[0-9.]+\s+\w+)\s+[0-9:]+)\s+(.+)\s*"""
78 )
75 self.__rx_file = re.compile( 79 self.__rx_file = re.compile(
76 r"""\s*([0-9]+)\s+(\w+)\s+([0-9]+)\s""" 80 r"""\s*([0-9]+)\s+(\w+)\s+([0-9]+)\s"""
77 r"""((?:\w+\s+\d+|[0-9.]+\s+\w+)\s+[0-9:]+)\s+(.+)\s*""") 81 r"""((?:\w+\s+\d+|[0-9.]+\s+\w+)\s+[0-9:]+)\s+(.+)\s*"""
78 82 )
83
79 def closeEvent(self, e): 84 def closeEvent(self, e):
80 """ 85 """
81 Protected slot implementing a close event handler. 86 Protected slot implementing a close event handler.
82 87
83 @param e close event (QCloseEvent) 88 @param e close event (QCloseEvent)
84 """ 89 """
85 if ( 90 if (
86 self.__process is not None and 91 self.__process is not None
87 self.__process.state() != QProcess.ProcessState.NotRunning 92 and self.__process.state() != QProcess.ProcessState.NotRunning
88 ): 93 ):
89 self.__process.terminate() 94 self.__process.terminate()
90 QTimer.singleShot(2000, self.__process.kill) 95 QTimer.singleShot(2000, self.__process.kill)
91 self.__process.waitForFinished(3000) 96 self.__process.waitForFinished(3000)
92 97
93 e.accept() 98 e.accept()
94 99
95 def __resort(self): 100 def __resort(self):
96 """ 101 """
97 Private method to resort the tree. 102 Private method to resort the tree.
98 """ 103 """
99 self.repoTree.sortItems( 104 self.repoTree.sortItems(
100 self.repoTree.sortColumn(), 105 self.repoTree.sortColumn(), self.repoTree.header().sortIndicatorOrder()
101 self.repoTree.header().sortIndicatorOrder()) 106 )
102 107
103 def __resizeColumns(self): 108 def __resizeColumns(self):
104 """ 109 """
105 Private method to resize the tree columns. 110 Private method to resize the tree columns.
106 """ 111 """
107 self.repoTree.header().resizeSections( 112 self.repoTree.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
108 QHeaderView.ResizeMode.ResizeToContents)
109 self.repoTree.header().setStretchLastSection(True) 113 self.repoTree.header().setStretchLastSection(True)
110 114
111 def __generateItem(self, repopath, revision, author, size, date, 115 def __generateItem(self, repopath, revision, author, size, date, nodekind, url):
112 nodekind, url):
113 """ 116 """
114 Private method to generate a tree item in the repository tree. 117 Private method to generate a tree item in the repository tree.
115 118
116 @param repopath path of the item (string) 119 @param repopath path of the item (string)
117 @param revision revision info (string) 120 @param revision revision info (string)
118 @param author author info (string) 121 @param author author info (string)
119 @param size size info (string) 122 @param size size info (string)
120 @param date date info (string) 123 @param date date info (string)
122 @param url url of the entry (string) 125 @param url url of the entry (string)
123 @return reference to the generated item (QTreeWidgetItem) 126 @return reference to the generated item (QTreeWidgetItem)
124 """ 127 """
125 rev = "" if revision == "" else int(revision) 128 rev = "" if revision == "" else int(revision)
126 sz = "" if size == "" else int(size) 129 sz = "" if size == "" else int(size)
127 130
128 itm = QTreeWidgetItem(self.parentItem) 131 itm = QTreeWidgetItem(self.parentItem)
129 itm.setData(0, Qt.ItemDataRole.DisplayRole, repopath) 132 itm.setData(0, Qt.ItemDataRole.DisplayRole, repopath)
130 itm.setData(1, Qt.ItemDataRole.DisplayRole, rev) 133 itm.setData(1, Qt.ItemDataRole.DisplayRole, rev)
131 itm.setData(2, Qt.ItemDataRole.DisplayRole, author) 134 itm.setData(2, Qt.ItemDataRole.DisplayRole, author)
132 itm.setData(3, Qt.ItemDataRole.DisplayRole, sz) 135 itm.setData(3, Qt.ItemDataRole.DisplayRole, sz)
133 itm.setData(4, Qt.ItemDataRole.DisplayRole, date) 136 itm.setData(4, Qt.ItemDataRole.DisplayRole, date)
134 137
135 if nodekind == "dir": 138 if nodekind == "dir":
136 itm.setIcon(0, self.__dirIcon) 139 itm.setIcon(0, self.__dirIcon)
137 itm.setChildIndicatorPolicy( 140 itm.setChildIndicatorPolicy(
138 QTreeWidgetItem.ChildIndicatorPolicy.ShowIndicator) 141 QTreeWidgetItem.ChildIndicatorPolicy.ShowIndicator
142 )
139 elif nodekind == "file": 143 elif nodekind == "file":
140 itm.setIcon(0, self.__fileIcon) 144 itm.setIcon(0, self.__fileIcon)
141 145
142 itm.setData(0, self.__urlRole, url) 146 itm.setData(0, self.__urlRole, url)
143 147
144 itm.setTextAlignment(0, Qt.AlignmentFlag.AlignLeft) 148 itm.setTextAlignment(0, Qt.AlignmentFlag.AlignLeft)
145 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignRight) 149 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignRight)
146 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignLeft) 150 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignLeft)
147 itm.setTextAlignment(3, Qt.AlignmentFlag.AlignRight) 151 itm.setTextAlignment(3, Qt.AlignmentFlag.AlignRight)
148 itm.setTextAlignment(4, Qt.AlignmentFlag.AlignLeft) 152 itm.setTextAlignment(4, Qt.AlignmentFlag.AlignLeft)
149 153
150 return itm 154 return itm
151 155
152 def __repoRoot(self, url): 156 def __repoRoot(self, url):
153 """ 157 """
154 Private method to get the repository root using the svn info command. 158 Private method to get the repository root using the svn info command.
155 159
156 @param url the repository URL to browser (string) 160 @param url the repository URL to browser (string)
157 @return repository root (string) 161 @return repository root (string)
158 """ 162 """
159 ioEncoding = Preferences.getSystem("IOEncoding") 163 ioEncoding = Preferences.getSystem("IOEncoding")
160 repoRoot = None 164 repoRoot = None
161 165
162 process = QProcess() 166 process = QProcess()
163 167
164 args = [] 168 args = []
165 args.append('info') 169 args.append("info")
166 self.vcs.addArguments(args, self.vcs.options['global']) 170 self.vcs.addArguments(args, self.vcs.options["global"])
167 args.append('--xml') 171 args.append("--xml")
168 args.append(url) 172 args.append(url)
169 173
170 process.start('svn', args) 174 process.start("svn", args)
171 procStarted = process.waitForStarted(5000) 175 procStarted = process.waitForStarted(5000)
172 if procStarted: 176 if procStarted:
173 finished = process.waitForFinished(30000) 177 finished = process.waitForFinished(30000)
174 if finished: 178 if finished:
175 if process.exitCode() == 0: 179 if process.exitCode() == 0:
176 output = str(process.readAllStandardOutput(), ioEncoding, 180 output = str(process.readAllStandardOutput(), ioEncoding, "replace")
177 'replace')
178 for line in output.splitlines(): 181 for line in output.splitlines():
179 line = line.strip() 182 line = line.strip()
180 if line.startswith('<root>'): 183 if line.startswith("<root>"):
181 repoRoot = ( 184 repoRoot = line.replace("<root>", "").replace("</root>", "")
182 line.replace('<root>', '')
183 .replace('</root>', '')
184 )
185 break 185 break
186 else: 186 else:
187 error = str(process.readAllStandardError(), 187 error = str(
188 Preferences.getSystem("IOEncoding"), 188 process.readAllStandardError(),
189 'replace') 189 Preferences.getSystem("IOEncoding"),
190 "replace",
191 )
190 self.errors.insertPlainText(error) 192 self.errors.insertPlainText(error)
191 self.errors.ensureCursorVisible() 193 self.errors.ensureCursorVisible()
192 else: 194 else:
193 EricMessageBox.critical( 195 EricMessageBox.critical(
194 self, 196 self,
195 self.tr('Process Generation Error'), 197 self.tr("Process Generation Error"),
196 self.tr( 198 self.tr(
197 'The process {0} could not be started. ' 199 "The process {0} could not be started. "
198 'Ensure, that it is in the search path.' 200 "Ensure, that it is in the search path."
199 ).format('svn')) 201 ).format("svn"),
202 )
200 return repoRoot 203 return repoRoot
201 204
202 def __listRepo(self, url, parent=None): 205 def __listRepo(self, url, parent=None):
203 """ 206 """
204 Private method to perform the svn list command. 207 Private method to perform the svn list command.
205 208
206 @param url the repository URL to browse (string) 209 @param url the repository URL to browse (string)
207 @param parent reference to the item, the data should be appended to 210 @param parent reference to the item, the data should be appended to
208 (QTreeWidget or QTreeWidgetItem) 211 (QTreeWidget or QTreeWidgetItem)
209 """ 212 """
210 self.errorGroup.hide() 213 self.errorGroup.hide()
211 214
212 self.repoUrl = url 215 self.repoUrl = url
213 216
214 if parent is None: 217 if parent is None:
215 self.parentItem = self.repoTree 218 self.parentItem = self.repoTree
216 else: 219 else:
217 self.parentItem = parent 220 self.parentItem = parent
218 221
219 if self.parentItem == self.repoTree: 222 if self.parentItem == self.repoTree:
220 repoRoot = self.__repoRoot(url) 223 repoRoot = self.__repoRoot(url)
221 if repoRoot is None: 224 if repoRoot is None:
222 self.__finish() 225 self.__finish()
223 return 226 return
224 self.__ignoreExpand = True 227 self.__ignoreExpand = True
225 itm = self.__generateItem( 228 itm = self.__generateItem(repoRoot, "", "", "", "", "dir", repoRoot)
226 repoRoot, "", "", "", "", "dir", repoRoot)
227 itm.setExpanded(True) 229 itm.setExpanded(True)
228 self.parentItem = itm 230 self.parentItem = itm
229 urlPart = repoRoot 231 urlPart = repoRoot
230 for element in url.replace(repoRoot, "").split("/"): 232 for element in url.replace(repoRoot, "").split("/"):
231 if element: 233 if element:
232 urlPart = "{0}/{1}".format(urlPart, element) 234 urlPart = "{0}/{1}".format(urlPart, element)
233 itm = self.__generateItem( 235 itm = self.__generateItem(element, "", "", "", "", "dir", urlPart)
234 element, "", "", "", "", "dir", urlPart)
235 itm.setExpanded(True) 236 itm.setExpanded(True)
236 self.parentItem = itm 237 self.parentItem = itm
237 itm.setExpanded(False) 238 itm.setExpanded(False)
238 self.__ignoreExpand = False 239 self.__ignoreExpand = False
239 self.__finish() 240 self.__finish()
240 return 241 return
241 242
242 self.intercept = False 243 self.intercept = False
243 244
244 self.__process.kill() 245 self.__process.kill()
245 246
246 args = [] 247 args = []
247 args.append('list') 248 args.append("list")
248 self.vcs.addArguments(args, self.vcs.options['global']) 249 self.vcs.addArguments(args, self.vcs.options["global"])
249 if '--verbose' not in self.vcs.options['global']: 250 if "--verbose" not in self.vcs.options["global"]:
250 args.append('--verbose') 251 args.append("--verbose")
251 args.append(url) 252 args.append(url)
252 253
253 self.__process.start('svn', args) 254 self.__process.start("svn", args)
254 procStarted = self.__process.waitForStarted(5000) 255 procStarted = self.__process.waitForStarted(5000)
255 if not procStarted: 256 if not procStarted:
256 self.__finish() 257 self.__finish()
257 self.inputGroup.setEnabled(False) 258 self.inputGroup.setEnabled(False)
258 self.inputGroup.hide() 259 self.inputGroup.hide()
259 EricMessageBox.critical( 260 EricMessageBox.critical(
260 self, 261 self,
261 self.tr('Process Generation Error'), 262 self.tr("Process Generation Error"),
262 self.tr( 263 self.tr(
263 'The process {0} could not be started. ' 264 "The process {0} could not be started. "
264 'Ensure, that it is in the search path.' 265 "Ensure, that it is in the search path."
265 ).format('svn')) 266 ).format("svn"),
267 )
266 else: 268 else:
267 self.inputGroup.setEnabled(True) 269 self.inputGroup.setEnabled(True)
268 self.inputGroup.show() 270 self.inputGroup.show()
269 271
270 def __normalizeUrl(self, url): 272 def __normalizeUrl(self, url):
271 """ 273 """
272 Private method to normalite the url. 274 Private method to normalite the url.
273 275
274 @param url the url to normalize (string) 276 @param url the url to normalize (string)
275 @return normalized URL (string) 277 @return normalized URL (string)
276 """ 278 """
277 if url.endswith("/"): 279 if url.endswith("/"):
278 return url[:-1] 280 return url[:-1]
279 return url 281 return url
280 282
281 def start(self, url): 283 def start(self, url):
282 """ 284 """
283 Public slot to start the svn info command. 285 Public slot to start the svn info command.
284 286
285 @param url the repository URL to browser (string) 287 @param url the repository URL to browser (string)
286 """ 288 """
287 self.repoTree.clear() 289 self.repoTree.clear()
288 290
289 self.url = "" 291 self.url = ""
290 292
291 url = self.__normalizeUrl(url) 293 url = self.__normalizeUrl(url)
292 if self.urlCombo.findText(url) == -1: 294 if self.urlCombo.findText(url) == -1:
293 self.urlCombo.addItem(url) 295 self.urlCombo.addItem(url)
294 296
295 @pyqtSlot(int) 297 @pyqtSlot(int)
296 def on_urlCombo_currentIndexChanged(self, index): 298 def on_urlCombo_currentIndexChanged(self, index):
297 """ 299 """
298 Private slot called, when a new repository URL is entered or selected. 300 Private slot called, when a new repository URL is entered or selected.
299 301
300 @param index index of the current item 302 @param index index of the current item
301 @type int 303 @type int
302 """ 304 """
303 text = self.urlCombo.itemText(index) 305 text = self.urlCombo.itemText(index)
304 url = self.__normalizeUrl(text) 306 url = self.__normalizeUrl(text)
305 if url != self.url: 307 if url != self.url:
306 self.url = url 308 self.url = url
307 self.repoTree.clear() 309 self.repoTree.clear()
308 self.__listRepo(url) 310 self.__listRepo(url)
309 311
310 @pyqtSlot(QTreeWidgetItem) 312 @pyqtSlot(QTreeWidgetItem)
311 def on_repoTree_itemExpanded(self, item): 313 def on_repoTree_itemExpanded(self, item):
312 """ 314 """
313 Private slot called when an item is expanded. 315 Private slot called when an item is expanded.
314 316
315 @param item reference to the item to be expanded (QTreeWidgetItem) 317 @param item reference to the item to be expanded (QTreeWidgetItem)
316 """ 318 """
317 if not self.__ignoreExpand: 319 if not self.__ignoreExpand:
318 url = item.data(0, self.__urlRole) 320 url = item.data(0, self.__urlRole)
319 self.__listRepo(url, item) 321 self.__listRepo(url, item)
320 322
321 @pyqtSlot(QTreeWidgetItem) 323 @pyqtSlot(QTreeWidgetItem)
322 def on_repoTree_itemCollapsed(self, item): 324 def on_repoTree_itemCollapsed(self, item):
323 """ 325 """
324 Private slot called when an item is collapsed. 326 Private slot called when an item is collapsed.
325 327
326 @param item reference to the item to be collapsed (QTreeWidgetItem) 328 @param item reference to the item to be collapsed (QTreeWidgetItem)
327 """ 329 """
328 for child in item.takeChildren(): 330 for child in item.takeChildren():
329 del child 331 del child
330 332
331 @pyqtSlot() 333 @pyqtSlot()
332 def on_repoTree_itemSelectionChanged(self): 334 def on_repoTree_itemSelectionChanged(self):
333 """ 335 """
334 Private slot called when the selection changes. 336 Private slot called when the selection changes.
335 """ 337 """
336 if self.mode == "select": 338 if self.mode == "select":
337 self.buttonBox.button( 339 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(True)
338 QDialogButtonBox.StandardButton.Ok).setEnabled(True) 340
339
340 def accept(self): 341 def accept(self):
341 """ 342 """
342 Public slot called when the dialog is accepted. 343 Public slot called when the dialog is accepted.
343 """ 344 """
344 if self.focusWidget() == self.urlCombo: 345 if self.focusWidget() == self.urlCombo:
345 return 346 return
346 347
347 super().accept() 348 super().accept()
348 349
349 def getSelectedUrl(self): 350 def getSelectedUrl(self):
350 """ 351 """
351 Public method to retrieve the selected repository URL. 352 Public method to retrieve the selected repository URL.
352 353
353 @return the selected repository URL (string) 354 @return the selected repository URL (string)
354 """ 355 """
355 items = self.repoTree.selectedItems() 356 items = self.repoTree.selectedItems()
356 if len(items) == 1: 357 if len(items) == 1:
357 return items[0].data(0, self.__urlRole) 358 return items[0].data(0, self.__urlRole)
358 else: 359 else:
359 return "" 360 return ""
360 361
361 def __finish(self): 362 def __finish(self):
362 """ 363 """
363 Private slot called when the process finished or the user pressed the 364 Private slot called when the process finished or the user pressed the
364 button. 365 button.
365 """ 366 """
366 if ( 367 if (
367 self.__process is not None and 368 self.__process is not None
368 self.__process.state() != QProcess.ProcessState.NotRunning 369 and self.__process.state() != QProcess.ProcessState.NotRunning
369 ): 370 ):
370 self.__process.terminate() 371 self.__process.terminate()
371 QTimer.singleShot(2000, self.__process.kill) 372 QTimer.singleShot(2000, self.__process.kill)
372 self.__process.waitForFinished(3000) 373 self.__process.waitForFinished(3000)
373 374
374 self.inputGroup.setEnabled(False) 375 self.inputGroup.setEnabled(False)
375 self.inputGroup.hide() 376 self.inputGroup.hide()
376 377
377 self.__resizeColumns() 378 self.__resizeColumns()
378 self.__resort() 379 self.__resort()
379 380
380 def __procFinished(self, exitCode, exitStatus): 381 def __procFinished(self, exitCode, exitStatus):
381 """ 382 """
382 Private slot connected to the finished signal. 383 Private slot connected to the finished signal.
383 384
384 @param exitCode exit code of the process (integer) 385 @param exitCode exit code of the process (integer)
385 @param exitStatus exit status of the process (QProcess.ExitStatus) 386 @param exitStatus exit status of the process (QProcess.ExitStatus)
386 """ 387 """
387 self.__finish() 388 self.__finish()
388 389
389 def __readStdout(self): 390 def __readStdout(self):
390 """ 391 """
391 Private slot to handle the readyReadStandardOutput signal. 392 Private slot to handle the readyReadStandardOutput signal.
392 393
393 It reads the output of the process, formats it and inserts it into 394 It reads the output of the process, formats it and inserts it into
394 the contents pane. 395 the contents pane.
395 """ 396 """
396 if self.__process is not None: 397 if self.__process is not None:
397 self.__process.setReadChannel( 398 self.__process.setReadChannel(QProcess.ProcessChannel.StandardOutput)
398 QProcess.ProcessChannel.StandardOutput) 399
399
400 while self.__process.canReadLine(): 400 while self.__process.canReadLine():
401 s = str(self.__process.readLine(), 401 s = str(
402 Preferences.getSystem("IOEncoding"), 402 self.__process.readLine(),
403 'replace') 403 Preferences.getSystem("IOEncoding"),
404 match = ( 404 "replace",
405 self.__rx_dir.fullmatch(s) or
406 self.__rx_file.fullmatch(s)
407 ) 405 )
406 match = self.__rx_dir.fullmatch(s) or self.__rx_file.fullmatch(s)
408 if match is None: 407 if match is None:
409 continue 408 continue
410 elif match.re is self.__rx_dir: 409 elif match.re is self.__rx_dir:
411 revision = match.group(1) 410 revision = match.group(1)
412 author = match.group(2) 411 author = match.group(2)
423 author = match.group(2) 422 author = match.group(2)
424 size = match.group(3) 423 size = match.group(3)
425 date = match.group(4) 424 date = match.group(4)
426 name = match.group(5).strip() 425 name = match.group(5).strip()
427 nodekind = "file" 426 nodekind = "file"
428 427
429 url = "{0}/{1}".format(self.repoUrl, name) 428 url = "{0}/{1}".format(self.repoUrl, name)
430 self.__generateItem( 429 self.__generateItem(name, revision, author, size, date, nodekind, url)
431 name, revision, author, size, date, nodekind, url) 430
432
433 def __readStderr(self): 431 def __readStderr(self):
434 """ 432 """
435 Private slot to handle the readyReadStandardError signal. 433 Private slot to handle the readyReadStandardError signal.
436 434
437 It reads the error output of the process and inserts it into the 435 It reads the error output of the process and inserts it into the
438 error pane. 436 error pane.
439 """ 437 """
440 if self.__process is not None: 438 if self.__process is not None:
441 s = str(self.__process.readAllStandardError(), 439 s = str(
442 Preferences.getSystem("IOEncoding"), 440 self.__process.readAllStandardError(),
443 'replace') 441 Preferences.getSystem("IOEncoding"),
442 "replace",
443 )
444 self.errors.insertPlainText(s) 444 self.errors.insertPlainText(s)
445 self.errors.ensureCursorVisible() 445 self.errors.ensureCursorVisible()
446 self.errorGroup.show() 446 self.errorGroup.show()
447 447
448 def on_passwordCheckBox_toggled(self, isOn): 448 def on_passwordCheckBox_toggled(self, isOn):
449 """ 449 """
450 Private slot to handle the password checkbox toggled. 450 Private slot to handle the password checkbox toggled.
451 451
452 @param isOn flag indicating the status of the check box (boolean) 452 @param isOn flag indicating the status of the check box (boolean)
453 """ 453 """
454 if isOn: 454 if isOn:
455 self.input.setEchoMode(QLineEdit.EchoMode.Password) 455 self.input.setEchoMode(QLineEdit.EchoMode.Password)
456 else: 456 else:
457 self.input.setEchoMode(QLineEdit.EchoMode.Normal) 457 self.input.setEchoMode(QLineEdit.EchoMode.Normal)
458 458
459 @pyqtSlot() 459 @pyqtSlot()
460 def on_sendButton_clicked(self): 460 def on_sendButton_clicked(self):
461 """ 461 """
462 Private slot to send the input to the subversion process. 462 Private slot to send the input to the subversion process.
463 """ 463 """
464 inputTxt = self.input.text() 464 inputTxt = self.input.text()
465 inputTxt += os.linesep 465 inputTxt += os.linesep
466 466
467 if self.passwordCheckBox.isChecked(): 467 if self.passwordCheckBox.isChecked():
468 self.errors.insertPlainText(os.linesep) 468 self.errors.insertPlainText(os.linesep)
469 self.errors.ensureCursorVisible() 469 self.errors.ensureCursorVisible()
470 else: 470 else:
471 self.errors.insertPlainText(inputTxt) 471 self.errors.insertPlainText(inputTxt)
472 self.errors.ensureCursorVisible() 472 self.errors.ensureCursorVisible()
473 473
474 self.__process.write(strToQByteArray(inputTxt)) 474 self.__process.write(strToQByteArray(inputTxt))
475 475
476 self.passwordCheckBox.setChecked(False) 476 self.passwordCheckBox.setChecked(False)
477 self.input.clear() 477 self.input.clear()
478 478
479 def on_input_returnPressed(self): 479 def on_input_returnPressed(self):
480 """ 480 """
481 Private slot to handle the press of the return key in the input field. 481 Private slot to handle the press of the return key in the input field.
482 """ 482 """
483 self.intercept = True 483 self.intercept = True
484 self.on_sendButton_clicked() 484 self.on_sendButton_clicked()
485 485
486 def keyPressEvent(self, evt): 486 def keyPressEvent(self, evt):
487 """ 487 """
488 Protected slot to handle a key press event. 488 Protected slot to handle a key press event.
489 489
490 @param evt the key press event (QKeyEvent) 490 @param evt the key press event (QKeyEvent)
491 """ 491 """
492 if self.intercept: 492 if self.intercept:
493 self.intercept = False 493 self.intercept = False
494 evt.accept() 494 evt.accept()

eric ide

mercurial