src/eric7/Plugins/VcsPlugins/vcsMercurial/HgLogBrowserDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
--- a/src/eric7/Plugins/VcsPlugins/vcsMercurial/HgLogBrowserDialog.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/Plugins/VcsPlugins/vcsMercurial/HgLogBrowserDialog.py	Wed Jul 13 14:55:47 2022 +0200
@@ -15,11 +15,24 @@
 
 from PyQt6.QtCore import pyqtSlot, Qt, QDate, QSize, QPoint
 from PyQt6.QtGui import (
-    QColor, QPixmap, QPainter, QPen, QBrush, QIcon, QTextCursor, QPalette
+    QColor,
+    QPixmap,
+    QPainter,
+    QPen,
+    QBrush,
+    QIcon,
+    QTextCursor,
+    QPalette,
 )
 from PyQt6.QtWidgets import (
-    QWidget, QDialogButtonBox, QHeaderView, QTreeWidgetItem, QApplication,
-    QLineEdit, QMenu, QInputDialog
+    QWidget,
+    QDialogButtonBox,
+    QHeaderView,
+    QTreeWidgetItem,
+    QApplication,
+    QLineEdit,
+    QMenu,
+    QInputDialog,
 )
 
 from EricWidgets.EricApplication import ericApp
@@ -35,21 +48,47 @@
 import Preferences
 import Utilities
 
-COLORNAMES = ["blue", "darkgreen", "red", "green", "darkblue", "purple",
-              "cyan", "olive", "magenta", "darkred", "darkmagenta",
-              "darkcyan", "gray", "yellow"]
+COLORNAMES = [
+    "blue",
+    "darkgreen",
+    "red",
+    "green",
+    "darkblue",
+    "purple",
+    "cyan",
+    "olive",
+    "magenta",
+    "darkred",
+    "darkmagenta",
+    "darkcyan",
+    "gray",
+    "yellow",
+]
 COLORS = [str(QColor(x).name()) for x in COLORNAMES]
 
-LIGHTCOLORS = ["#aaaaff", "#7faa7f", "#ffaaaa", "#aaffaa", "#7f7faa",
-               "#ffaaff", "#aaffff", "#d5d579", "#ffaaff", "#d57979",
-               "#d579d5", "#79d5d5", "#d5d5d5", "#d5d500",
-               ]
+LIGHTCOLORS = [
+    "#aaaaff",
+    "#7faa7f",
+    "#ffaaaa",
+    "#aaffaa",
+    "#7f7faa",
+    "#ffaaff",
+    "#aaffff",
+    "#d5d579",
+    "#ffaaff",
+    "#d57979",
+    "#d579d5",
+    "#79d5d5",
+    "#d5d5d5",
+    "#d5d500",
+]
 
 
 class HgLogBrowserDialog(QWidget, Ui_HgLogBrowserDialog):
     """
     Class implementing a dialog to browse the log history.
     """
+
     IconColumn = 0
     BranchColumn = 1
     RevisionColumn = 2
@@ -59,20 +98,20 @@
     MessageColumn = 6
     TagsColumn = 7
     BookmarksColumn = 8
-    
+
     LargefilesCacheL = ".hglf/"
     LargefilesCacheW = ".hglf\\"
     PathSeparatorRe = re.compile(r"/|\\")
-    
+
     GraftedRe = re.compile(r"\(grafted from ([0-9a-fA-F]+)\)")
     GraftedTemplate = '(grafted from <a href="chg:{0}">{0}</a>)'
-    
+
     ClosedIndicator = " \u2612"
-    
+
     def __init__(self, vcs, mode="", parent=None):
         """
         Constructor
-        
+
         @param vcs reference to the vcs object
         @type Hg
         @param mode mode of the dialog
@@ -82,23 +121,23 @@
         """
         super().__init__(parent)
         self.setupUi(self)
-        
+
         windowFlags = self.windowFlags()
         windowFlags |= Qt.WindowType.WindowContextHelpButtonHint
         self.setWindowFlags(windowFlags)
-        
+
         self.mainSplitter.setSizes([300, 400])
         self.mainSplitter.setStretchFactor(0, 1)
         self.mainSplitter.setStretchFactor(1, 2)
         self.diffSplitter.setStretchFactor(0, 1)
         self.diffSplitter.setStretchFactor(1, 2)
-        
+
         if not mode:
             if vcs.getPlugin().getPreferences("LogBrowserShowFullLog"):
                 mode = "full_log"
             else:
                 mode = "log"
-        
+
         if mode == "log":
             self.setWindowTitle(self.tr("Mercurial Log"))
         elif mode == "incoming":
@@ -107,45 +146,44 @@
             self.setWindowTitle(self.tr("Mercurial Log (Outgoing)"))
         elif mode == "full_log":
             self.setWindowTitle(self.tr("Mercurial Full Log"))
-        
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setEnabled(False)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setDefault(True)
-        
+
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
+
         self.filesTree.headerItem().setText(self.filesTree.columnCount(), "")
-        self.filesTree.header().setSortIndicator(
-            0, Qt.SortOrder.AscendingOrder)
-        
+        self.filesTree.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder)
+
         self.upButton.setIcon(UI.PixmapCache.getIcon("1uparrow"))
         self.downButton.setIcon(UI.PixmapCache.getIcon("1downarrow"))
-        
+
         self.refreshButton = self.buttonBox.addButton(
-            self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole)
+            self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole
+        )
         self.refreshButton.setToolTip(
-            self.tr("Press to refresh the list of changesets"))
+            self.tr("Press to refresh the list of changesets")
+        )
         self.refreshButton.setEnabled(False)
-        
+
         self.findPrevButton.setIcon(UI.PixmapCache.getIcon("1leftarrow"))
         self.findNextButton.setIcon(UI.PixmapCache.getIcon("1rightarrow"))
         self.__findBackwards = False
-        
+
         self.modeComboBox.addItem(self.tr("Find"), "find")
         self.modeComboBox.addItem(self.tr("Filter"), "filter")
-        
+
         self.fieldCombo.addItem(self.tr("Revision"), "revision")
         self.fieldCombo.addItem(self.tr("Author"), "author")
         self.fieldCombo.addItem(self.tr("Message"), "message")
         self.fieldCombo.addItem(self.tr("File"), "file")
         self.fieldCombo.addItem(self.tr("Phase"), "phase")
-        
+
         font = Preferences.getEditorOtherFonts("MonospacedFont")
         self.diffEdit.document().setDefaultFont(font)
-        
+
         self.diffHighlighter = HgDiffHighlighter(self.diffEdit.document())
         self.__diffGenerator = HgDiffGenerator(vcs, self)
         self.__diffGenerator.finished.connect(self.__generatorFinished)
-        
+
         self.vcs = vcs
         if mode in ("log", "incoming", "outgoing", "full_log"):
             if mode == "full_log":
@@ -157,7 +195,7 @@
             self.commandMode = "log"
             self.initialCommandMode = "log"
         self.__hgClient = vcs.getClient()
-        
+
         self.__detailsTemplate = self.tr(
             "<table>"
             "<tr><td><b>Revision</b></td><td>{0}</td></tr>"
@@ -168,36 +206,32 @@
             "<tr><td><b>Message</b></td><td>{5}</td></tr>"
             "</table>"
         )
-        self.__parentsTemplate = self.tr(
-            "<tr><td><b>Parents</b></td><td>{0}</td></tr>"
-        )
+        self.__parentsTemplate = self.tr("<tr><td><b>Parents</b></td><td>{0}</td></tr>")
         self.__childrenTemplate = self.tr(
             "<tr><td><b>Children</b></td><td>{0}</td></tr>"
         )
-        self.__tagsTemplate = self.tr(
-            "<tr><td><b>Tags</b></td><td>{0}</td></tr>"
-        )
+        self.__tagsTemplate = self.tr("<tr><td><b>Tags</b></td><td>{0}</td></tr>")
         self.__latestTagTemplate = self.tr(
             "<tr><td><b>Latest Tag</b></td><td>{0}</td></tr>"
         )
         self.__bookmarksTemplate = self.tr(
             "<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>"
         )
-        
+
         self.__bundle = ""
         self.__filename = ""
         self.__isFile = False
         self.__selectedRevisions = []
         self.intercept = False
-        
+
         self.__initData()
-        
+
         self.__allBranchesFilter = self.tr("All")
-        
+
         self.fromDate.setDisplayFormat("yyyy-MM-dd")
         self.toDate.setDisplayFormat("yyyy-MM-dd")
         self.__resetUI()
-        
+
         # roles used in the log tree
         self.__messageRole = Qt.ItemDataRole.UserRole
         self.__changesRole = Qt.ItemDataRole.UserRole + 1
@@ -205,58 +239,56 @@
         self.__parentsRole = Qt.ItemDataRole.UserRole + 3
         self.__latestTagRole = Qt.ItemDataRole.UserRole + 4
         self.__incomingRole = Qt.ItemDataRole.UserRole + 5
-        
+
         # roles used in the file tree
         self.__diffFileLineRole = Qt.ItemDataRole.UserRole
-        
+
         self.flags = {
-            'A': self.tr('Added'),
-            'D': self.tr('Deleted'),
-            'M': self.tr('Modified'),
+            "A": self.tr("Added"),
+            "D": self.tr("Deleted"),
+            "M": self.tr("Modified"),
         }
-        
+
         self.phases = {
-            'draft': self.tr("Draft"),
-            'public': self.tr("Public"),
-            'secret': self.tr("Secret"),
+            "draft": self.tr("Draft"),
+            "public": self.tr("Public"),
+            "secret": self.tr("Secret"),
         }
-        
+
         self.__dotRadius = 8
         self.__rowHeight = 20
-        
-        self.logTree.setIconSize(
-            QSize(100 * self.__rowHeight, self.__rowHeight))
+
+        self.logTree.setIconSize(QSize(100 * self.__rowHeight, self.__rowHeight))
         self.BookmarksColumn = self.logTree.columnCount()
-        self.logTree.headerItem().setText(
-            self.BookmarksColumn, self.tr("Bookmarks"))
-        
+        self.logTree.headerItem().setText(self.BookmarksColumn, self.tr("Bookmarks"))
+
         self.__logTreeNormalFont = self.logTree.font()
         self.__logTreeNormalFont.setBold(False)
         self.__logTreeBoldFont = self.logTree.font()
         self.__logTreeBoldFont.setBold(True)
         self.__logTreeHasDarkBackground = ericApp().usesDarkPalette()
-        
+
         self.detailsEdit.anchorClicked.connect(self.__revisionClicked)
-        
+
         self.__initActionsMenu()
-        
+
         self.__finishCallbacks = []
         if self.initialCommandMode == "full_log":
             self.__addFinishCallback(self.on_nextButton_clicked)
-    
+
     def __addFinishCallback(self, callback):
         """
         Private method to add a method to be called once the process finished.
-        
+
         The callback methods are invoke in a FIFO style and are consumed. If
         a callback method needs to be called again, it must be added again.
-        
+
         @param callback callback method
         @type function
         """
         if callback not in self.__finishCallbacks:
             self.__finishCallbacks.append(callback)
