eric6/Plugins/VcsPlugins/vcsSubversion/SvnLogBrowserDialog.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7192
a22eee00b052
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2007 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to browse the log history.
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 PyQt5.QtCore import QTimer, QDate, QProcess, QRegExp, Qt, pyqtSlot, \
19 QPoint
20 from PyQt5.QtGui import QCursor
21 from PyQt5.QtWidgets import QHeaderView, QLineEdit, QWidget, QApplication, \
22 QDialogButtonBox, QTreeWidgetItem
23
24 from E5Gui import E5MessageBox
25
26 from .Ui_SvnLogBrowserDialog import Ui_SvnLogBrowserDialog
27
28 import Preferences
29 import UI.PixmapCache
30 from Globals import strToQByteArray
31
32
33 class SvnLogBrowserDialog(QWidget, Ui_SvnLogBrowserDialog):
34 """
35 Class implementing a dialog to browse the log history.
36 """
37 def __init__(self, vcs, parent=None):
38 """
39 Constructor
40
41 @param vcs reference to the vcs object
42 @param parent parent widget (QWidget)
43 """
44 super(SvnLogBrowserDialog, self).__init__(parent)
45 self.setupUi(self)
46
47 self.__position = QPoint()
48
49 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
50 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
51
52 self.upButton.setIcon(UI.PixmapCache.getIcon("1uparrow.png"))
53 self.downButton.setIcon(UI.PixmapCache.getIcon("1downarrow.png"))
54
55 self.filesTree.headerItem().setText(self.filesTree.columnCount(), "")
56 self.filesTree.header().setSortIndicator(0, Qt.AscendingOrder)
57
58 self.vcs = vcs
59
60 self.__initData()
61
62 self.fromDate.setDisplayFormat("yyyy-MM-dd")
63 self.toDate.setDisplayFormat("yyyy-MM-dd")
64 self.__resetUI()
65
66 self.__messageRole = Qt.UserRole
67 self.__changesRole = Qt.UserRole + 1
68
69 self.process = QProcess()
70 self.process.finished.connect(self.__procFinished)
71 self.process.readyReadStandardOutput.connect(self.__readStdout)
72 self.process.readyReadStandardError.connect(self.__readStderr)
73
74 self.rx_sep1 = QRegExp('\\-+\\s*')
75 self.rx_sep2 = QRegExp('=+\\s*')
76 self.rx_rev1 = QRegExp(
77 r'rev ([0-9]+): ([^|]*) \| ([^|]*) \| ([0-9]+) .*')
78 # "rev" followed by one or more decimals followed by a colon followed
79 # anything up to " | " (twice) followed by one or more decimals
80 # followed by anything
81 self.rx_rev2 = QRegExp(
82 r'r([0-9]+) \| ([^|]*) \| ([^|]*) \| ([0-9]+) .*')
83 # "r" followed by one or more decimals followed by " | " followed
84 # anything up to " | " (twice) followed by one or more decimals
85 # followed by anything
86 self.rx_flags1 = QRegExp(
87 r""" ([ADM])\s(.*)\s+\(\w+\s+(.*):([0-9]+)\)\s*""")
88 # three blanks followed by A or D or M followed by path followed by
89 # path copied from followed by copied from revision
90 self.rx_flags2 = QRegExp(' ([ADM]) (.*)\\s*')
91 # three blanks followed by A or D or M followed by path
92
93 self.flags = {
94 'A': self.tr('Added'),
95 'D': self.tr('Deleted'),
96 'M': self.tr('Modified'),
97 'R': self.tr('Replaced'),
98 }
99 self.intercept = False
100
101 self.__logTreeNormalFont = self.logTree.font()
102 self.__logTreeNormalFont.setBold(False)
103 self.__logTreeBoldFont = self.logTree.font()
104 self.__logTreeBoldFont.setBold(True)
105
106 self.__finishCallbacks = []
107
108 def __addFinishCallback(self, callback):
109 """
110 Private method to add a method to be called once the process finished.
111
112 The callback methods are invoke in a FIFO style and are consumed. If
113 a callback method needs to be called again, it must be added again.
114
115 @param callback callback method
116 @type function
117 """
118 if callback not in self.__finishCallbacks:
119 self.__finishCallbacks.append(callback)
120
121 def __initData(self):
122 """
123 Private method to (re-)initialize some data.
124 """
125 self.__maxDate = QDate()
126 self.__minDate = QDate()
127 self.__filterLogsEnabled = True
128
129 self.buf = [] # buffer for stdout
130 self.diff = None
131 self.__started = False
132 self.__lastRev = 0
133
134 def closeEvent(self, e):
135 """
136 Protected slot implementing a close event handler.
137
138 @param e close event (QCloseEvent)
139 """
140 if self.process is not None and \
141 self.process.state() != QProcess.NotRunning:
142 self.process.terminate()
143 QTimer.singleShot(2000, self.process.kill)
144 self.process.waitForFinished(3000)
145
146 self.__position = self.pos()
147
148 e.accept()
149
150 def show(self):
151 """
152 Public slot to show the dialog.
153 """
154 if not self.__position.isNull():
155 self.move(self.__position)
156 self.__resetUI()
157
158 super(SvnLogBrowserDialog, self).show()
159
160 def __resetUI(self):
161 """
162 Private method to reset the user interface.
163 """
164 self.fromDate.setDate(QDate.currentDate())
165 self.toDate.setDate(QDate.currentDate())
166 self.fieldCombo.setCurrentIndex(self.fieldCombo.findText(
167 self.tr("Message")))
168 self.limitSpinBox.setValue(self.vcs.getPlugin().getPreferences(
169 "LogLimit"))
170 self.stopCheckBox.setChecked(self.vcs.getPlugin().getPreferences(
171 "StopLogOnCopy"))
172
173 self.logTree.clear()
174
175 self.nextButton.setEnabled(True)
176 self.limitSpinBox.setEnabled(True)
177
178 def __resizeColumnsLog(self):
179 """
180 Private method to resize the log tree columns.
181 """
182 self.logTree.header().resizeSections(QHeaderView.ResizeToContents)
183 self.logTree.header().setStretchLastSection(True)
184
185 def __resortLog(self):
186 """
187 Private method to resort the log tree.
188 """
189 self.logTree.sortItems(
190 self.logTree.sortColumn(),
191 self.logTree.header().sortIndicatorOrder())
192
193 def __resizeColumnsFiles(self):
194 """
195 Private method to resize the changed files tree columns.
196 """
197 self.filesTree.header().resizeSections(QHeaderView.ResizeToContents)
198 self.filesTree.header().setStretchLastSection(True)
199
200 def __resortFiles(self):
201 """
202 Private method to resort the changed files tree.
203 """
204 sortColumn = self.filesTree.sortColumn()
205 self.filesTree.sortItems(
206 1, self.filesTree.header().sortIndicatorOrder())
207 self.filesTree.sortItems(
208 sortColumn, self.filesTree.header().sortIndicatorOrder())
209
210 def __generateLogItem(self, author, date, message, revision, changedPaths):
211 """
212 Private method to generate a log tree entry.
213
214 @param author author info (string)
215 @param date date info (string)
216 @param message text of the log message (list of strings)
217 @param revision revision info (string)
218 @param changedPaths list of dictionary objects containing
219 info about the changed files/directories
220 @return reference to the generated item (QTreeWidgetItem)
221 """
222 msg = []
223 for line in message:
224 msg.append(line.strip())
225
226 itm = QTreeWidgetItem(self.logTree)
227 itm.setData(0, Qt.DisplayRole, int(revision))
228 itm.setData(1, Qt.DisplayRole, author)
229 itm.setData(2, Qt.DisplayRole, date)
230 itm.setData(3, Qt.DisplayRole, " ".join(msg))
231
232 itm.setData(0, self.__messageRole, message)
233 itm.setData(0, self.__changesRole, changedPaths)
234
235 itm.setTextAlignment(0, Qt.AlignRight)
236 itm.setTextAlignment(1, Qt.AlignLeft)
237 itm.setTextAlignment(2, Qt.AlignLeft)
238 itm.setTextAlignment(3, Qt.AlignLeft)
239 itm.setTextAlignment(4, Qt.AlignLeft)
240
241 try:
242 self.__lastRev = int(revision)
243 except ValueError:
244 self.__lastRev = 0
245
246 return itm
247
248 def __generateFileItem(self, action, path, copyFrom, copyRev):
249 """
250 Private method to generate a changed files tree entry.
251
252 @param action indicator for the change action ("A", "D" or "M")
253 @param path path of the file in the repository (string)
254 @param copyFrom path the file was copied from (None, string)
255 @param copyRev revision the file was copied from (None, string)
256 @return reference to the generated item (QTreeWidgetItem)
257 """
258 itm = QTreeWidgetItem(self.filesTree, [
259 self.flags[action],
260 path,
261 copyFrom,
262 copyRev,
263 ])
264
265 itm.setTextAlignment(3, Qt.AlignRight)
266
267 return itm
268
269 def __getLogEntries(self, startRev=None):
270 """
271 Private method to retrieve log entries from the repository.
272
273 @param startRev revision number to start from (integer, string)
274 """
275 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
276 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
277 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
278 QApplication.processEvents()
279
280 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
281 QApplication.processEvents()
282
283 self.intercept = False
284 self.process.kill()
285
286 self.buf = []
287 self.cancelled = False
288 self.errors.clear()
289
290 args = []
291 args.append('log')
292 self.vcs.addArguments(args, self.vcs.options['global'])
293 self.vcs.addArguments(args, self.vcs.options['log'])
294 args.append('--verbose')
295 args.append('--limit')
296 args.append('{0:d}'.format(self.limitSpinBox.value()))
297 if startRev is not None:
298 args.append('--revision')
299 args.append('{0}:0'.format(startRev))
300 if self.stopCheckBox.isChecked():
301 args.append('--stop-on-copy')
302 args.append(self.fname)
303
304 self.process.setWorkingDirectory(self.dname)
305
306 self.inputGroup.setEnabled(True)
307 self.inputGroup.show()
308
309 self.process.start('svn', args)
310 procStarted = self.process.waitForStarted(5000)
311 if not procStarted:
312 self.inputGroup.setEnabled(False)
313 self.inputGroup.hide()
314 E5MessageBox.critical(
315 self,
316 self.tr('Process Generation Error'),
317 self.tr(
318 'The process {0} could not be started. '
319 'Ensure, that it is in the search path.'
320 ).format('svn'))
321
322 def start(self, fn, isFile=False):
323 """
324 Public slot to start the svn log command.
325
326 @param fn filename to show the log for (string)
327 @keyparam isFile flag indicating log for a file is to be shown
328 (boolean)
329 """
330 self.sbsCheckBox.setEnabled(isFile)
331 self.sbsCheckBox.setVisible(isFile)
332
333 self.errorGroup.hide()
334 QApplication.processEvents()
335
336 self.__initData()
337
338 self.filename = fn
339 self.dname, self.fname = self.vcs.splitPath(fn)
340
341 self.activateWindow()
342 self.raise_()
343
344 self.logTree.clear()
345 self.__started = True
346 self.__getLogEntries()
347
348 def __procFinished(self, exitCode, exitStatus):
349 """
350 Private slot connected to the finished signal.
351
352 @param exitCode exit code of the process (integer)
353 @param exitStatus exit status of the process (QProcess.ExitStatus)
354 """
355 self.__processBuffer()
356 self.__finish()
357
358 def __finish(self):
359 """
360 Private slot called when the process finished or the user pressed the
361 button.
362 """
363 if self.process is not None and \
364 self.process.state() != QProcess.NotRunning:
365 self.process.terminate()
366 QTimer.singleShot(2000, self.process.kill)
367 self.process.waitForFinished(3000)
368
369 QApplication.restoreOverrideCursor()
370
371 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
372 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
373 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
374
375 self.inputGroup.setEnabled(False)
376 self.inputGroup.hide()
377
378 while self.__finishCallbacks:
379 self.__finishCallbacks.pop(0)()
380
381 def __processBuffer(self):
382 """
383 Private method to process the buffered output of the svn log command.
384 """
385 noEntries = 0
386 log = {"message": []}
387 changedPaths = []
388 for s in self.buf:
389 if self.rx_rev1.exactMatch(s):
390 log["revision"] = self.rx_rev.cap(1)
391 log["author"] = self.rx_rev.cap(2)
392 log["date"] = self.rx_rev.cap(3)
393 # number of lines is ignored
394 elif self.rx_rev2.exactMatch(s):
395 log["revision"] = self.rx_rev2.cap(1)
396 log["author"] = self.rx_rev2.cap(2)
397 log["date"] = " ".join(self.rx_rev2.cap(3).split()[:2])
398 # number of lines is ignored
399 elif self.rx_flags1.exactMatch(s):
400 changedPaths.append({
401 "action":
402 self.rx_flags1.cap(1).strip(),
403 "path":
404 self.rx_flags1.cap(2).strip(),
405 "copyfrom_path":
406 self.rx_flags1.cap(3).strip(),
407 "copyfrom_revision":
408 self.rx_flags1.cap(4).strip(),
409 })
410 elif self.rx_flags2.exactMatch(s):
411 changedPaths.append({
412 "action":
413 self.rx_flags2.cap(1).strip(),
414 "path":
415 self.rx_flags2.cap(2).strip(),
416 "copyfrom_path": "",
417 "copyfrom_revision": "",
418 })
419 elif self.rx_sep1.exactMatch(s) or self.rx_sep2.exactMatch(s):
420 if len(log) > 1:
421 self.__generateLogItem(
422 log["author"], log["date"], log["message"],
423 log["revision"], changedPaths)
424 dt = QDate.fromString(log["date"], Qt.ISODate)
425 if not self.__maxDate.isValid() and \
426 not self.__minDate.isValid():
427 self.__maxDate = dt
428 self.__minDate = dt
429 else:
430 if self.__maxDate < dt:
431 self.__maxDate = dt
432 if self.__minDate > dt:
433 self.__minDate = dt
434 noEntries += 1
435 log = {"message": []}
436 changedPaths = []
437 else:
438 if s.strip().endswith(":") or not s.strip():
439 continue
440 else:
441 log["message"].append(s)
442
443 self.__resizeColumnsLog()
444 self.__resortLog()
445
446 if self.__started:
447 self.logTree.setCurrentItem(self.logTree.topLevelItem(0))
448 self.__started = False
449
450 if noEntries < self.limitSpinBox.value() and not self.cancelled:
451 self.nextButton.setEnabled(False)
452 self.limitSpinBox.setEnabled(False)
453
454 self.__filterLogsEnabled = False
455 self.fromDate.setMinimumDate(self.__minDate)
456 self.fromDate.setMaximumDate(self.__maxDate)
457 self.fromDate.setDate(self.__minDate)
458 self.toDate.setMinimumDate(self.__minDate)
459 self.toDate.setMaximumDate(self.__maxDate)
460 self.toDate.setDate(self.__maxDate)
461 self.__filterLogsEnabled = True
462 self.__filterLogs()
463
464 def __readStdout(self):
465 """
466 Private slot to handle the readyReadStandardOutput signal.
467
468 It reads the output of the process and inserts it into a buffer.
469 """
470 self.process.setReadChannel(QProcess.StandardOutput)
471
472 while self.process.canReadLine():
473 line = str(self.process.readLine(),
474 Preferences.getSystem("IOEncoding"),
475 'replace')
476 self.buf.append(line)
477
478 def __readStderr(self):
479 """
480 Private slot to handle the readyReadStandardError signal.
481
482 It reads the error output of the process and inserts it into the
483 error pane.
484 """
485 if self.process is not None:
486 self.errorGroup.show()
487 s = str(self.process.readAllStandardError(),
488 Preferences.getSystem("IOEncoding"),
489 'replace')
490 self.errors.insertPlainText(s)
491 self.errors.ensureCursorVisible()
492
493 def __diffRevisions(self, rev1, rev2):
494 """
495 Private method to do a diff of two revisions.
496
497 @param rev1 first revision number (integer)
498 @param rev2 second revision number (integer)
499 """
500 if self.sbsCheckBox.isEnabled() and self.sbsCheckBox.isChecked():
501 self.vcs.svnSbsDiff(self.filename,
502 revisions=(str(rev1), str(rev2)))
503 else:
504 if self.diff is None:
505 from .SvnDiffDialog import SvnDiffDialog
506 self.diff = SvnDiffDialog(self.vcs)
507 self.diff.show()
508 self.diff.raise_()
509 self.diff.start(self.filename, [rev1, rev2])
510
511 def on_buttonBox_clicked(self, button):
512 """
513 Private slot called by a button of the button box clicked.
514
515 @param button button that was clicked (QAbstractButton)
516 """
517 if button == self.buttonBox.button(QDialogButtonBox.Close):
518 self.close()
519 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
520 self.cancelled = True
521 self.__finish()
522
523 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
524 def on_logTree_currentItemChanged(self, current, previous):
525 """
526 Private slot called, when the current item of the log tree changes.
527
528 @param current reference to the new current item (QTreeWidgetItem)
529 @param previous reference to the old current item (QTreeWidgetItem)
530 """
531 if current is not None:
532 self.messageEdit.clear()
533 for line in current.data(0, self.__messageRole):
534 self.messageEdit.append(line.strip())
535
536 self.filesTree.clear()
537 changes = current.data(0, self.__changesRole)
538 if len(changes) > 0:
539 for change in changes:
540 self.__generateFileItem(
541 change["action"], change["path"],
542 change["copyfrom_path"],
543 change["copyfrom_revision"])
544 self.__resizeColumnsFiles()
545 self.__resortFiles()
546
547 self.diffPreviousButton.setEnabled(
548 current != self.logTree.topLevelItem(
549 self.logTree.topLevelItemCount() - 1))
550
551 # Highlight the current entry using a bold font
552 for col in range(self.logTree.columnCount()):
553 current and current.setFont(col, self.__logTreeBoldFont)
554 previous and previous.setFont(col, self.__logTreeNormalFont)
555
556 # set the state of the up and down buttons
557 self.upButton.setEnabled(
558 current is not None and
559 self.logTree.indexOfTopLevelItem(current) > 0)
560 self.downButton.setEnabled(
561 current is not None and
562 int(current.text(0)) > 1)
563
564 @pyqtSlot()
565 def on_logTree_itemSelectionChanged(self):
566 """
567 Private slot called, when the selection has changed.
568 """
569 self.diffRevisionsButton.setEnabled(
570 len(self.logTree.selectedItems()) == 2)
571
572 @pyqtSlot()
573 def on_nextButton_clicked(self):
574 """
575 Private slot to handle the Next button.
576 """
577 if self.__lastRev > 1:
578 self.__getLogEntries(self.__lastRev - 1)
579
580 @pyqtSlot()
581 def on_diffPreviousButton_clicked(self):
582 """
583 Private slot to handle the Diff to Previous button.
584 """
585 itm = self.logTree.currentItem()
586 if itm is None:
587 self.diffPreviousButton.setEnabled(False)
588 return
589 rev2 = int(itm.text(0))
590
591 itm = self.logTree.topLevelItem(
592 self.logTree.indexOfTopLevelItem(itm) + 1)
593 if itm is None:
594 self.diffPreviousButton.setEnabled(False)
595 return
596 rev1 = int(itm.text(0))
597
598 self.__diffRevisions(rev1, rev2)
599
600 @pyqtSlot()
601 def on_diffRevisionsButton_clicked(self):
602 """
603 Private slot to handle the Compare Revisions button.
604 """
605 items = self.logTree.selectedItems()
606 if len(items) != 2:
607 self.diffRevisionsButton.setEnabled(False)
608 return
609
610 rev2 = int(items[0].text(0))
611 rev1 = int(items[1].text(0))
612
613 self.__diffRevisions(min(rev1, rev2), max(rev1, rev2))
614
615 @pyqtSlot(QDate)
616 def on_fromDate_dateChanged(self, date):
617 """
618 Private slot called, when the from date changes.
619
620 @param date new date (QDate)
621 """
622 self.__filterLogs()
623
624 @pyqtSlot(QDate)
625 def on_toDate_dateChanged(self, date):
626 """
627 Private slot called, when the from date changes.
628
629 @param date new date (QDate)
630 """
631 self.__filterLogs()
632
633 @pyqtSlot(str)
634 def on_fieldCombo_activated(self, txt):
635 """
636 Private slot called, when a new filter field is selected.
637
638 @param txt text of the selected field (string)
639 """
640 self.__filterLogs()
641
642 @pyqtSlot(str)
643 def on_rxEdit_textChanged(self, txt):
644 """
645 Private slot called, when a filter expression is entered.
646
647 @param txt filter expression (string)
648 """
649 self.__filterLogs()
650
651 def __filterLogs(self):
652 """
653 Private method to filter the log entries.
654 """
655 if self.__filterLogsEnabled:
656 from_ = self.fromDate.date().toString("yyyy-MM-dd")
657 to_ = self.toDate.date().addDays(1).toString("yyyy-MM-dd")
658 txt = self.fieldCombo.currentText()
659 if txt == self.tr("Author"):
660 fieldIndex = 1
661 searchRx = QRegExp(self.rxEdit.text(), Qt.CaseInsensitive)
662 elif txt == self.tr("Revision"):
663 fieldIndex = 0
664 txt = self.rxEdit.text()
665 if txt.startswith("^"):
666 searchRx = QRegExp(
667 r"^\s*{0}".format(txt[1:]), Qt.CaseInsensitive)
668 else:
669 searchRx = QRegExp(txt, Qt.CaseInsensitive)
670 else:
671 fieldIndex = 3
672 searchRx = QRegExp(self.rxEdit.text(), Qt.CaseInsensitive)
673
674 currentItem = self.logTree.currentItem()
675 for topIndex in range(self.logTree.topLevelItemCount()):
676 topItem = self.logTree.topLevelItem(topIndex)
677 if topItem.text(2) <= to_ and topItem.text(2) >= from_ and \
678 searchRx.indexIn(topItem.text(fieldIndex)) > -1:
679 topItem.setHidden(False)
680 if topItem is currentItem:
681 self.on_logTree_currentItemChanged(topItem, None)
682 else:
683 topItem.setHidden(True)
684 if topItem is currentItem:
685 self.messageEdit.clear()
686 self.filesTree.clear()
687
688 @pyqtSlot(bool)
689 def on_stopCheckBox_clicked(self, checked):
690 """
691 Private slot called, when the stop on copy/move checkbox is clicked.
692
693 @param checked flag indicating the checked state (boolean)
694 """
695 self.vcs.getPlugin().setPreferences("StopLogOnCopy",
696 self.stopCheckBox.isChecked())
697 self.nextButton.setEnabled(True)
698 self.limitSpinBox.setEnabled(True)
699
700 @pyqtSlot()
701 def on_upButton_clicked(self):
702 """
703 Private slot to move the current item up one entry.
704 """
705 itm = self.logTree.itemAbove(self.logTree.currentItem())
706 if itm:
707 self.logTree.setCurrentItem(itm)
708
709 @pyqtSlot()
710 def on_downButton_clicked(self):
711 """
712 Private slot to move the current item down one entry.
713 """
714 itm = self.logTree.itemBelow(self.logTree.currentItem())
715 if itm:
716 self.logTree.setCurrentItem(itm)
717 else:
718 # load the next bunch and try again
719 self.__addFinishCallback(self.on_downButton_clicked)
720 self.on_nextButton_clicked()
721
722 def on_passwordCheckBox_toggled(self, isOn):
723 """
724 Private slot to handle the password checkbox toggled.
725
726 @param isOn flag indicating the status of the check box (boolean)
727 """
728 if isOn:
729 self.input.setEchoMode(QLineEdit.Password)
730 else:
731 self.input.setEchoMode(QLineEdit.Normal)
732
733 @pyqtSlot()
734 def on_sendButton_clicked(self):
735 """
736 Private slot to send the input to the subversion process.
737 """
738 inputTxt = self.input.text()
739 inputTxt += os.linesep
740
741 if self.passwordCheckBox.isChecked():
742 self.errors.insertPlainText(os.linesep)
743 self.errors.ensureCursorVisible()
744 else:
745 self.errors.insertPlainText(inputTxt)
746 self.errors.ensureCursorVisible()
747 self.errorGroup.show()
748
749 self.process.write(strToQByteArray(inputTxt))
750
751 self.passwordCheckBox.setChecked(False)
752 self.input.clear()
753
754 def on_input_returnPressed(self):
755 """
756 Private slot to handle the press of the return key in the input field.
757 """
758 self.intercept = True
759 self.on_sendButton_clicked()
760
761 def keyPressEvent(self, evt):
762 """
763 Protected slot to handle a key press event.
764
765 @param evt the key press event (QKeyEvent)
766 """
767 if self.intercept:
768 self.intercept = False
769 evt.accept()
770 return
771 super(SvnLogBrowserDialog, self).keyPressEvent(evt)

eric ide

mercurial