eric6/Plugins/VcsPlugins/vcsSubversion/SvnLogBrowserDialog.py

changeset 7775
4a1db75550bd
parent 7771
787a6b3f8c9f
child 7900
72b88fb20261
child 7924
8a96736d465e
equal deleted inserted replaced
7774:9eed155411f0 7775:4a1db75550bd
5 5
6 """ 6 """
7 Module implementing a dialog to browse the log history. 7 Module implementing a dialog to browse the log history.
8 """ 8 """
9 9
10 10 import re
11 import os 11 import os
12 12
13 from PyQt5.QtCore import ( 13 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QDate, QProcess, QPoint
14 QTimer, QDate, QProcess, QRegExp, Qt, pyqtSlot, QPoint
15 )
16 from PyQt5.QtWidgets import ( 14 from PyQt5.QtWidgets import (
17 QHeaderView, QLineEdit, QWidget, QApplication, QDialogButtonBox, 15 QHeaderView, QLineEdit, QWidget, QApplication, QDialogButtonBox,
18 QTreeWidgetItem 16 QTreeWidgetItem
19 ) 17 )
20 18
67 self.__process = E5OverrideCursorProcess() 65 self.__process = E5OverrideCursorProcess()
68 self.__process.finished.connect(self.__procFinished) 66 self.__process.finished.connect(self.__procFinished)
69 self.__process.readyReadStandardOutput.connect(self.__readStdout) 67 self.__process.readyReadStandardOutput.connect(self.__readStdout)
70 self.__process.readyReadStandardError.connect(self.__readStderr) 68 self.__process.readyReadStandardError.connect(self.__readStderr)
71 69
72 self.rx_sep1 = QRegExp('\\-+\\s*') 70 self.rx_sep1 = re.compile('\\-+\\s*')
73 self.rx_sep2 = QRegExp('=+\\s*') 71 self.rx_sep2 = re.compile('=+\\s*')
74 self.rx_rev1 = QRegExp( 72 self.rx_rev1 = re.compile(
75 r'rev ([0-9]+): ([^|]*) \| ([^|]*) \| ([0-9]+) .*') 73 r'rev ([0-9]+): ([^|]*) \| ([^|]*) \| ([0-9]+) .*')
76 # "rev" followed by one or more decimals followed by a colon followed 74 # "rev" followed by one or more decimals followed by a colon followed
77 # anything up to " | " (twice) followed by one or more decimals 75 # anything up to " | " (twice) followed by one or more decimals
78 # followed by anything 76 # followed by anything
79 self.rx_rev2 = QRegExp( 77 self.rx_rev2 = re.compile(
80 r'r([0-9]+) \| ([^|]*) \| ([^|]*) \| ([0-9]+) .*') 78 r'r([0-9]+) \| ([^|]*) \| ([^|]*) \| ([0-9]+) .*')
81 # "r" followed by one or more decimals followed by " | " followed 79 # "r" followed by one or more decimals followed by " | " followed
82 # anything up to " | " (twice) followed by one or more decimals 80 # anything up to " | " (twice) followed by one or more decimals
83 # followed by anything 81 # followed by anything
84 self.rx_flags1 = QRegExp( 82 self.rx_flags1 = re.compile(
85 r""" ([ADM])\s(.*)\s+\(\w+\s+(.*):([0-9]+)\)\s*""") 83 r""" ([ADM])\s(.*)\s+\(\w+\s+(.*):([0-9]+)\)\s*""")
86 # three blanks followed by A or D or M followed by path followed by 84 # three blanks followed by A or D or M followed by path followed by
87 # path copied from followed by copied from revision 85 # path copied from followed by copied from revision
88 self.rx_flags2 = QRegExp(' ([ADM]) (.*)\\s*') 86 self.rx_flags2 = re.compile(' ([ADM]) (.*)\\s*')
89 # three blanks followed by A or D or M followed by path 87 # three blanks followed by A or D or M followed by path
90 88
91 self.flags = { 89 self.flags = {
92 'A': self.tr('Added'), 90 'A': self.tr('Added'),
93 'D': self.tr('Deleted'), 91 'D': self.tr('Deleted'),
381 """ 379 """
382 noEntries = 0 380 noEntries = 0
383 log = {"message": []} 381 log = {"message": []}
384 changedPaths = [] 382 changedPaths = []
385 for s in self.buf: 383 for s in self.buf:
386 if self.rx_rev1.exactMatch(s): 384 match = (
387 log["revision"] = self.rx_rev.cap(1) 385 self.rx_rev1.fullmatch(s) or
388 log["author"] = self.rx_rev.cap(2) 386 self.rx_rev2.fullmatch(s) or
389 log["date"] = self.rx_rev.cap(3) 387 self.rx_flags1.fullmatch(s) or
388 self.rx_flags2.fullmatch(s) or
389 self.rx_sep1.fullmatch(s) or
390 self.rx_sep2.fullmatch(s)
391 )
392 if match is None:
393 if s.strip().endswith(":") or not s.strip():
394 continue
395 else:
396 log["message"].append(s)
397 elif match.re is self.rx_rev1:
398 log["revision"] = match.group(1)
399 log["author"] = match.group(2)
400 log["date"] = match.group(3)
390 # number of lines is ignored 401 # number of lines is ignored
391 elif self.rx_rev2.exactMatch(s): 402 elif match.re is self.rx_rev2:
392 log["revision"] = self.rx_rev2.cap(1) 403 log["revision"] = match.group(1)
393 log["author"] = self.rx_rev2.cap(2) 404 log["author"] = match.group(2)
394 log["date"] = " ".join(self.rx_rev2.cap(3).split()[:2]) 405 log["date"] = " ".join(match.group(3).split()[:2])
395 # number of lines is ignored 406 # number of lines is ignored
396 elif self.rx_flags1.exactMatch(s): 407 elif match.re is self.rx_flags1:
397 changedPaths.append({ 408 changedPaths.append({
398 "action": 409 "action": match.group(1).strip(),
399 self.rx_flags1.cap(1).strip(), 410 "path": match.group(2).strip(),
400 "path": 411 "copyfrom_path": match.group(3).strip(),
401 self.rx_flags1.cap(2).strip(), 412 "copyfrom_revision": match.group(4).strip(),
402 "copyfrom_path":
403 self.rx_flags1.cap(3).strip(),
404 "copyfrom_revision":
405 self.rx_flags1.cap(4).strip(),
406 }) 413 })
407 elif self.rx_flags2.exactMatch(s): 414 elif match.re is self.rx_flags2:
408 changedPaths.append({ 415 changedPaths.append({
409 "action": 416 "action": match.group(1).strip(),
410 self.rx_flags2.cap(1).strip(), 417 "path": match.group(2).strip(),
411 "path":
412 self.rx_flags2.cap(2).strip(),
413 "copyfrom_path": "", 418 "copyfrom_path": "",
414 "copyfrom_revision": "", 419 "copyfrom_revision": "",
415 }) 420 })
416 elif self.rx_sep1.exactMatch(s) or self.rx_sep2.exactMatch(s): 421 elif (
422 match.re is self.rx_sep1 or
423 match.re is self.rx_sep2
424 ):
417 if len(log) > 1: 425 if len(log) > 1:
418 self.__generateLogItem( 426 self.__generateLogItem(
419 log["author"], log["date"], log["message"], 427 log["author"], log["date"], log["message"],
420 log["revision"], changedPaths) 428 log["revision"], changedPaths)
421 dt = QDate.fromString(log["date"], Qt.ISODate) 429 dt = QDate.fromString(log["date"], Qt.ISODate)
431 if self.__minDate > dt: 439 if self.__minDate > dt:
432 self.__minDate = dt 440 self.__minDate = dt
433 noEntries += 1 441 noEntries += 1
434 log = {"message": []} 442 log = {"message": []}
435 changedPaths = [] 443 changedPaths = []
436 else:
437 if s.strip().endswith(":") or not s.strip():
438 continue
439 else:
440 log["message"].append(s)
441 444
442 self.__resizeColumnsLog() 445 self.__resizeColumnsLog()
443 self.__resortLog() 446 self.__resortLog()
444 447
445 if self.__started: 448 if self.__started:
655 from_ = self.fromDate.date().toString("yyyy-MM-dd") 658 from_ = self.fromDate.date().toString("yyyy-MM-dd")
656 to_ = self.toDate.date().addDays(1).toString("yyyy-MM-dd") 659 to_ = self.toDate.date().addDays(1).toString("yyyy-MM-dd")
657 txt = self.fieldCombo.currentText() 660 txt = self.fieldCombo.currentText()
658 if txt == self.tr("Author"): 661 if txt == self.tr("Author"):
659 fieldIndex = 1 662 fieldIndex = 1
660 searchRx = QRegExp(self.rxEdit.text(), Qt.CaseInsensitive) 663 searchRx = re.compile(self.rxEdit.text(), re.IGNORECASE)
661 elif txt == self.tr("Revision"): 664 elif txt == self.tr("Revision"):
662 fieldIndex = 0 665 fieldIndex = 0
663 txt = self.rxEdit.text() 666 txt = self.rxEdit.text()
664 if txt.startswith("^"): 667 if txt.startswith("^"):
665 searchRx = QRegExp( 668 searchRx = re.compile(
666 r"^\s*{0}".format(txt[1:]), Qt.CaseInsensitive) 669 r"^\s*{0}".format(txt[1:]), re.IGNORECASE)
667 else: 670 else:
668 searchRx = QRegExp(txt, Qt.CaseInsensitive) 671 searchRx = re.compile(txt, re.IGNORECASE)
669 else: 672 else:
670 fieldIndex = 3 673 fieldIndex = 3
671 searchRx = QRegExp(self.rxEdit.text(), Qt.CaseInsensitive) 674 searchRx = re.compile(self.rxEdit.text(), re.IGNORECASE)
672 675
673 currentItem = self.logTree.currentItem() 676 currentItem = self.logTree.currentItem()
674 for topIndex in range(self.logTree.topLevelItemCount()): 677 for topIndex in range(self.logTree.topLevelItemCount()):
675 topItem = self.logTree.topLevelItem(topIndex) 678 topItem = self.logTree.topLevelItem(topIndex)
676 if ( 679 if (
677 topItem.text(2) <= to_ and 680 topItem.text(2) <= to_ and
678 topItem.text(2) >= from_ and 681 topItem.text(2) >= from_ and
679 searchRx.indexIn(topItem.text(fieldIndex)) > -1 682 searchRx.match(topItem.text(fieldIndex)) is not None
680 ): 683 ):
681 topItem.setHidden(False) 684 topItem.setHidden(False)
682 if topItem is currentItem: 685 if topItem is currentItem:
683 self.on_logTree_currentItemChanged(topItem, None) 686 self.on_logTree_currentItemChanged(topItem, None)
684 else: 687 else:

eric ide

mercurial