-    
+
     def __initActionsMenu(self):
         """
         Private method to initialize the actions menu.
@@ -264,138 +296,181 @@
         self.__actionsMenu = QMenu()
         self.__actionsMenu.setTearOffEnabled(True)
         self.__actionsMenu.setToolTipsVisible(True)
-        
+
         self.__graftAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsGraft"),
-            self.tr("Copy Changesets"), self.__graftActTriggered)
-        self.__graftAct.setToolTip(self.tr(
-            "Copy the selected changesets to the current branch"))
-        
+            self.tr("Copy Changesets"),
+            self.__graftActTriggered,
+        )
+        self.__graftAct.setToolTip(
+            self.tr("Copy the selected changesets to the current branch")
+        )
+
         self.__mergeAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsMerge"),
-            self.tr("Merge with Changeset"), self.__mergeActTriggered)
-        self.__mergeAct.setToolTip(self.tr(
-            "Merge the working directory with the selected changeset"))
-        
+            self.tr("Merge with Changeset"),
+            self.__mergeActTriggered,
+        )
+        self.__mergeAct.setToolTip(
+            self.tr("Merge the working directory with the selected changeset")
+        )
+
         self.__phaseAct = self.__actionsMenu.addAction(
-            self.tr("Change Phase"), self.__phaseActTriggered)
-        self.__phaseAct.setToolTip(self.tr(
-            "Change the phase of the selected revisions"))
-        self.__phaseAct.setWhatsThis(self.tr(
-            """<b>Change Phase</b>\n<p>This changes the phase of the"""
-            """ selected revisions. The selected revisions have to have"""
-            """ the same current phase.</p>"""))
-        
+            self.tr("Change Phase"), self.__phaseActTriggered
+        )
+        self.__phaseAct.setToolTip(
+            self.tr("Change the phase of the selected revisions")
+        )
+        self.__phaseAct.setWhatsThis(
+            self.tr(
+                """<b>Change Phase</b>\n<p>This changes the phase of the"""
+                """ selected revisions. The selected revisions have to have"""
+                """ the same current phase.</p>"""
+            )
+        )
+
         self.__tagAct = self.__actionsMenu.addAction(
-            UI.PixmapCache.getIcon("vcsTag"), self.tr("Tag"),
-            self.__tagActTriggered)
+            UI.PixmapCache.getIcon("vcsTag"), self.tr("Tag"), self.__tagActTriggered
+        )
         self.__tagAct.setToolTip(self.tr("Tag the selected revision"))
-        
+
         self.__closeHeadsAct = self.__actionsMenu.addAction(
-            UI.PixmapCache.getIcon("closehead"), self.tr("Close Heads"),
-            self.__closeHeadsActTriggered)
+            UI.PixmapCache.getIcon("closehead"),
+            self.tr("Close Heads"),
+            self.__closeHeadsActTriggered,
+        )
         self.__closeHeadsAct.setToolTip(self.tr("Close the selected heads"))
-        
+
         self.__switchAct = self.__actionsMenu.addAction(
-            UI.PixmapCache.getIcon("vcsSwitch"), self.tr("Switch"),
-            self.__switchActTriggered)
-        self.__switchAct.setToolTip(self.tr(
-            "Switch the working directory to the selected revision"))
-        
+            UI.PixmapCache.getIcon("vcsSwitch"),
+            self.tr("Switch"),
+            self.__switchActTriggered,
+        )
+        self.__switchAct.setToolTip(
+            self.tr("Switch the working directory to the selected revision")
+        )
+
         self.__actionsMenu.addSeparator()
-        
+
         self.__bookmarkAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("addBookmark"),
-            self.tr("Define Bookmark..."), self.__bookmarkActTriggered)
-        self.__bookmarkAct.setToolTip(
-            self.tr("Bookmark the selected revision"))
+            self.tr("Define Bookmark..."),
+            self.__bookmarkActTriggered,
+        )
+        self.__bookmarkAct.setToolTip(self.tr("Bookmark the selected revision"))
         self.__bookmarkMoveAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("moveBookmark"),
-            self.tr("Move Bookmark..."), self.__bookmarkMoveActTriggered)
+            self.tr("Move Bookmark..."),
+            self.__bookmarkMoveActTriggered,
+        )
         self.__bookmarkMoveAct.setToolTip(
-            self.tr("Move bookmark to the selected revision"))
-        
+            self.tr("Move bookmark to the selected revision")
+        )
+
         self.__actionsMenu.addSeparator()
-        
+
         self.__pullAct = self.__actionsMenu.addAction(
-            UI.PixmapCache.getIcon("vcsUpdate"), self.tr("Pull Changes"),
-            self.__pullActTriggered)
-        self.__pullAct.setToolTip(self.tr(
-            "Pull changes from a remote repository"))
+            UI.PixmapCache.getIcon("vcsUpdate"),
+            self.tr("Pull Changes"),
+            self.__pullActTriggered,
+        )
+        self.__pullAct.setToolTip(self.tr("Pull changes from a remote repository"))
         self.__lfPullAct = self.__actionsMenu.addAction(
-            self.tr("Pull Large Files"), self.__lfPullActTriggered)
-        self.__lfPullAct.setToolTip(self.tr(
-            "Pull large files for selected revisions"))
-        
+            self.tr("Pull Large Files"), self.__lfPullActTriggered
+        )
+        self.__lfPullAct.setToolTip(self.tr("Pull large files for selected revisions"))
+
         self.__actionsMenu.addSeparator()
-        
+
         self.__pushAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsCommit"),
-            self.tr("Push Selected Changes"), self.__pushActTriggered)
-        self.__pushAct.setToolTip(self.tr(
-            "Push changes of the selected changeset and its ancestors"
-            " to a remote repository"))
+            self.tr("Push Selected Changes"),
+            self.__pushActTriggered,
+        )
+        self.__pushAct.setToolTip(
+            self.tr(
+                "Push changes of the selected changeset and its ancestors"
+                " to a remote repository"
+            )
+        )
         self.__pushAllAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsCommit"),
-            self.tr("Push All Changes"), self.__pushAllActTriggered)
-        self.__pushAllAct.setToolTip(self.tr(
-            "Push all changes to a remote repository"))
-        
+            self.tr("Push All Changes"),
+            self.__pushAllActTriggered,
+        )
+        self.__pushAllAct.setToolTip(self.tr("Push all changes to a remote repository"))
+
         self.__actionsMenu.addSeparator()
-        
+
         self.__bundleAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsCreateChangegroup"),
-            self.tr("Create Changegroup"), self.__bundleActTriggered)
-        self.__bundleAct.setToolTip(self.tr(
-            "Create a changegroup file containing the selected changesets"))
-        self.__bundleAct.setWhatsThis(self.tr(
-            """<b>Create Changegroup</b>\n<p>This creates a changegroup"""
-            """ file containing the selected revisions. If no revisions"""
-            """ are selected, all changesets will be bundled. If one"""
-            """ revision is selected, it will be interpreted as the base"""
-            """ revision. Otherwise the lowest revision will be used as"""
-            """ the base revision and all other revision will be bundled."""
-            """ If the dialog is showing outgoing changesets, all"""
-            """ selected changesets will be bundled.</p>"""))
+            self.tr("Create Changegroup"),
+            self.__bundleActTriggered,
+        )
+        self.__bundleAct.setToolTip(
+            self.tr("Create a changegroup file containing the selected changesets")
+        )
+        self.__bundleAct.setWhatsThis(
+            self.tr(
+                """<b>Create Changegroup</b>\n<p>This creates a changegroup"""
+                """ file containing the selected revisions. If no revisions"""
+                """ are selected, all changesets will be bundled. If one"""
+                """ revision is selected, it will be interpreted as the base"""
+                """ revision. Otherwise the lowest revision will be used as"""
+                """ the base revision and all other revision will be bundled."""
+                """ If the dialog is showing outgoing changesets, all"""
+                """ selected changesets will be bundled.</p>"""
+            )
+        )
         self.__unbundleAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsApplyChangegroup"),
-            self.tr("Apply Changegroup"), self.__unbundleActTriggered)
-        self.__unbundleAct.setToolTip(self.tr(
-            "Apply the currently viewed changegroup file"))
-        
+            self.tr("Apply Changegroup"),
+            self.__unbundleActTriggered,
+        )
+        self.__unbundleAct.setToolTip(
+            self.tr("Apply the currently viewed changegroup file")
+        )
+
         self.__actionsMenu.addSeparator()
-        
+
         self.__gpgSignAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("changesetSign"),
-            self.tr("Sign Revisions"), self.__gpgSignActTriggered)
-        self.__gpgSignAct.setToolTip(self.tr(
-            "Add a signature for the selected revisions"))
+            self.tr("Sign Revisions"),
+            self.__gpgSignActTriggered,
+        )
+        self.__gpgSignAct.setToolTip(
+            self.tr("Add a signature for the selected revisions")
+        )
         self.__gpgVerifyAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("changesetSignVerify"),
-            self.tr("Verify Signatures"), self.__gpgVerifyActTriggered)
-        self.__gpgVerifyAct.setToolTip(self.tr(
-            "Verify all signatures there may be for the selected revision"))
-        
+            self.tr("Verify Signatures"),
+            self.__gpgVerifyActTriggered,
+        )
+        self.__gpgVerifyAct.setToolTip(
+            self.tr("Verify all signatures there may be for the selected revision")
+        )
+
         self.__actionsMenu.addSeparator()
-        
+
         self.__stripAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("fileDelete"),
-            self.tr("Strip Changesets"), self.__stripActTriggered)
-        self.__stripAct.setToolTip(self.tr(
-            "Strip changesets from a repository"))
-        
+            self.tr("Strip Changesets"),
+            self.__stripActTriggered,
+        )
+        self.__stripAct.setToolTip(self.tr("Strip changesets from a repository"))
+
         self.__actionsMenu.addSeparator()
-        
+
         self.__selectAllAct = self.__actionsMenu.addAction(
-            self.tr("Select All Entries"), self.__selectAllActTriggered)
+            self.tr("Select All Entries"), self.__selectAllActTriggered
+        )
         self.__unselectAllAct = self.__actionsMenu.addAction(
-            self.tr("Deselect All Entries"),
-            lambda: self.__selectAllActTriggered(False))
-        
-        self.actionsButton.setIcon(
-            UI.PixmapCache.getIcon("actionsToolButton"))
+            self.tr("Deselect All Entries"), lambda: self.__selectAllActTriggered(False)
+        )
+
+        self.actionsButton.setIcon(UI.PixmapCache.getIcon("actionsToolButton"))
         self.actionsButton.setMenu(self.__actionsMenu)
-    
+
     def __initData(self):
         """
         Private method to (re-)initialize some data.
@@ -403,46 +478,46 @@
         self.__maxDate = QDate()
         self.__minDate = QDate()
         self.__filterLogsEnabled = True
-        
-        self.buf = []        # buffer for stdout
+
+        self.buf = []  # buffer for stdout
         self.diff = None
         self.__started = False
         self.__lastRev = 0
         self.projectMode = False
-        
+
         # attributes to store log graph data
         self.__revs = []
         self.__revColors = {}
         self.__revColor = 0
-        
+
         self.__branchColors = {}
-        
+
         self.__projectWorkingDirParents = []
         self.__projectBranch = ""
-        
+
         self.__childrenInfo = collections.defaultdict(list)
-    
+
     def closeEvent(self, e):
         """
         Protected slot implementing a close event handler.
-        
+
         @param e close event (QCloseEvent)
         """
         if self.__hgClient.isExecuting():
             self.__hgClient.cancel()
-        
+
+        self.vcs.getPlugin().setPreferences("LogBrowserGeometry", self.saveGeometry())
         self.vcs.getPlugin().setPreferences(
-            "LogBrowserGeometry", self.saveGeometry())
-        self.vcs.getPlugin().setPreferences(
-            "LogBrowserSplitterStates", [
+            "LogBrowserSplitterStates",
+            [
                 self.mainSplitter.saveState(),
                 self.detailsSplitter.saveState(),
                 self.diffSplitter.saveState(),
-            ]
+            ],
         )
-        
+
         e.accept()
-    
+
     def show(self):
         """
         Public slot to show the dialog.
@@ -450,7 +525,7 @@
         self.__reloadGeometry()
         self.__restoreSplitterStates()
         self.__resetUI()
-        
+
         super().show()
 
     def __reloadGeometry(self):
@@ -463,19 +538,18 @@
             self.resize(s)
         else:
             self.restoreGeometry(geom)
-    
+
     def __restoreSplitterStates(self):
         """
         Private method to restore the state of the various splitters.
         """
-        states = self.vcs.getPlugin().getPreferences(
-            "LogBrowserSplitterStates")
+        states = self.vcs.getPlugin().getPreferences("LogBrowserSplitterStates")
         if len(states) == 3:
             # we have three splitters
             self.mainSplitter.restoreState(states[0])
             self.detailsSplitter.restoreState(states[1])
             self.diffSplitter.restoreState(states[2])
-    
+
     def __resetUI(self):
         """
         Private method to reset the user interface.
@@ -484,55 +558,53 @@
         self.fromDate.setDate(QDate.currentDate())
         self.toDate.setDate(QDate.currentDate())
         self.fieldCombo.setCurrentIndex(self.fieldCombo.findData("message"))
-        self.limitSpinBox.setValue(self.vcs.getPlugin().getPreferences(
-            "LogLimit"))
-        self.stopCheckBox.setChecked(self.vcs.getPlugin().getPreferences(
-            "StopLogOnCopy"))
-        
+        self.limitSpinBox.setValue(self.vcs.getPlugin().getPreferences("LogLimit"))
+        self.stopCheckBox.setChecked(
+            self.vcs.getPlugin().getPreferences("StopLogOnCopy")
+        )
+
         if self.initialCommandMode in ("incoming", "outgoing"):
             self.nextButton.setEnabled(False)
             self.limitSpinBox.setEnabled(False)
         else:
             self.nextButton.setEnabled(True)
             self.limitSpinBox.setEnabled(True)
-        
+
         self.logTree.clear()
-        
+
         if self.initialCommandMode == "full_log":
             self.commandMode = "incoming"
         else:
             self.commandMode = self.initialCommandMode
-    
+
     def __resizeColumnsLog(self):
         """
         Private method to resize the log tree columns.
         """
-        self.logTree.header().resizeSections(
-            QHeaderView.ResizeMode.ResizeToContents)
+        self.logTree.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
         self.logTree.header().setStretchLastSection(True)
-    
+
     def __resizeColumnsFiles(self):
         """
         Private method to resize the changed files tree columns.
         """
-        self.filesTree.header().resizeSections(
-            QHeaderView.ResizeMode.ResizeToContents)
+        self.filesTree.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
         self.filesTree.header().setStretchLastSection(True)
-    
+
     def __resortFiles(self):
         """
         Private method to resort the changed files tree.
         """
         sortColumn = self.filesTree.sortColumn()
-        self.filesTree.sortItems(
-            1, self.filesTree.header().sortIndicatorOrder())
+        self.filesTree.sortItems(1, self.filesTree.header().sortIndicatorOrder())
         self.filesTree.sortItems(
-            sortColumn, self.filesTree.header().sortIndicatorOrder())
-    
+            sortColumn, self.filesTree.header().sortIndicatorOrder()
+        )
+
     def __getColor(self, n):
         """
         Private method to get the (rotating) name of the color given an index.
-        
+
         @param n color index
         @type int
         @return color name
@@ -542,23 +614,22 @@
             return LIGHTCOLORS[n % len(LIGHTCOLORS)]
         else:
             return COLORS[n % len(COLORS)]
-    
+
     def __branchColor(self, branchName):
         """
         Private method to calculate a color for a given branch name.
-        
+
         @param branchName name of the branch (string)
         @return name of the color to use (string)
         """
         if branchName not in self.__branchColors:
-            self.__branchColors[branchName] = self.__getColor(
-                len(self.__branchColors))
+            self.__branchColors[branchName] = self.__getColor(len(self.__branchColors))
         return self.__branchColors[branchName]
-    
+
     def __generateEdges(self, rev, parents):
         """
         Private method to generate edge info for the give data.
-        
+
         @param rev revision to calculate edge info for (integer)
         @param parents list of parent revisions (list of integers)
         @return tuple containing the column and color index for
@@ -571,15 +642,15 @@
             self.__revs.append(rev)
             self.__revColors[rev] = self.__revColor
             self.__revColor += 1
-        
+
         col = self.__revs.index(rev)
         color = self.__revColors.pop(rev)
         nextRevs = self.__revs[:]
-        
+
         # add parents to next
         addparents = [p for p in parents if p not in nextRevs]
-        nextRevs[col:col + 1] = addparents
-        
+        nextRevs[col : col + 1] = addparents
+
         # set colors for the parents
         for i, p in enumerate(addparents):
             if not i:
@@ -587,28 +658,35 @@
             else:
                 self.__revColors[p] = self.__revColor
                 self.__revColor += 1
-        
+
         # add edges to the graph
         edges = []
         if parents[0] != -1:
             for ecol, erev in enumerate(self.__revs):
                 if erev in nextRevs:
-                    edges.append(
-                        (ecol, nextRevs.index(erev), self.__revColors[erev]))
+                    edges.append((ecol, nextRevs.index(erev), self.__revColors[erev]))
                 elif erev == rev:
                     for p in parents:
-                        edges.append(
-                            (ecol, nextRevs.index(p), self.__revColors[p]))
-        
+                        edges.append((ecol, nextRevs.index(p), self.__revColors[p]))
+
         self.__revs = nextRevs
         return col, color, edges
-    
-    def __generateIcon(self, column, color, bottomedges, topedges, dotColor,
-                       currentRev, closed, isPushableDraft):
+
+    def __generateIcon(
+        self,
+        column,
+        color,
+        bottomedges,
+        topedges,
+        dotColor,
+        currentRev,
+        closed,
+        isPushableDraft,
+    ):
         """
         Private method to generate an icon containing the revision tree for the
         given data.
-        
+
         @param column column index of the revision
         @type int
         @param color color of the node
@@ -631,32 +709,32 @@
         @return icon for the node
         @rtype QIcon
         """
+
         def col2x(col, radius):
             """
             Local function to calculate a x-position for a column.
-            
+
             @param col column number (integer)
             @param radius radius of the indicator circle (integer)
             """
             return int(1.2 * radius) * col + radius // 2 + 3
-        
+
         textColor = self.logTree.palette().color(QPalette.ColorRole.Text)
-        
+
         radius = self.__dotRadius
         w = len(bottomedges) * radius + 20
         h = self.__rowHeight
-        
+
         dot_x = col2x(column, radius) - radius // 2
         dot_y = h // 2
-        
+
         pix = QPixmap(w, h)
-        pix.fill(QColor(0, 0, 0, 0))        # draw transparent background
+        pix.fill(QColor(0, 0, 0, 0))  # draw transparent background
         painter = QPainter(pix)
         painter.setRenderHint(QPainter.RenderHint.Antialiasing)
-        
+
         # draw the revision history lines
-        for y1, y2, lines in ((0, h, bottomedges),
-                              (-h, 0, topedges)):
+        for y1, y2, lines in ((0, h, bottomedges), (-h, 0, topedges)):
             if lines:
                 for start, end, ecolor in lines:
                     lpen = QPen(QColor(self.__getColor(ecolor)))
@@ -665,12 +743,12 @@
                     x1 = col2x(start, radius)
                     x2 = col2x(end, radius)
                     painter.drawLine(x1, dot_y + y1, x2, dot_y + y2)
-        
+
         penradius = 1
         pencolor = textColor
-        
+
         dot_y = (h // 2) - radius // 2
-        
+
         # draw an indicator for the revision
         if currentRev:
             # enlarge for the current revision
@@ -684,8 +762,7 @@
         pen.setWidth(penradius)
         painter.setPen(pen)
         if closed:
-            painter.drawRect(dot_x - 2, dot_y + 1,
-                             radius + 4, radius - 2)
+            painter.drawRect(dot_x - 2, dot_y + 1, radius + 4, radius - 2)
         elif self.commandMode in ("incoming", "outgoing"):
             offset = radius // 2
             if self.commandMode == "incoming":
@@ -693,14 +770,14 @@
                 painter.drawConvexPolygon(
                     QPoint(dot_x, dot_y),
                     QPoint(dot_x + 2 * offset, dot_y),
-                    QPoint(dot_x + offset, dot_y + 2 * offset)
+                    QPoint(dot_x + offset, dot_y + 2 * offset),
                 )
             else:
                 # outgoing: draw an up arrow
                 painter.drawConvexPolygon(
                     QPoint(dot_x + offset, dot_y),
                     QPoint(dot_x, dot_y + 2 * offset),
-                    QPoint(dot_x + 2 * offset, dot_y + 2 * offset)
+                    QPoint(dot_x + 2 * offset, dot_y + 2 * offset),
                 )
         else:
             if isPushableDraft:
@@ -710,34 +787,31 @@
                 painter.drawConvexPolygon(
                     QPoint(dot_x + offset, dot_y),
                     QPoint(dot_x, dot_y + 2 * offset),
-                    QPoint(dot_x + 2 * offset, dot_y + 2 * offset)
+                    QPoint(dot_x + 2 * offset, dot_y + 2 * offset),
                 )
             else:
                 painter.drawEllipse(dot_x, dot_y, radius, radius)
         painter.end()
         return QIcon(pix)
-    
+
     def __getParents(self, rev):
         """
         Private method to get the parents of the currently viewed
         file/directory.
-        
+
         @param rev revision number to get parents for (string)
         @return list of parent revisions (list of integers)
         """
         errMsg = ""
         parents = [-1]
-        
+
         if int(rev) > 0:
             args = self.vcs.initCommand("parents")
             if self.commandMode == "incoming":
                 if self.__bundle:
                     args.append("--repository")
                     args.append(self.__bundle)
-                elif (
-                    self.vcs.bundleFile and
-                    os.path.exists(self.vcs.bundleFile)
-                ):
+                elif self.vcs.bundleFile and os.path.exists(self.vcs.bundleFile):
                     args.append("--repository")
                     args.append(self.vcs.bundleFile)
             args.append("--template")
@@ -746,114 +820,101 @@
             args.append(rev)
             if not self.projectMode:
                 args.append(self.__filename)
-            
+
             output, errMsg = self.__hgClient.runcommand(args)
-            
+
             if output:
                 parents = [int(p) for p in output.strip().splitlines()]
-        
+
         return parents
-    
+
     def __identifyProject(self):
         """
         Private method to determine the revision of the project directory.
         """
         errMsg = ""
-        
+
         args = self.vcs.initCommand("identify")
         args.append("-nb")
-        
+
         output, errMsg = self.__hgClient.runcommand(args)
-        
+
         if errMsg:
-            EricMessageBox.critical(
-                self,
-                self.tr("Mercurial Error"),
-                errMsg)
-        
+            EricMessageBox.critical(self, self.tr("Mercurial Error"), errMsg)
+
         if output:
             outputList = output.strip().split(None, 1)
             if len(outputList) == 2:
                 outputRevs = outputList[0].strip()
                 if outputRevs.endswith("+"):
                     outputRevs = outputRevs[:-1]
-                    self.__projectWorkingDirParents = outputRevs.split('+')
+                    self.__projectWorkingDirParents = outputRevs.split("+")
                 else:
                     self.__projectWorkingDirParents = [outputRevs]
                 self.__projectBranch = outputList[1].strip()
-    
+
     def __getClosedBranches(self):
         """
         Private method to get the list of closed branches.
         """
         self.__closedBranchesRevs = []
         errMsg = ""
-        
+
         args = self.vcs.initCommand("branches")
         args.append("--closed")
-        
+
         output, errMsg = self.__hgClient.runcommand(args)
-        
+
         if errMsg:
-            EricMessageBox.critical(
-                self,
-                self.tr("Mercurial Error"),
-                errMsg)
-        
+            EricMessageBox.critical(self, self.tr("Mercurial Error"), errMsg)
+
         if output:
             for line in output.splitlines():
                 if line.strip().endswith("(closed)"):
                     parts = line.split()
-                    self.__closedBranchesRevs.append(
-                        parts[-2].split(":", 1)[0])
-    
+                    self.__closedBranchesRevs.append(parts[-2].split(":", 1)[0])
+
     def __getHeads(self):
         """
         Private method to get the list of all heads.
         """
         self.__headRevisions = []
         errMsg = ""
-        
+
         args = self.vcs.initCommand("heads")
         args.append("--closed")
         args.append("--template")
         args.append("{rev}\n")
-        
+
         output, errMsg = self.__hgClient.runcommand(args)
-        
+
         if errMsg:
-            EricMessageBox.critical(
-                self,
-                self.tr("Mercurial Error"),
-                errMsg)
-        
+            EricMessageBox.critical(self, self.tr("Mercurial Error"), errMsg)
+
         if output:
             for line in output.splitlines():
                 line = line.strip()
                 if line:
                     self.__headRevisions.append(line)
-    
+
     def __getRevisionOfTag(self, tag):
         """
         Private method to get the revision of a tag.
-        
+
         @param tag tag name
         @type str
         @return tuple containing the revision and changeset ID
         @rtype tuple of (str, str)
         """
         errMsg = ""
-        
+
         args = self.vcs.initCommand("tags")
-        
+
         output, errMsg = self.__hgClient.runcommand(args)
-        
+
         if errMsg:
-            EricMessageBox.critical(
-                self,
-                self.tr("Mercurial Error"),
-                errMsg)
-        
+            EricMessageBox.critical(self, self.tr("Mercurial Error"), errMsg)
+
         res = ("", "")
         if output:
             for line in output.splitlines():
@@ -863,15 +924,27 @@
                         if name == tag:
                             res = tuple(rev.split(":", 1))
                             break
-        
+
         return res
-    
-    def __generateLogItem(self, author, date, message, revision, changedPaths,
-                          parents, branches, tags, phase, bookmarks,
-                          latestTag, canPush=False):
+
+    def __generateLogItem(
+        self,
+        author,
+        date,
+        message,
+        revision,
+        changedPaths,
+        parents,
+        branches,
+        tags,
+        phase,
+        bookmarks,
+        latestTag,
+        canPush=False,
+    ):
         """
         Private method to generate a log tree entry.
-        
+
         @param author author info
         @type str
         @param date date info
@@ -901,7 +974,8 @@
         @rtype QTreeWidgetItem
         """
         logMessageColumnWidth = self.vcs.getPlugin().getPreferences(
-            "LogMessageColumnWidth")
+            "LogMessageColumnWidth"
+        )
         msgtxt = ""
         for line in message:
             if ". " in line:
@@ -911,10 +985,9 @@
                 msgtxt += " " + line.strip()
         if len(msgtxt) > logMessageColumnWidth:
             msgtxt = "{0}...".format(msgtxt[:logMessageColumnWidth])
-        
+
         rev, node = revision.split(":")
-        closedStr = (self.ClosedIndicator
-                     if rev in self.__closedBranchesRevs else "")
+        closedStr = self.ClosedIndicator if rev in self.__closedBranchesRevs else ""
         phaseStr = self.phases.get(phase, phase)
         columnLabels = [
             "",
@@ -929,16 +1002,17 @@
         if bookmarks is not None:
             columnLabels.append(", ".join(bookmarks))
         itm = QTreeWidgetItem(self.logTree, columnLabels)
-        
-        itm.setForeground(self.BranchColumn,
-                          QBrush(QColor(self.__branchColor(branches[0]))))
-        
+
+        itm.setForeground(
+            self.BranchColumn, QBrush(QColor(self.__branchColor(branches[0])))
+        )
+
         if not self.projectMode:
             parents = self.__getParents(rev)
         if not parents:
             parents = [int(rev) - 1]
         column, color, edges = self.__generateEdges(int(rev), parents)
-        
+
         itm.setData(0, self.__messageRole, message)
         itm.setData(0, self.__changesRole, changedPaths)
         itm.setData(0, self.__edgesRole, edges)
@@ -950,112 +1024,115 @@
             for parent in parents:
                 self.__childrenInfo[parent].append(int(rev))
         itm.setData(0, self.__incomingRole, self.commandMode == "incoming")
-        
+
         topedges = (
-            self.logTree.topLevelItem(
-                self.logTree.indexOfTopLevelItem(itm) - 1
-            ).data(0, self.__edgesRole)
-            if self.logTree.topLevelItemCount() > 1 else
-            None
+            self.logTree.topLevelItem(self.logTree.indexOfTopLevelItem(itm) - 1).data(
+                0, self.__edgesRole
+            )
+            if self.logTree.topLevelItemCount() > 1
+            else None
         )
-        
-        icon = self.__generateIcon(column, color, edges, topedges,
-                                   QColor(self.__branchColor(branches[0])),
-                                   rev in self.__projectWorkingDirParents,
-                                   rev in self.__closedBranchesRevs,
-                                   phase == "draft" and canPush)
+
+        icon = self.__generateIcon(
+            column,
+            color,
+            edges,
+            topedges,
+            QColor(self.__branchColor(branches[0])),
+            rev in self.__projectWorkingDirParents,
+            rev in self.__closedBranchesRevs,
+            phase == "draft" and canPush,
+        )
         itm.setIcon(0, icon)
-        
+
         try:
             self.__lastRev = int(revision.split(":")[0])
         except ValueError:
             self.__lastRev = 0
-        
+
         return itm
-    
+
     def __getLogEntries(self, startRev=None, noEntries=0):
         """
         Private method to retrieve log entries from the repository.
-        
+
         @param startRev revision number to start from (integer, string)
         @param noEntries number of entries to get (0 = default) (int)
         """
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setEnabled(False)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setDefault(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
         QApplication.processEvents()
-        
+
         with EricOverrideCursor():
             self.buf = []
             self.cancelled = False
             self.errors.clear()
             self.intercept = False
-            
+
             if noEntries == 0:
                 noEntries = self.limitSpinBox.value()
-            
+
             preargs = []
             args = self.vcs.initCommand(self.commandMode)
-            args.append('--verbose')
+            args.append("--verbose")
             if self.commandMode not in ("incoming", "outgoing"):
-                args.append('--limit')
+                args.append("--limit")
                 args.append(str(noEntries))
             if self.commandMode in ("incoming", "outgoing"):
                 args.append("--newest-first")
                 if self.vcs.hasSubrepositories():
                     args.append("--subrepos")
             if startRev is not None:
-                args.append('--rev')
-                args.append('{0}:0'.format(startRev))
-            if (
-                not self.projectMode and
-                not self.stopCheckBox.isChecked()
-            ):
-                args.append('--follow')
+                args.append("--rev")
+                args.append("{0}:0".format(startRev))
+            if not self.projectMode and not self.stopCheckBox.isChecked():
+                args.append("--follow")
             if self.commandMode == "log":
-                args.append('--copies')
-            args.append('--template')
-            args.append(os.path.join(os.path.dirname(__file__),
-                                     "templates",
-                                     "logBrowserBookmarkPhase.tmpl"))
+                args.append("--copies")
+            args.append("--template")
+            args.append(
+                os.path.join(
+                    os.path.dirname(__file__),
+                    "templates",
+                    "logBrowserBookmarkPhase.tmpl",
+                )
+            )
             if self.commandMode == "incoming":
                 if self.__bundle:
                     args.append(self.__bundle)
                 elif not self.vcs.hasSubrepositories():
                     project = ericApp().getObject("Project")
                     self.vcs.bundleFile = os.path.join(
-                        project.getProjectManagementDir(), "hg-bundle.hg")
+                        project.getProjectManagementDir(), "hg-bundle.hg"
+                    )
                     if os.path.exists(self.vcs.bundleFile):
                         os.remove(self.vcs.bundleFile)
                     preargs = args[:]
                     preargs.append("--quiet")
-                    preargs.append('--bundle')
+                    preargs.append("--bundle")
                     preargs.append(self.vcs.bundleFile)
                     args.append(self.vcs.bundleFile)
             if not self.projectMode:
                 args.append(self.__filename)
-            
+
             if preargs:
                 out, err = self.__hgClient.runcommand(preargs)
             else:
                 err = ""
             if err:
                 if (
-                    self.commandMode == "incoming" and
-                    self.initialCommandMode == "full_log"
+                    self.commandMode == "incoming"
+                    and self.initialCommandMode == "full_log"
                 ):
                     # ignore the error
                     self.commandMode = "log"
                 else:
                     self.__showError(err)
             elif (
-                self.commandMode != "incoming" or
-                (self.vcs.bundleFile and
-                 os.path.exists(self.vcs.bundleFile)) or
-                self.__bundle
+                self.commandMode != "incoming"
+                or (self.vcs.bundleFile and os.path.exists(self.vcs.bundleFile))
+                or self.__bundle
             ):
                 out, err = self.__hgClient.runcommand(args)
                 self.buf = out.splitlines(True)
@@ -1063,17 +1140,16 @@
                     self.__showError(err)
                 self.__processBuffer()
             elif (
-                self.commandMode == "incoming" and
-                self.initialCommandMode == "full_log"
+                self.commandMode == "incoming" and self.initialCommandMode == "full_log"
             ):
                 # no incoming changesets, just switch to log mode
                 self.commandMode = "log"
         self.__finish()
-    
+
     def start(self, name=None, bundle=None, isFile=False, noEntries=0):
         """
         Public slot to start the hg log command.
-        
+
         @param name file/directory name to show the log for
         @type str
         @param bundle name of a bundle file
@@ -1085,7 +1161,7 @@
         """
         self.__bundle = bundle
         self.__isFile = isFile
-        
+
         if self.initialCommandMode == "full_log":
             if isFile:
                 self.commandMode = "log"
@@ -1093,59 +1169,57 @@
             else:
                 self.commandMode = "incoming"
                 self.__addFinishCallback(self.on_nextButton_clicked)
-        
+
         self.sbsSelectLabel.clear()
-        
+
         self.errorGroup.hide()
         self.errors.clear()
         QApplication.processEvents()
-        
+
         self.__initData()
-        
+
         self.__filename = name
-        
+
         self.projectMode = name is None
         self.stopCheckBox.setDisabled(self.projectMode)
         self.activateWindow()
         self.raise_()
-        
+
         self.logTree.clear()
         self.__started = True
         self.__identifyProject()
         self.__getClosedBranches()
         self.__getHeads()
         self.__getLogEntries(noEntries=noEntries)
-    
+
     def __finish(self):
         """
         Private slot called when the process finished or the user pressed
         the button.
         """
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setEnabled(True)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setDefault(True)
-        
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True)
+
         self.refreshButton.setEnabled(True)
-        
+
         while self.__finishCallbacks:
             self.__finishCallbacks.pop(0)()
-    
+
     def __modifyForLargeFiles(self, filename):
         """
         Private method to convert the displayed file name for a large file.
-        
+
         @param filename file name to be processed (string)
         @return processed file name (string)
         """
         if filename.startswith((self.LargefilesCacheL, self.LargefilesCacheW)):
             return self.tr("{0} (large file)").format(
-                self.PathSeparatorRe.split(filename, 1)[1])
+                self.PathSeparatorRe.split(filename, 1)[1]
+            )
         else:
             return filename
-    
+
     def __processBuffer(self):
         """
         Private method to process the buffered output of the hg log command.
@@ -1170,8 +1244,7 @@
                     log["author"] = value.strip()
                 elif key == "parents":
                     log["parents"] = [
-                        int(x.split(":", 1)[0])
-                        for x in value.strip().split()
+                        int(x.split(":", 1)[0]) for x in value.strip().split()
                     ]
                 elif key == "date":
                     log["date"] = " ".join(value.strip().split()[:2])
@@ -1181,34 +1254,43 @@
                     if value.strip():
                         for f in value.strip().split(", "):
                             if f in fileCopies:
-                                changedPaths.append({
-                                    "action": "A",
-                                    "path": self.__modifyForLargeFiles(f),
-                                    "copyfrom": self.__modifyForLargeFiles(
-                                        fileCopies[f]),
-                                })
+                                changedPaths.append(
+                                    {
+                                        "action": "A",
+                                        "path": self.__modifyForLargeFiles(f),
+                                        "copyfrom": self.__modifyForLargeFiles(
+                                            fileCopies[f]
+                                        ),
+                                    }
+                                )
                             else:
-                                changedPaths.append({
-                                    "action": "A",
-                                    "path": self.__modifyForLargeFiles(f),
-                                    "copyfrom": "",
-                                })
+                                changedPaths.append(
+                                    {
+                                        "action": "A",
+                                        "path": self.__modifyForLargeFiles(f),
+                                        "copyfrom": "",
+                                    }
+                                )
                 elif key == "files_mods":
                     if value.strip():
                         for f in value.strip().split(", "):
-                            changedPaths.append({
-                                "action": "M",
-                                "path": self.__modifyForLargeFiles(f),
-                                "copyfrom": "",
-                            })
+                            changedPaths.append(
+                                {
+                                    "action": "M",
+                                    "path": self.__modifyForLargeFiles(f),
+                                    "copyfrom": "",
+                                }
+                            )
                 elif key == "file_dels":
                     if value.strip():
                         for f in value.strip().split(", "):
-                            changedPaths.append({
-                                "action": "D",
-                                "path": self.__modifyForLargeFiles(f),
-                                "copyfrom": "",
-                            })
+                            changedPaths.append(
+                                {
+                                    "action": "D",
+                                    "path": self.__modifyForLargeFiles(f),
+                                    "copyfrom": "",
+                                }
+                            )
                 elif key == "file_copies":
                     if value.strip():
                         for entry in value.strip().split(", "):
@@ -1231,7 +1313,8 @@
                         log["latesttag"] = []
                     elif ":" in tag:
                         log["latesttag"] = [
-                            t.strip() for t in tag.split(":") if t.strip()]
+                            t.strip() for t in tag.split(":") if t.strip()
+                        ]
                     else:
                         log["latesttag"] = [tag]
                 else:
@@ -1242,16 +1325,21 @@
             else:
                 if len(log) > 1:
                     self.__generateLogItem(
-                        log["author"], log["date"],
-                        log["message"], log["revision"], changedPaths,
-                        log["parents"], log["branches"], log["tags"],
-                        log["phase"], log["bookmarks"], log["latesttag"],
-                        canPush=canPush)
+                        log["author"],
+                        log["date"],
+                        log["message"],
+                        log["revision"],
+                        changedPaths,
+                        log["parents"],
+                        log["branches"],
+                        log["tags"],
+                        log["phase"],
+                        log["bookmarks"],
+                        log["latesttag"],
+                        canPush=canPush,
+                    )
                     dt = QDate.fromString(log["date"], Qt.DateFormat.ISODate)
-                    if (
-                        not self.__maxDate.isValid() and
-                        not self.__minDate.isValid()
-                    ):
+                    if not self.__maxDate.isValid() and not self.__minDate.isValid():
                         self.__maxDate = dt
                         self.__minDate = dt
                     else:
@@ -1263,20 +1351,21 @@
                     log = {"message": [], "bookmarks": None, "phase": ""}
                     changedPaths = []
                     fileCopies = {}
-        
+
         self.__resizeColumnsLog()
-        
+
         if self.__started and not self.__finishCallbacks:
             # we are really done
             if self.__selectedRevisions:
                 foundItems = self.logTree.findItems(
-                    self.__selectedRevisions[0], Qt.MatchFlag.MatchExactly,
-                    self.RevisionColumn)
+                    self.__selectedRevisions[0],
+                    Qt.MatchFlag.MatchExactly,
+                    self.RevisionColumn,
+                )
                 if foundItems:
                     self.logTree.setCurrentItem(foundItems[0])
                 else:
-                    self.logTree.setCurrentItem(
-                        self.logTree.topLevelItem(0))
+                    self.logTree.setCurrentItem(self.logTree.topLevelItem(0))
             elif self.__projectWorkingDirParents:
                 for rev in self.__projectWorkingDirParents:
                     # rev string format must match with the format of the
@@ -1284,19 +1373,19 @@
                     items = self.logTree.findItems(
                         "{0:>7}:".format(rev),
                         Qt.MatchFlag.MatchStartsWith,
-                        self.RevisionColumn)
+                        self.RevisionColumn,
+                    )
                     if items:
                         self.logTree.setCurrentItem(items[0])
                         break
                 else:
-                    self.logTree.setCurrentItem(
-                        self.logTree.topLevelItem(0))
+                    self.logTree.setCurrentItem(self.logTree.topLevelItem(0))
             else:
                 self.logTree.setCurrentItem(self.logTree.topLevelItem(0))
             self.__started = False
-        
+
         if self.commandMode in ("incoming", "outgoing"):
-            self.commandMode = "log"    # switch to log mode
+            self.commandMode = "log"  # switch to log mode
             if self.__lastRev > 0:
                 self.nextButton.setEnabled(True)
                 self.limitSpinBox.setEnabled(True)
@@ -1304,7 +1393,7 @@
             if noEntries < self.limitSpinBox.value() and not self.cancelled:
                 self.nextButton.setEnabled(False)
                 self.limitSpinBox.setEnabled(False)
-        
+
         # update the log filters
         self.__filterLogsEnabled = False
         self.fromDate.setMinimumDate(self.__minDate)
@@ -1313,59 +1402,56 @@
         self.toDate.setMinimumDate(self.__minDate)
         self.toDate.setMaximumDate(self.__maxDate)
         self.toDate.setDate(self.__maxDate)
-        
+
         branchFilter = self.branchCombo.currentText()
         if not branchFilter:
             branchFilter = self.__allBranchesFilter
         self.branchCombo.clear()
         self.branchCombo.addItems(
-            [self.__allBranchesFilter] + sorted(self.__branchColors.keys()))
-        self.branchCombo.setCurrentIndex(
-            self.branchCombo.findText(branchFilter))
-        
+            [self.__allBranchesFilter] + sorted(self.__branchColors.keys())
+        )
+        self.branchCombo.setCurrentIndex(self.branchCombo.findText(branchFilter))
+
         self.__filterLogsEnabled = True
         if self.__actionMode() == "filter":
             self.__filterLogs()
         self.__updateToolMenuActions()
-        
+
         # restore selected item
         if self.__selectedRevisions and not self.__finishCallbacks:
             # we are really done
             for revision in self.__selectedRevisions:
                 items = self.logTree.findItems(
-                    revision, Qt.MatchFlag.MatchExactly, self.RevisionColumn)
+                    revision, Qt.MatchFlag.MatchExactly, self.RevisionColumn
+                )
                 if items:
                     items[0].setSelected(True)
             self.__selectedRevisions = []
-    
+
     def __showError(self, out):
         """
         Private slot to show some error.
-        
+
         @param out error to be shown (string)
         """
         self.errorGroup.show()
         self.errors.insertPlainText(out)
         self.errors.ensureCursorVisible()
-    
+
     def on_buttonBox_clicked(self, button):
         """
         Private slot called by a button of the button box clicked.
-        
+
         @param button button that was clicked (QAbstractButton)
         """
-        if button == self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close
-        ):
+        if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
             self.close()
-        elif button == self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel
-        ):
+        elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel):
             self.cancelled = True
             self.__hgClient.cancel()
         elif button == self.refreshButton:
             self.on_refreshButton_clicked()
-    
+
     def __updateSbsSelectLabel(self):
         """
         Private slot to update the enabled status of the diff buttons.
@@ -1375,32 +1461,33 @@
             selectedItems = self.logTree.selectedItems()
             if len(selectedItems) == 1:
                 currentItem = selectedItems[0]
-                rev2 = (
-                    currentItem.text(self.RevisionColumn).split(":", 1)[0]
-                    .strip()
-                )
+                rev2 = currentItem.text(self.RevisionColumn).split(":", 1)[0].strip()
                 parents = currentItem.data(0, self.__parentsRole)
                 if parents:
                     parentLinks = []
                     for index in range(len(parents)):
                         parentLinks.append(
-                            '<a href="sbsdiff:{0}_{1}">&nbsp;{2}&nbsp;</a>'
-                            .format(parents[index], rev2, index + 1))
+                            '<a href="sbsdiff:{0}_{1}">&nbsp;{2}&nbsp;</a>'.format(
+                                parents[index], rev2, index + 1
+                            )
+                        )
                     self.sbsSelectLabel.setText(
-                        self.tr('Side-by-Side Diff to Parent {0}').format(
-                            " ".join(parentLinks)))
+                        self.tr("Side-by-Side Diff to Parent {0}").format(
+                            " ".join(parentLinks)
+                        )
+                    )
             elif len(selectedItems) == 2:
-                rev1 = int(selectedItems[0].text(self.RevisionColumn)
-                           .split(":", 1)[0])
-                rev2 = int(selectedItems[1].text(self.RevisionColumn)
-                           .split(":", 1)[0])
+                rev1 = int(selectedItems[0].text(self.RevisionColumn).split(":", 1)[0])
+                rev2 = int(selectedItems[1].text(self.RevisionColumn).split(":", 1)[0])
                 if rev1 > rev2:
                     # Swap the entries, so that rev1 < rev2
                     rev1, rev2 = rev2, rev1
-                self.sbsSelectLabel.setText(self.tr(
-                    '<a href="sbsdiff:{0}_{1}">Side-by-Side Compare</a>')
-                    .format(rev1, rev2))
-    
+                self.sbsSelectLabel.setText(
+                    self.tr(
+                        '<a href="sbsdiff:{0}_{1}">Side-by-Side Compare</a>'
+                    ).format(rev1, rev2)
+                )
+
     def __updateToolMenuActions(self):
         """
         Private slot to update the status of the tool menu actions and
@@ -1412,8 +1499,11 @@
             secret = 0
             draft = 0
             public = 0
-            for itm in [item for item in self.logTree.selectedItems()
-                        if not item.data(0, self.__incomingRole)]:
+            for itm in [
+                item
+                for item in self.logTree.selectedItems()
+                if not item.data(0, self.__incomingRole)
+            ]:
                 # count phase for local items only
                 phase = itm.text(self.PhaseColumn)
                 if phase == self.phases["draft"]:
@@ -1422,46 +1512,53 @@
                     secret += 1
                 else:
                     public += 1
-            
+
             # step 2: set the status of the phase action
-            if (
-                public == 0 and
-                ((secret > 0 and draft == 0) or
-                 (secret == 0 and draft > 0))
+            if public == 0 and (
+                (secret > 0 and draft == 0) or (secret == 0 and draft > 0)
             ):
                 self.__phaseAct.setEnabled(True)
             else:
                 self.__phaseAct.setEnabled(False)
-            
+
             # do the graft action
             # step 1: count selected entries not belonging to the
             #         current branch
             otherBranches = 0
-            for itm in [item for item in self.logTree.selectedItems()
-                        if not item.data(0, self.__incomingRole)]:
+            for itm in [
+                item
+                for item in self.logTree.selectedItems()
+                if not item.data(0, self.__incomingRole)
+            ]:
                 # for local items only
                 branch = itm.text(self.BranchColumn)
                 if branch != self.__projectBranch:
                     otherBranches += 1
-            
+
             # step 2: set the status of the graft action
             self.__graftAct.setEnabled(otherBranches > 0)
-            
-            selectedItemsCount = len([
-                itm for itm in self.logTree.selectedItems()
-                if not itm.data(0, self.__incomingRole)
-            ])
-            selectedIncomingItemsCount = len([
-                itm for itm in self.logTree.selectedItems()
-                if itm.data(0, self.__incomingRole)
-            ])
-            
+
+            selectedItemsCount = len(
+                [
+                    itm
+                    for itm in self.logTree.selectedItems()
+                    if not itm.data(0, self.__incomingRole)
+                ]
+            )
+            selectedIncomingItemsCount = len(
+                [
+                    itm
+                    for itm in self.logTree.selectedItems()
+                    if itm.data(0, self.__incomingRole)
+                ]
+            )
+
             self.__mergeAct.setEnabled(selectedItemsCount == 1)
             self.__tagAct.setEnabled(selectedItemsCount == 1)
             self.__switchAct.setEnabled(selectedItemsCount == 1)
             self.__bookmarkAct.setEnabled(selectedItemsCount == 1)
             self.__bookmarkMoveAct.setEnabled(selectedItemsCount == 1)
-            
+
             if selectedIncomingItemsCount > 0:
                 self.__pullAct.setText(self.tr("Pull Selected Changes"))
             else:
@@ -1469,35 +1566,34 @@
             if self.vcs.canPull():
                 self.__pullAct.setEnabled(True)
                 self.__lfPullAct.setEnabled(
-                    self.vcs.isExtensionActive("largefiles") and
-                    selectedItemsCount > 0)
+                    self.vcs.isExtensionActive("largefiles") and selectedItemsCount > 0
+                )
             else:
                 self.__pullAct.setEnabled(False)
                 self.__lfPullAct.setEnabled(False)
-            
+
             if self.vcs.canPush():
                 self.__pushAct.setEnabled(
-                    selectedItemsCount == 1 and
-                    not self.logTree.selectedItems()[0].data(
-                        0, self.__incomingRole) and
-                    self.logTree.selectedItems()[0].text(self.PhaseColumn) ==
-                    self.phases["draft"])
+                    selectedItemsCount == 1
+                    and not self.logTree.selectedItems()[0].data(0, self.__incomingRole)
+                    and self.logTree.selectedItems()[0].text(self.PhaseColumn)
+                    == self.phases["draft"]
+                )
                 self.__pushAllAct.setEnabled(True)
             else:
                 self.__pushAct.setEnabled(False)
                 self.__pushAllAct.setEnabled(False)
-            
+
             self.__stripAct.setEnabled(
-                self.vcs.isExtensionActive("strip") and
-                selectedItemsCount == 1)
-            
+                self.vcs.isExtensionActive("strip") and selectedItemsCount == 1
+            )
+
             # count incoming items for 'full_log'
             if self.initialCommandMode == "full_log":
                 # incoming items are at the top
                 incomingCount = 0
                 for row in range(self.logTree.topLevelItemCount()):
-                    if self.logTree.topLevelItem(row).data(
-                            0, self.__incomingRole):
+                    if self.logTree.topLevelItem(row).data(0, self.__incomingRole):
                         incomingCount += 1
                     else:
                         break
@@ -1506,76 +1602,103 @@
                 localCount = self.logTree.topLevelItemCount()
             self.__bundleAct.setEnabled(localCount > 0)
             self.__unbundleAct.setEnabled(False)
-            
+
             self.__gpgSignAct.setEnabled(
-                self.vcs.isExtensionActive("gpg") and
-                selectedItemsCount > 0)
+                self.vcs.isExtensionActive("gpg") and selectedItemsCount > 0
+            )
             self.__gpgVerifyAct.setEnabled(
-                self.vcs.isExtensionActive("gpg") and
-                selectedItemsCount == 1)
-            
+                self.vcs.isExtensionActive("gpg") and selectedItemsCount == 1
+            )
+
             if self.vcs.isExtensionActive("closehead"):
-                revs = [itm.text(self.RevisionColumn).strip().split(":", 1)[0]
-                        for itm in self.logTree.selectedItems()
-                        if not itm.data(0, self.__incomingRole)]
+                revs = [
+                    itm.text(self.RevisionColumn).strip().split(":", 1)[0]
+                    for itm in self.logTree.selectedItems()
+                    if not itm.data(0, self.__incomingRole)
+                ]
                 revs = [rev for rev in revs if rev in self.__headRevisions]
                 self.__closeHeadsAct.setEnabled(len(revs) > 0)
             else:
                 self.__closeHeadsAct.setEnabled(False)
             self.actionsButton.setEnabled(True)
-        
+
         elif self.initialCommandMode == "incoming" and self.projectMode:
-            for act in [self.__phaseAct, self.__graftAct, self.__mergeAct,
-                        self.__tagAct, self.__closeHeadsAct, self.__switchAct,
-                        self.__bookmarkAct, self.__bookmarkMoveAct,
-                        self.__pushAct, self.__pushAllAct, self.__stripAct,
-                        self.__bundleAct, self.__gpgSignAct,
-                        self.__gpgVerifyAct]:
+            for act in [
+                self.__phaseAct,
+                self.__graftAct,
+                self.__mergeAct,
+                self.__tagAct,
+                self.__closeHeadsAct,
+                self.__switchAct,
+                self.__bookmarkAct,
+                self.__bookmarkMoveAct,
+                self.__pushAct,
+                self.__pushAllAct,
+                self.__stripAct,
+                self.__bundleAct,
+                self.__gpgSignAct,
+                self.__gpgVerifyAct,
+            ]:
                 act.setEnabled(False)
-            
+
             self.__pullAct.setText(self.tr("Pull Selected Changes"))
             if self.vcs.canPull() and not bool(self.__bundle):
-                selectedIncomingItemsCount = len([
-                    itm for itm in self.logTree.selectedItems()
-                    if itm.data(0, self.__incomingRole)
-                ])
+                selectedIncomingItemsCount = len(
+                    [
+                        itm
+                        for itm in self.logTree.selectedItems()
+                        if itm.data(0, self.__incomingRole)
+                    ]
+                )
                 self.__pullAct.setEnabled(selectedIncomingItemsCount > 0)
                 self.__lfPullAct.setEnabled(
-                    self.vcs.isExtensionActive("largefiles") and
-                    selectedIncomingItemsCount > 0)
+                    self.vcs.isExtensionActive("largefiles")
+                    and selectedIncomingItemsCount > 0
+                )
             else:
                 self.__pullAct.setEnabled(False)
                 self.__lfPullAct.setEnabled(False)
-            
+
             self.__unbundleAct.setEnabled(bool(self.__bundle))
-            
+
             self.actionsButton.setEnabled(True)
-        
+
         elif self.initialCommandMode == "outgoing" and self.projectMode:
-            for act in [self.__phaseAct, self.__graftAct, self.__mergeAct,
-                        self.__tagAct, self.__closeHeadsAct, self.__switchAct,
-                        self.__bookmarkAct, self.__bookmarkMoveAct,
-                        self.__pullAct, self.__lfPullAct,
-                        self.__stripAct, self.__gpgSignAct,
-                        self.__gpgVerifyAct, self.__unbundleAct]:
+            for act in [
+                self.__phaseAct,
+                self.__graftAct,
+                self.__mergeAct,
+                self.__tagAct,
+                self.__closeHeadsAct,
+                self.__switchAct,
+                self.__bookmarkAct,
+                self.__bookmarkMoveAct,
+                self.__pullAct,
+                self.__lfPullAct,
+                self.__stripAct,
+                self.__gpgSignAct,
+                self.__gpgVerifyAct,
+                self.__unbundleAct,
+            ]:
                 act.setEnabled(False)
-            
+
             selectedItemsCount = len(self.logTree.selectedItems())
             if self.vcs.canPush():
                 self.__pushAct.setEnabled(
-                    selectedItemsCount == 1 and
-                    self.logTree.selectedItems()[0].text(self.PhaseColumn) ==
-                    self.phases["draft"])
+                    selectedItemsCount == 1
+                    and self.logTree.selectedItems()[0].text(self.PhaseColumn)
+                    == self.phases["draft"]
+                )
                 self.__pushAllAct.setEnabled(True)
             else:
                 self.__pushAct.setEnabled(False)
                 self.__pushAllAct.setEnabled(False)
-            
+
             self.__bundleAct.setEnabled(selectedItemsCount > 0)
-        
+
         else:
             self.actionsButton.setEnabled(False)
-    
+
     def __updateDetailsAndFiles(self):
         """
         Private slot to update the details and file changes panes.
@@ -1583,11 +1706,10 @@
         self.detailsEdit.clear()
         self.filesTree.clear()
         self.__diffUpdatesFiles = False
-        
+
         selectedItems = self.logTree.selectedItems()
         if len(selectedItems) == 1:
-            self.detailsEdit.setHtml(
-                self.__generateDetailsTableText(selectedItems[0]))
+            self.detailsEdit.setHtml(self.__generateDetailsTableText(selectedItems[0]))
             self.__updateFilesTree(self.filesTree, selectedItems[0])
             self.__resizeColumnsFiles()
             self.__resortFiles()
@@ -1598,7 +1720,8 @@
             if index1 > index2:
                 # Swap the entries
                 selectedItems[0], selectedItems[1] = (
-                    selectedItems[1], selectedItems[0]
+                    selectedItems[1],
+                    selectedItems[0],
                 )
             html = "{0}<hr/>{1}".format(
                 self.__generateDetailsTableText(selectedItems[0]),
@@ -1606,12 +1729,12 @@
             )
             self.detailsEdit.setHtml(html)
             # self.filesTree is updated by the diff
-    
+
     def __generateDetailsTableText(self, itm):
         """
         Private method to generate an HTML table with the details of the given
         changeset.
-        
+
         @param itm reference to the item the table should be based on
         @type QTreeWidgetItem
         @return HTML table containing details
@@ -1622,76 +1745,74 @@
                 tagsStr = self.__tagsTemplate.format(itm.text(self.TagsColumn))
             else:
                 tagsStr = ""
-            
+
             if itm.text(self.BookmarksColumn):
                 bookmarksStr = self.__bookmarksTemplate.format(
-                    itm.text(self.BookmarksColumn))
+                    itm.text(self.BookmarksColumn)
+                )
             else:
                 bookmarksStr = ""
-            
+
             if self.projectMode and itm.data(0, self.__latestTagRole):
                 latestTagLinks = []
                 for tag in itm.data(0, self.__latestTagRole):
-                    latestTagLinks.append('<a href="rev:{0}">{1}</a>'.format(
-                        self.__getRevisionOfTag(tag)[0], tag))
+                    latestTagLinks.append(
+                        '<a href="rev:{0}">{1}</a>'.format(
+                            self.__getRevisionOfTag(tag)[0], tag
+                        )
+                    )
                 latestTagStr = self.__latestTagTemplate.format(
-                    ", ".join(latestTagLinks))
+                    ", ".join(latestTagLinks)
+                )
             else:
                 latestTagStr = ""
-            
+
             rev = int(itm.text(self.RevisionColumn).split(":", 1)[0])
-            
+
             if itm.data(0, self.__parentsRole):
                 parentLinks = []
-                for parent in [str(x) for x in
-                               itm.data(0, self.__parentsRole)]:
-                    parentLinks.append(
-                        '<a href="rev:{0}">{0}</a>'.format(parent))
-                parentsStr = self.__parentsTemplate.format(
-                    ", ".join(parentLinks))
+                for parent in [str(x) for x in itm.data(0, self.__parentsRole)]:
+                    parentLinks.append('<a href="rev:{0}">{0}</a>'.format(parent))
+                parentsStr = self.__parentsTemplate.format(", ".join(parentLinks))
             else:
                 parentsStr = ""
-            
+
             if self.__childrenInfo[rev]:
                 childLinks = []
                 for child in [str(x) for x in self.__childrenInfo[rev]]:
-                    childLinks.append(
-                        '<a href="rev:{0}">{0}</a>'.format(child))
-                childrenStr = self.__childrenTemplate.format(
-                    ", ".join(childLinks))
+                    childLinks.append('<a href="rev:{0}">{0}</a>'.format(child))
+                childrenStr = self.__childrenTemplate.format(", ".join(childLinks))
             else:
                 childrenStr = ""
-            
+
             messagesList = []
             for line in itm.data(0, self.__messageRole):
                 match = HgLogBrowserDialog.GraftedRe.fullmatch(line)
                 if match:
                     messagesList.append(
-                        HgLogBrowserDialog.GraftedTemplate.format(
-                            match.group(1)))
+                        HgLogBrowserDialog.GraftedTemplate.format(match.group(1))
+                    )
                 else:
                     messagesList.append(Utilities.html_encode(line.strip()))
             messageStr = "<br />\n".join(messagesList)
-            
+
             html = self.__detailsTemplate.format(
                 itm.text(self.RevisionColumn),
                 itm.text(self.DateColumn),
                 itm.text(self.AuthorColumn),
-                itm.text(self.BranchColumn).replace(
-                    self.ClosedIndicator, ""),
-                parentsStr + childrenStr + tagsStr + latestTagStr +
-                bookmarksStr,
+                itm.text(self.BranchColumn).replace(self.ClosedIndicator, ""),
+                parentsStr + childrenStr + tagsStr + latestTagStr + bookmarksStr,
                 messageStr,
             )
         else:
             html = ""
-        
+
         return html
-    
+
     def __updateFilesTree(self, parent, itm):
         """
         Private method to update the files tree with changes of the given item.
-        
+
         @param parent parent for the items to be added
         @type QTreeWidget or QTreeWidgetItem
         @param itm reference to the item the update should be based on
@@ -1701,38 +1822,44 @@
             changes = itm.data(0, self.__changesRole)
             if len(changes) > 0:
                 for change in changes:
-                    QTreeWidgetItem(parent, [
-                        self.flags[change["action"]],
-                        change["path"].strip(),
-                        change["copyfrom"].strip(),
-                    ])
-    
+                    QTreeWidgetItem(
+                        parent,
+                        [
+                            self.flags[change["action"]],
+                            change["path"].strip(),
+                            change["copyfrom"].strip(),
+                        ],
+                    )
+
     @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
     def on_logTree_currentItemChanged(self, current, previous):
         """
         Private slot called, when the current item of the log tree changes.
-        
+
         @param current reference to the new current item (QTreeWidgetItem)
         @param previous reference to the old current item (QTreeWidgetItem)
         """
         self.__updateToolMenuActions()
-        
+
         # Highlight the current entry using a bold font
         for col in range(self.logTree.columnCount()):
             current and current.setFont(col, self.__logTreeBoldFont)
             previous and previous.setFont(col, self.__logTreeNormalFont)
-        
+
         # set the state of the up and down buttons
         self.upButton.setEnabled(
-            current is not None and
-            self.logTree.indexOfTopLevelItem(current) > 0)
+            current is not None and self.logTree.indexOfTopLevelItem(current) > 0
+        )
         self.downButton.setEnabled(
-            current is not None and
-            int(current.text(self.RevisionColumn).split(":")[0]) > 0 and
-            (self.logTree.indexOfTopLevelItem(current) <
-                self.logTree.topLevelItemCount() - 1 or
-             self.nextButton.isEnabled()))
-    
+            current is not None
+            and int(current.text(self.RevisionColumn).split(":")[0]) > 0
+            and (
+                self.logTree.indexOfTopLevelItem(current)
+                < self.logTree.topLevelItemCount() - 1
+                or self.nextButton.isEnabled()
+            )
+        )
+
     @pyqtSlot()
     def on_logTree_itemSelectionChanged(self):
         """
@@ -1742,7 +1869,7 @@
         self.__updateSbsSelectLabel()
         self.__updateToolMenuActions()
         self.__generateDiffs()
-    
+
     @pyqtSlot()
     def on_upButton_clicked(self):
         """
@@ -1751,7 +1878,7 @@
         itm = self.logTree.itemAbove(self.logTree.currentItem())
         if itm:
             self.logTree.setCurrentItem(itm)
-    
+
     @pyqtSlot()
     def on_downButton_clicked(self):
         """
@@ -1765,7 +1892,7 @@
             if self.nextButton.isEnabled():
                 self.__addFinishCallback(self.on_downButton_clicked)
                 self.on_nextButton_clicked()
-    
+
     @pyqtSlot()
     def on_nextButton_clicked(self):
         """
@@ -1776,61 +1903,61 @@
                 self.__getLogEntries(startRev=self.__lastRev - 1)
             else:
                 self.__getLogEntries()
-    
+
     @pyqtSlot(QDate)
     def on_fromDate_dateChanged(self, date):
         """
         Private slot called, when the from date changes.
-        
+
         @param date new date (QDate)
         """
         if self.__actionMode() == "filter":
             self.__filterLogs()
-    
+
     @pyqtSlot(QDate)
     def on_toDate_dateChanged(self, date):
         """
         Private slot called, when the from date changes.
-        
+
         @param date new date (QDate)
         """
         if self.__actionMode() == "filter":
             self.__filterLogs()
-    
+
     @pyqtSlot(int)
     def on_branchCombo_activated(self, index):
         """
         Private slot called, when a new branch is selected.
-        
+
         @param index index of the selected entry
         @type int
         """
         if self.__actionMode() == "filter":
             self.__filterLogs()
-    
+
     @pyqtSlot(int)
     def on_fieldCombo_activated(self, index):
         """
         Private slot called, when a new filter field is selected.
-        
+
         @param index index of the selected entry
         @type int
         """
         if self.__actionMode() == "filter":
             self.__filterLogs()
-    
+
     @pyqtSlot(str)
     def on_rxEdit_textChanged(self, txt):
         """
         Private slot called, when a filter expression is entered.
-        
+
         @param txt filter expression (string)
         """
         if self.__actionMode() == "filter":
             self.__filterLogs()
         elif self.__actionMode() == "find":
             self.__findItem(self.__findBackwards, interactive=True)
-    
+
     @pyqtSlot()
     def on_rxEdit_returnPressed(self):
         """
@@ -1838,7 +1965,7 @@
         """
         if self.__actionMode() == "find":
             self.__findItem(self.__findBackwards, interactive=True)
-    
+
     def __filterLogs(self):
         """
         Private method to filter the log entries.
@@ -1847,9 +1974,9 @@
             from_ = self.fromDate.date().toString("yyyy-MM-dd")
             to_ = self.toDate.date().addDays(1).toString("yyyy-MM-dd")
             branch = self.branchCombo.currentText()
-            closedBranch = branch + '--'
+            closedBranch = branch + "--"
             fieldIndex, searchRx, indexIsRole = self.__prepareFieldSearch()
-            
+
             visibleItemCount = self.logTree.topLevelItemCount()
             currentItem = self.logTree.currentItem()
             for topIndex in range(self.logTree.topLevelItemCount()):
@@ -1858,8 +1985,8 @@
                     if fieldIndex == self.__changesRole:
                         changes = topItem.data(0, self.__changesRole)
                         txt = "\n".join(
-                            [c["path"] for c in changes] +
-                            [c["copyfrom"] for c in changes]
+                            [c["path"] for c in changes]
+                            + [c["copyfrom"] for c in changes]
                         )
                     else:
                         # Find based on complete message text
@@ -1867,12 +1994,13 @@
                 else:
                     txt = topItem.text(fieldIndex)
                 if (
-                    topItem.text(self.DateColumn) <= to_ and
-                    topItem.text(self.DateColumn) >= from_ and
-                    (branch == self.__allBranchesFilter or
-                     topItem.text(self.BranchColumn) in
-                        [branch, closedBranch]) and
-                    searchRx.search(txt) is not None
+                    topItem.text(self.DateColumn) <= to_
+                    and topItem.text(self.DateColumn) >= from_
+                    and (
+                        branch == self.__allBranchesFilter
+                        or topItem.text(self.BranchColumn) in [branch, closedBranch]
+                    )
+                    and searchRx.search(txt) is not None
                 ):
                     topItem.setHidden(False)
                     if topItem is currentItem:
@@ -1883,13 +2011,13 @@
                         self.filesTree.clear()
                     visibleItemCount -= 1
             self.logTree.header().setSectionHidden(
-                self.IconColumn,
-                visibleItemCount != self.logTree.topLevelItemCount())
-    
+                self.IconColumn, visibleItemCount != self.logTree.topLevelItemCount()
+            )
+
     def __prepareFieldSearch(self):
         """
         Private slot to prepare the filed search data.
-        
+
         @return tuple of field index, search expression and flag indicating
             that the field index is a data role (integer, string, boolean)
         """
@@ -1902,8 +2030,7 @@
             fieldIndex = self.RevisionColumn
             txt = self.rxEdit.text()
             if txt.startswith("^"):
-                searchRx = re.compile(r"^\s*{0}".format(txt[1:]),
-                                      re.IGNORECASE)
+                searchRx = re.compile(r"^\s*{0}".format(txt[1:]), re.IGNORECASE)
             else:
                 searchRx = re.compile(txt, re.IGNORECASE)
         elif txt == "file":
@@ -1917,44 +2044,42 @@
             fieldIndex = self.__messageRole
             searchRx = re.compile(self.rxEdit.text(), re.IGNORECASE)
             indexIsRole = True
-        
+
         return fieldIndex, searchRx, indexIsRole
-    
+
     @pyqtSlot(bool)
     def on_stopCheckBox_clicked(self, checked):
         """
         Private slot called, when the stop on copy/move checkbox is clicked.
-        
+
         @param checked flag indicating the state of the check box (boolean)
         """
-        self.vcs.getPlugin().setPreferences("StopLogOnCopy",
-                                            self.stopCheckBox.isChecked())
+        self.vcs.getPlugin().setPreferences(
+            "StopLogOnCopy", self.stopCheckBox.isChecked()
+        )
         self.nextButton.setEnabled(True)
         self.limitSpinBox.setEnabled(True)
-    
+
     @pyqtSlot()
     def on_refreshButton_clicked(self, addNext=False):
         """
         Private slot to refresh the log.
-        
+
         @param addNext flag indicating to get a second batch of log entries as
             well
         @type bool
         """
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setEnabled(False)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
-        self.buttonBox.button(
-            QDialogButtonBox.StandardButton.Cancel).setDefault(True)
-        
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
+
         self.refreshButton.setEnabled(False)
-        
+
         # save the selected items commit IDs
         self.__selectedRevisions = []
         for item in self.logTree.selectedItems():
             self.__selectedRevisions.append(item.text(self.RevisionColumn))
-        
+
         if self.initialCommandMode in ("incoming", "outgoing"):
             self.nextButton.setEnabled(False)
             self.limitSpinBox.setEnabled(False)
@@ -1963,15 +2088,19 @@
         else:
             self.nextButton.setEnabled(True)
             self.limitSpinBox.setEnabled(True)
-        
+
         if self.initialCommandMode == "full_log":
             self.commandMode = "incoming"
             self.__addFinishCallback(self.on_nextButton_clicked)
         else:
             self.commandMode = self.initialCommandMode
-        self.start(self.__filename, bundle=self.__bundle, isFile=self.__isFile,
-                   noEntries=self.logTree.topLevelItemCount())
-    
+        self.start(
+            self.__filename,
+            bundle=self.__bundle,
+            isFile=self.__isFile,
+            noEntries=self.logTree.topLevelItemCount(),
+        )
+
     @pyqtSlot()
     def __phaseActTriggered(self):
         """
@@ -1983,13 +2112,12 @@
             revs = []
             for itm in self.logTree.selectedItems():
                 if itm.text(self.PhaseColumn) == currentPhase:
-                    revs.append(
-                        itm.text(self.RevisionColumn).split(":")[0].strip())
-            
+                    revs.append(itm.text(self.RevisionColumn).split(":")[0].strip())
+
             if not revs:
                 self.__phaseAct.setEnabled(False)
                 return
-            
+
             if currentPhase == self.phases["draft"]:
                 newPhase = self.phases["secret"]
                 data = (revs, "s", True)
@@ -2000,88 +2128,113 @@
             if res:
                 for itm in self.logTree.selectedItems():
                     itm.setText(self.PhaseColumn, newPhase)
-    
+
     @pyqtSlot()
     def __graftActTriggered(self):
         """
         Private slot to handle the Copy Changesets action.
         """
         revs = []
-        
-        for itm in [item for item in self.logTree.selectedItems()
-                    if not item.data(0, self.__incomingRole)]:
+
+        for itm in [
+            item
+            for item in self.logTree.selectedItems()
+            if not item.data(0, self.__incomingRole)
+        ]:
             branch = itm.text(self.BranchColumn)
             if branch != self.__projectBranch:
-                revs.append(
-                    itm.text(self.RevisionColumn).strip().split(":", 1)[0])
-        
+                revs.append(itm.text(self.RevisionColumn).strip().split(":", 1)[0])
+
         if revs:
             shouldReopen = self.vcs.hgGraft(revs)
             if shouldReopen:
                 res = EricMessageBox.yesNo(
                     None,
                     self.tr("Copy Changesets"),
-                    self.tr(
-                        """The project should be reread. Do this now?"""),
-                    yesDefault=True)
+                    self.tr("""The project should be reread. Do this now?"""),
+                    yesDefault=True,
+                )
                 if res:
                     ericApp().getObject("Project").reopenProject()
                     return
-            
+
             self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __tagActTriggered(self):
         """
         Private slot to tag the selected revision.
         """
-        if len([itm for itm in self.logTree.selectedItems()
-                if not itm.data(0, self.__incomingRole)]) == 1:
+        if (
+            len(
+                [
+                    itm
+                    for itm in self.logTree.selectedItems()
+                    if not itm.data(0, self.__incomingRole)
+                ]
+            )
+            == 1
+        ):
             itm = self.logTree.selectedItems()[0]
             rev = itm.text(self.RevisionColumn).strip().split(":", 1)[0]
             tag = itm.text(self.TagsColumn).strip().split(", ", 1)[0]
             res = self.vcs.vcsTag(revision=rev, tagName=tag)
             if res:
                 self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __closeHeadsActTriggered(self):
         """
         Private slot to close the selected head revisions.
         """
         if self.vcs.isExtensionActive("closehead"):
-            revs = [itm.text(self.RevisionColumn).strip().split(":", 1)[0]
-                    for itm in self.logTree.selectedItems()
-                    if not itm.data(0, self.__incomingRole)]
+            revs = [
+                itm.text(self.RevisionColumn).strip().split(":", 1)[0]
+                for itm in self.logTree.selectedItems()
+                if not itm.data(0, self.__incomingRole)
+            ]
             revs = [rev for rev in revs if rev in self.__headRevisions]
             if revs:
                 closeheadExtension = self.vcs.getExtensionObject("closehead")
                 if closeheadExtension is not None:
                     closeheadExtension.hgCloseheads(revisions=revs)
-                    
+
                     self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __switchActTriggered(self):
         """
         Private slot to switch the working directory to the
         selected revision.
         """
-        if len([itm for itm in self.logTree.selectedItems()
-                if not itm.data(0, self.__incomingRole)]) == 1:
+        if (
+            len(
+                [
+                    itm
+                    for itm in self.logTree.selectedItems()
+                    if not itm.data(0, self.__incomingRole)
+                ]
+            )
+            == 1
+        ):
             itm = self.logTree.selectedItems()[0]
             rev = itm.text(self.RevisionColumn).strip().split(":", 1)[0]
-            bookmarks = [bm.strip() for bm in
-                         itm.text(self.BookmarksColumn).strip().split(",")
-                         if bm.strip()]
+            bookmarks = [
+                bm.strip()
+                for bm in itm.text(self.BookmarksColumn).strip().split(",")
+                if bm.strip()
+            ]
             if bookmarks:
                 bookmark, ok = QInputDialog.getItem(
                     self,
                     self.tr("Switch"),
-                    self.tr("Select bookmark to switch to (leave empty to"
-                            " use revision):"),
+                    self.tr(
+                        "Select bookmark to switch to (leave empty to" " use revision):"
+                    ),
                     [""] + bookmarks,
-                    0, False)
+                    0,
+                    False,
+                )
                 if not ok:
                     return
                 if bookmark:
@@ -2092,78 +2245,96 @@
                     res = EricMessageBox.yesNo(
                         None,
                         self.tr("Switch"),
-                        self.tr(
-                            """The project should be reread. Do this now?"""),
-                        yesDefault=True)
+                        self.tr("""The project should be reread. Do this now?"""),
+                        yesDefault=True,
+                    )
                     if res:
                         ericApp().getObject("Project").reopenProject()
                         return
-                
+
                 self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __bookmarkActTriggered(self):
         """
         Private slot to bookmark the selected revision.
         """
-        if len([itm for itm in self.logTree.selectedItems()
-                if not itm.data(0, self.__incomingRole)]) == 1:
+        if (
+            len(
+                [
+                    itm
+                    for itm in self.logTree.selectedItems()
+                    if not itm.data(0, self.__incomingRole)
+                ]
+            )
+            == 1
+        ):
             itm = self.logTree.selectedItems()[0]
-            rev, changeset = (
-                itm.text(self.RevisionColumn).strip().split(":", 1)
-            )
+            rev, changeset = itm.text(self.RevisionColumn).strip().split(":", 1)
             bookmark, ok = QInputDialog.getText(
                 self,
                 self.tr("Define Bookmark"),
-                self.tr('Enter bookmark name for changeset "{0}":').format(
-                    changeset),
-                QLineEdit.EchoMode.Normal)
+                self.tr('Enter bookmark name for changeset "{0}":').format(changeset),
+                QLineEdit.EchoMode.Normal,
+            )
             if ok and bool(bookmark):
                 self.vcs.hgBookmarkDefine(
-                    revision="rev({0})".format(rev),
-                    bookmark=bookmark)
+                    revision="rev({0})".format(rev), bookmark=bookmark
+                )
                 self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __bookmarkMoveActTriggered(self):
         """
         Private slot to move a bookmark to the selected revision.
         """
-        if len([itm for itm in self.logTree.selectedItems()
-                if not itm.data(0, self.__incomingRole)]) == 1:
+        if (
+            len(
+                [
+                    itm
+                    for itm in self.logTree.selectedItems()
+                    if not itm.data(0, self.__incomingRole)
+                ]
+            )
+            == 1
+        ):
             itm = self.logTree.selectedItems()[0]
-            rev, changeset = (
-                itm.text(self.RevisionColumn).strip().split(":", 1)
-            )
+            rev, changeset = itm.text(self.RevisionColumn).strip().split(":", 1)
             bookmarksList = self.vcs.hgGetBookmarksList()
             bookmark, ok = QInputDialog.getItem(
                 self,
                 self.tr("Move Bookmark"),
-                self.tr('Select the bookmark to be moved  to changeset'
-                        ' "{0}":').format(changeset),
+                self.tr(
+                    "Select the bookmark to be moved  to changeset" ' "{0}":'
+                ).format(changeset),
                 [""] + bookmarksList,
-                0, False)
+                0,
+                False,
+            )
             if ok and bool(bookmark):
                 self.vcs.hgBookmarkMove(
-                    revision="rev({0})".format(rev),
-                    bookmark=bookmark)
+                    revision="rev({0})".format(rev), bookmark=bookmark
+                )
                 self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __lfPullActTriggered(self):
         """
         Private slot to pull large files of selected revisions.
         """
         revs = []
-        for itm in [item for item in self.logTree.selectedItems()
-                    if not item.data(0, self.__incomingRole)]:
+        for itm in [
+            item
+            for item in self.logTree.selectedItems()
+            if not item.data(0, self.__incomingRole)
+        ]:
             rev = itm.text(self.RevisionColumn).strip().split(":", 1)[0]
             if rev:
                 revs.append(rev)
-        
+
         if revs:
             self.vcs.getExtensionObject("largefiles").hgLfPull(revisions=revs)
-    
+
     @pyqtSlot()
     def __pullActTriggered(self):
         """
@@ -2172,11 +2343,14 @@
         shouldReopen = False
         refresh = False
         addNext = False
-        
+
         if self.initialCommandMode in ("log", "full_log", "incoming"):
             revs = []
-            for itm in [item for item in self.logTree.selectedItems()
-                        if item.data(0, self.__incomingRole)]:
+            for itm in [
+                item
+                for item in self.logTree.selectedItems()
+                if item.data(0, self.__incomingRole)
+            ]:
                 rev = itm.text(self.RevisionColumn).split(":")[1].strip()
                 if rev:
                     revs.append(rev)
@@ -2184,21 +2358,21 @@
             refresh = True
             if self.initialCommandMode == "incoming":
                 addNext = True
-        
+
         if shouldReopen:
             res = EricMessageBox.yesNo(
                 None,
                 self.tr("Pull Changes"),
-                self.tr(
-                    """The project should be reread. Do this now?"""),
-                yesDefault=True)
+                self.tr("""The project should be reread. Do this now?"""),
+                yesDefault=True,
+            )
             if res:
                 ericApp().getObject("Project").reopenProject()
                 return
-        
+
         if refresh:
             self.on_refreshButton_clicked(addNext=addNext)
-    
+
     @pyqtSlot()
     def __pushActTriggered(self):
         """
@@ -2211,8 +2385,9 @@
             if rev:
                 self.vcs.hgPush(rev=rev)
                 self.on_refreshButton_clicked(
-                    addNext=self.initialCommandMode == "outgoing")
-    
+                    addNext=self.initialCommandMode == "outgoing"
+                )
+
     @pyqtSlot()
     def __pushAllActTriggered(self):
         """
@@ -2220,7 +2395,7 @@
         """
         self.vcs.hgPush()
         self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __stripActTriggered(self):
         """
@@ -2229,21 +2404,20 @@
         itm = self.logTree.selectedItems()[0]
         if not itm.data(0, self.__incomingRole):
             rev = itm.text(self.RevisionColumn).strip().split(":", 1)[1]
-            shouldReopen = self.vcs.getExtensionObject("strip").hgStrip(
-                rev=rev)
+            shouldReopen = self.vcs.getExtensionObject("strip").hgStrip(rev=rev)
             if shouldReopen:
                 res = EricMessageBox.yesNo(
                     None,
                     self.tr("Strip Changesets"),
-                    self.tr(
-                        """The project should be reread. Do this now?"""),
-                    yesDefault=True)
+                    self.tr("""The project should be reread. Do this now?"""),
+                    yesDefault=True,
+                )
                 if res:
                     ericApp().getObject("Project").reopenProject()
                     return
-            
+
         self.on_refreshButton_clicked()
-    
+
     @pyqtSlot()
     def __mergeActTriggered(self):
         """
@@ -2253,17 +2427,21 @@
         itm = self.logTree.selectedItems()[0]
         if not itm.data(0, self.__incomingRole):
             rev = "rev({0})".format(
-                itm.text(self.RevisionColumn).strip().split(":", 1)[0])
+                itm.text(self.RevisionColumn).strip().split(":", 1)[0]
+            )
             self.vcs.vcsMerge("", rev=rev)
-    
+
     @pyqtSlot()
     def __bundleActTriggered(self):
         """
         Private slot to create a changegroup file.
         """
         if self.initialCommandMode in ("log", "full_log"):
-            selectedItems = [itm for itm in self.logTree.selectedItems()
-                             if not itm.data(0, self.__incomingRole)]
+            selectedItems = [
+                itm
+                for itm in self.logTree.selectedItems()
+                if not itm.data(0, self.__incomingRole)
+            ]
             if len(selectedItems) == 0:
                 # all revisions of the local repository will be bundled
                 bundleData = {
@@ -2273,8 +2451,9 @@
                 }
             elif len(selectedItems) == 1:
                 # the selected changeset is the base
-                rev = selectedItems[0].text(self.RevisionColumn).split(
-                    ":", 1)[0].strip()
+                rev = (
+                    selectedItems[0].text(self.RevisionColumn).split(":", 1)[0].strip()
+                )
                 bundleData = {
                     "revs": [],
                     "base": rev,
@@ -2290,7 +2469,7 @@
                 baseRev = min(revs)
                 while baseRev in revs:
                     revs.remove(baseRev)
-                
+
                 bundleData = {
                     "revs": [str(rev) for rev in revs],
                     "base": str(baseRev),
@@ -2303,15 +2482,15 @@
                 for itm in selectedItems:
                     rev = itm.text(self.RevisionColumn).split(":", 1)[0]
                     revs.append(rev.strip())
-                
+
                 bundleData = {
                     "revs": revs,
                     "base": "",
                     "all": False,
                 }
-        
+
         self.vcs.hgBundle(bundleData=bundleData)
-    
+
     @pyqtSlot()
     def __unbundleActTriggered(self):
         """
@@ -2324,29 +2503,33 @@
                     None,
                     self.tr("Apply Changegroup"),
                     self.tr("""The project should be reread. Do this now?"""),
-                    yesDefault=True)
+                    yesDefault=True,
+                )
                 if res:
                     ericApp().getObject("Project").reopenProject()
                     return
-            
+
             self.vcs.vcsLogBrowser()
             self.close()
-    
+
     @pyqtSlot()
     def __gpgSignActTriggered(self):
         """
         Private slot to sign the selected revisions.
         """
         revs = []
-        for itm in [item for item in self.logTree.selectedItems()
-                    if not item.data(0, self.__incomingRole)]:
+        for itm in [
+            item
+            for item in self.logTree.selectedItems()
+            if not item.data(0, self.__incomingRole)
+        ]:
             rev = itm.text(self.RevisionColumn).split(":", 1)[0].strip()
             if rev:
                 revs.append(rev)
-        
+
         if revs:
             self.vcs.getExtensionObject("gpg").hgGpgSign(revisions=revs)
-    
+
     @pyqtSlot()
     def __gpgVerifyActTriggered(self):
         """
@@ -2356,13 +2539,12 @@
         if not itm.data(0, self.__incomingRole):
             rev = itm.text(self.RevisionColumn).split(":", 1)[0].strip()
             if rev:
-                self.vcs.getExtensionObject("gpg").hgGpgVerifySignatures(
-                    rev=rev)
-    
+                self.vcs.getExtensionObject("gpg").hgGpgVerifySignatures(rev=rev)
+
     def __selectAllActTriggered(self, select=True):
         """
         Private method to select or unselect all log entries.
-        
+
         @param select flag indicating to select all entries
         @type bool
         """
@@ -2371,66 +2553,64 @@
             self.logTree.topLevelItem(row).setSelected(select)
         self.logTree.blockSignals(blocked)
         self.on_logTree_itemSelectionChanged()
-    
+
     def __actionMode(self):
         """
         Private method to get the selected action mode.
-        
+
         @return selected action mode (string, one of filter or find)
         """
-        return self.modeComboBox.itemData(
-            self.modeComboBox.currentIndex())
-    
+        return self.modeComboBox.itemData(self.modeComboBox.currentIndex())
+
     @pyqtSlot(int)
     def on_modeComboBox_currentIndexChanged(self, index):
         """
         Private slot to react on mode changes.
-        
+
         @param index index of the selected entry (integer)
         """
         mode = self.modeComboBox.itemData(index)
         findMode = mode == "find"
         filterMode = mode == "filter"
-        
+
         self.fromDate.setEnabled(filterMode)
         self.toDate.setEnabled(filterMode)
         self.branchCombo.setEnabled(filterMode)
         self.findPrevButton.setVisible(findMode)
         self.findNextButton.setVisible(findMode)
-        
+
         if findMode:
             for topIndex in range(self.logTree.topLevelItemCount()):
                 self.logTree.topLevelItem(topIndex).setHidden(False)
             self.logTree.header().setSectionHidden(self.IconColumn, False)
         elif filterMode:
             self.__filterLogs()
-    
+
     @pyqtSlot()
     def on_findPrevButton_clicked(self):
         """
         Private slot to find the previous item matching the entered criteria.
         """
         self.__findItem(True)
-    
+
     @pyqtSlot()
     def on_findNextButton_clicked(self):
         """
         Private slot to find the next item matching the entered criteria.
         """
         self.__findItem(False)
-    
+
     def __findItem(self, backwards=False, interactive=False):
         """
         Private slot to find an item matching the entered criteria.
-        
+
         @param backwards flag indicating to search backwards (boolean)
         @param interactive flag indicating an interactive search (boolean)
         """
         self.__findBackwards = backwards
-        
+
         fieldIndex, searchRx, indexIsRole = self.__prepareFieldSearch()
-        currentIndex = self.logTree.indexOfTopLevelItem(
-            self.logTree.currentItem())
+        currentIndex = self.logTree.indexOfTopLevelItem(self.logTree.currentItem())
         if backwards:
             if interactive:
                 indexes = range(currentIndex, -1, -1)
@@ -2440,17 +2620,15 @@
             if interactive:
                 indexes = range(currentIndex, self.logTree.topLevelItemCount())
             else:
-                indexes = range(currentIndex + 1,
-                                self.logTree.topLevelItemCount())
-        
+                indexes = range(currentIndex + 1, self.logTree.topLevelItemCount())
+
         for index in indexes:
             topItem = self.logTree.topLevelItem(index)
             if indexIsRole:
                 if fieldIndex == self.__changesRole:
                     changes = topItem.data(0, self.__changesRole)
                     txt = "\n".join(
-                        [c["path"] for c in changes] +
-                        [c["copyfrom"] for c in changes]
+                        [c["path"] for c in changes] + [c["copyfrom"] for c in changes]
                     )
                 else:
                     # Find based on complete message text
@@ -2464,13 +2642,14 @@
             EricMessageBox.information(
                 self,
                 self.tr("Find Commit"),
-                self.tr("""'{0}' was not found.""").format(self.rxEdit.text()))
-    
+                self.tr("""'{0}' was not found.""").format(self.rxEdit.text()),
+            )
+
     def __revisionClicked(self, url):
         """
         Private slot to handle the anchorClicked signal of the changeset
         details pane.
-        
+
         @param url URL that was clicked
         @type QUrl
         """
@@ -2487,8 +2666,7 @@
                 searchStr = ":{0}".format(changeset[:12])  # max. 12 hash chars
                 # format must be in sync with item generation format
                 searchFlags = Qt.MatchFlag.MatchContains
-            items = self.logTree.findItems(
-                searchStr, searchFlags, self.RevisionColumn)
+            items = self.logTree.findItems(searchStr, searchFlags, self.RevisionColumn)
             if items:
                 itm = items[0]
                 if itm.isHidden():
@@ -2497,18 +2675,17 @@
             else:
                 # load the next batch and try again
                 if not self.cancelled and self.nextButton.isEnabled():
-                    self.__addFinishCallback(
-                        lambda: self.__revisionClicked(url))
+                    self.__addFinishCallback(lambda: self.__revisionClicked(url))
                     self.on_nextButton_clicked()
-    
+
     ###########################################################################
     ## Diff handling methods below
     ###########################################################################
-    
+
     def __generateDiffs(self, parent=1):
         """
         Private slot to generate diff outputs for the selected item.
-        
+
         @param parent number of parent to diff against
         @type int
         """
@@ -2516,7 +2693,7 @@
         self.diffLabel.setText(self.tr("Differences"))
         self.diffSelectLabel.clear()
         self.diffHighlighter.regenerateRules()
-        
+
         selectedItems = self.logTree.selectedItems()
         if len(selectedItems) == 1:
             currentItem = selectedItems[0]
@@ -2524,12 +2701,12 @@
             parents = currentItem.data(0, self.__parentsRole)
             if len(parents) >= parent:
                 self.diffLabel.setText(
-                    self.tr("Differences to Parent {0}").format(parent))
+                    self.tr("Differences to Parent {0}").format(parent)
+                )
                 rev1 = parents[parent - 1]
-                
-                self.__diffGenerator.start(self.__filename, [rev1, rev2],
-                                           self.__bundle)
-            
+
+                self.__diffGenerator.start(self.__filename, [rev1, rev2], self.__bundle)
+
             if len(parents) > 1:
                 if parent == 1:
                     par1 = "&nbsp;1&nbsp;"
@@ -2540,34 +2717,33 @@
                 else:
                     par2 = '<a href="diff:2">&nbsp;2&nbsp;</a>'
                 self.diffSelectLabel.setText(
-                    self.tr('Diff to Parent {0}{1}').format(par1, par2))
+                    self.tr("Diff to Parent {0}{1}").format(par1, par2)
+                )
         elif len(selectedItems) == 2:
-            rev2 = int(selectedItems[0].text(
-                self.RevisionColumn).split(":")[0])
-            rev1 = int(selectedItems[1].text(
-                self.RevisionColumn).split(":")[0])
-            
-            self.__diffGenerator.start(self.__filename,
-                                       [min(rev1, rev2), max(rev1, rev2)],
-                                       self.__bundle)
+            rev2 = int(selectedItems[0].text(self.RevisionColumn).split(":")[0])
+            rev1 = int(selectedItems[1].text(self.RevisionColumn).split(":")[0])
+
+            self.__diffGenerator.start(
+                self.__filename, [min(rev1, rev2), max(rev1, rev2)], self.__bundle
+            )
         else:
             self.diffEdit.clear()
-    
+
     def __generatorFinished(self):
         """
         Private slot connected to the finished signal of the diff generator.
         """
         diff, errors, fileSeparators = self.__diffGenerator.getResult()
-        
+
         if diff:
             self.diffEdit.setPlainText("".join(diff))
         elif errors:
             self.diffEdit.setPlainText("".join(errors))
         else:
-            self.diffEdit.setPlainText(self.tr('There is no difference.'))
-        
+            self.diffEdit.setPlainText(self.tr("There is no difference."))
+
         self.saveLabel.setVisible(bool(diff))
-        
+
         if self.__diffUpdatesFiles:
             for oldFileName, newFileName, lineNumber in fileSeparators:
                 if oldFileName == newFileName:
@@ -2585,21 +2761,21 @@
                 for fileName in (oldFileName, newFileName):
                     if fileName != "__NULL__":
                         items = self.filesTree.findItems(
-                            fileName, Qt.MatchFlag.MatchExactly, 1)
+                            fileName, Qt.MatchFlag.MatchExactly, 1
+                        )
                         for item in items:
-                            item.setData(0, self.__diffFileLineRole,
-                                         lineNumber)
-        
+                            item.setData(0, self.__diffFileLineRole, lineNumber)
+
         tc = self.diffEdit.textCursor()
         tc.movePosition(QTextCursor.MoveOperation.Start)
         self.diffEdit.setTextCursor(tc)
         self.diffEdit.ensureCursorVisible()
-    
+
     @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
     def on_filesTree_currentItemChanged(self, current, previous):
         """
         Private slot called, when the current item of the files tree changes.
-        
+
         @param current reference to the new current item (QTreeWidgetItem)
         @param previous reference to the old current item (QTreeWidgetItem)
         """
@@ -2622,20 +2798,23 @@
                     tc.movePosition(QTextCursor.MoveOperation.End)
                     self.diffEdit.setTextCursor(tc)
                     self.diffEdit.ensureCursorVisible()
-                    
+
                     # step 2: move cursor to desired line
                     tc = self.diffEdit.textCursor()
                     delta = tc.blockNumber() - para
-                    tc.movePosition(QTextCursor.MoveOperation.PreviousBlock,
-                                    QTextCursor.MoveMode.MoveAnchor, delta)
+                    tc.movePosition(
+                        QTextCursor.MoveOperation.PreviousBlock,
+                        QTextCursor.MoveMode.MoveAnchor,
+                        delta,
+                    )
                     self.diffEdit.setTextCursor(tc)
                     self.diffEdit.ensureCursorVisible()
-    
+
     @pyqtSlot(str)
     def on_diffSelectLabel_linkActivated(self, link):
         """
         Private slot to handle the selection of a diff target.
-        
+
         @param link activated link
         @type str
         """
@@ -2645,47 +2824,49 @@
                 with contextlib.suppress(ValueError):
                     parent = int(parent)
                     self.__generateDiffs(parent)
-    
+
     @pyqtSlot(str)
     def on_saveLabel_linkActivated(self, link):
         """
         Private slot to handle the selection of the save link.
-        
+
         @param link activated link
         @type str
         """
         if ":" not in link:
             return
-        
+
         scheme, rest = link.split(":", 1)
         if scheme != "save" or rest != "me":
             return
-        
+
         if self.projectMode:
             if self.__filename is None:
-                fname = "{0}.diff".format(os.path.splitext(
-                    ericApp().getObject("Project").getProjectFile())[0])
+                fname = "{0}.diff".format(
+                    os.path.splitext(ericApp().getObject("Project").getProjectFile())[0]
+                )
             else:
                 fname = self.vcs.splitPath(self.__filename)[0]
                 fname += "/{0}.diff".format(os.path.split(fname)[-1])
         else:
             dname, fname = self.vcs.splitPath(self.__filename)
-            if fname != '.':
+            if fname != ".":
                 fname = "{0}.diff".format(self.__filename)
             else:
                 fname = dname
-        
+
         fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
             self,
             self.tr("Save Diff"),
             fname,
             self.tr("Patch Files (*.diff)"),
             None,
-            EricFileDialog.DontConfirmOverwrite)
-        
+            EricFileDialog.DontConfirmOverwrite,
+        )
+
         if not fname:
             return  # user aborted
-        
+
         fpath = pathlib.Path(fname)
         if not fpath.suffix:
             ex = selectedFilter.split("(*")[1].split(")")[0]
@@ -2695,29 +2876,33 @@
             res = EricMessageBox.yesNo(
                 self,
                 self.tr("Save Diff"),
-                self.tr("<p>The patch file <b>{0}</b> already exists."
-                        " Overwrite it?</p>").format(fpath),
-                icon=EricMessageBox.Warning)
+                self.tr(
+                    "<p>The patch file <b>{0}</b> already exists." " Overwrite it?</p>"
+                ).format(fpath),
+                icon=EricMessageBox.Warning,
+            )
             if not res:
                 return
-        
+
         eol = ericApp().getObject("Project").getEolString()
         try:
             with fpath.open("w", encoding="utf-8", newline="") as f:
                 f.write(eol.join(self.diffEdit.toPlainText().splitlines()))
         except OSError as why:
             EricMessageBox.critical(
-                self, self.tr('Save Diff'),
+                self,
+                self.tr("Save Diff"),
                 self.tr(
-                    '<p>The patch file <b>{0}</b> could not be saved.'
-                    '<br>Reason: {1}</p>')
-                .format(fpath, str(why)))
-    
+                    "<p>The patch file <b>{0}</b> could not be saved."
+                    "<br>Reason: {1}</p>"
+                ).format(fpath, str(why)),
+            )
+
     @pyqtSlot(str)
     def on_sbsSelectLabel_linkActivated(self, link):
         """
         Private slot to handle selection of a side-by-side link.
-        
+
         @param link text of the selected link
         @type str
         """

eric ide

mercurial