Finished implementing the VCS status widget for the left side. eric7

Wed, 22 Sep 2021 18:20:06 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 22 Sep 2021 18:20:06 +0200
branch
eric7
changeset 8622
149d51870ce8
parent 8621
8c9f41115c04
child 8623
fced5aa98d41

Finished implementing the VCS status widget for the left side.

eric7/UI/UserInterface.py file | annotate | diff | comparison | revisions
eric7/VCS/StatusWidget.py file | annotate | diff | comparison | revisions
eric7/eric7.py file | annotate | diff | comparison | revisions
eric7/icons/breeze-dark/vcsResolved.svg file | annotate | diff | comparison | revisions
eric7/icons/breeze-light/vcsResolved.svg file | annotate | diff | comparison | revisions
eric7/icons/oxygen/vcsResolved.png file | annotate | diff | comparison | revisions
--- a/eric7/UI/UserInterface.py	Tue Sep 21 19:11:31 2021 +0200
+++ b/eric7/UI/UserInterface.py	Wed Sep 22 18:20:06 2021 +0200
@@ -2259,6 +2259,24 @@
             self.__activateFindFileWidget)
         self.actions.append(self.findFileActivateAct)
         self.addAction(self.findFileActivateAct)
+
+        self.vcsStatusListActivateAct = EricAction(
+            self.tr("VCS Status List"),
+            self.tr("VCS Status List"),
+            QKeySequence(self.tr("Alt+Shift+V")),
+            0, self,
+            'vcs_status_list_activate')
+        self.vcsStatusListActivateAct.setStatusTip(self.tr(
+            "Switch the input focus to the VCS Status List window."))
+        self.vcsStatusListActivateAct.setWhatsThis(self.tr(
+            """<b>VCS Status List</b>"""
+            """<p>This switches the input focus to the VCS Status List"""
+            """ window.</p>"""
+        ))
+        self.vcsStatusListActivateAct.triggered.connect(
+            self.__activateVcsStatusList)
+        self.actions.append(self.vcsStatusListActivateAct)
+        self.addAction(self.vcsStatusListActivateAct)
         
         self.whatsThisAct = EricAction(
             self.tr('What\'s This?'),
@@ -3335,6 +3353,7 @@
         if self.__shellPosition == "left":
             self.__menus["subwindow"].addAction(self.shellActivateAct)
         self.__menus["subwindow"].addAction(self.pbActivateAct)
+        self.__menus["subwindow"].addAction(self.vcsStatusListActivateAct)
         self.__menus["subwindow"].addAction(self.mpbActivateAct)
         if self.templateViewer is not None:
             self.__menus["subwindow"].addAction(self.templateViewerActivateAct)
@@ -6882,7 +6901,7 @@
     
     def __activateFindFileWidget(self):
         """
-        Private method to activate the Find In Files widget.
+        Private slot to activate the Find In Files widget.
         """
         if self.__layoutType == "Toolboxes":
             self.rToolboxDock.show()
@@ -6895,6 +6914,19 @@
         
         self.__findFileWidget.activate()
     
+    def __activateVcsStatusList(self):
+        """
+        Private slot to activate the VCS Status List.
+        """
+        if self.__layoutType == "Toolboxes":
+            self.lToolboxDock.show()
+            self.lToolbox.setCurrentWidget(self.__vcsStatusWidget)
+        elif self.__layoutType == "Sidebars":
+            self.leftSidebar.show()
+            self.leftSidebar.setCurrentWidget(self.__vcsStatusWidget)
+        self.__vcsStatusWidget.setFocus(
+            Qt.FocusReason.ActiveWindowFocusReason)
+    
     ##########################################################
     ## Below are slots to handle StdOut and StdErr
     ##########################################################
--- a/eric7/VCS/StatusWidget.py	Tue Sep 21 19:11:31 2021 +0200
+++ b/eric7/VCS/StatusWidget.py	Wed Sep 22 18:20:06 2021 +0200
@@ -107,6 +107,7 @@
             QAbstractItemView.SelectionMode.ExtendedSelection)
         self.__statusList.itemSelectionChanged.connect(
             self.__updateButtonStates)
+        self.__statusList.itemDoubleClicked.connect(self.__itemDoubleClicked)
         self.__layout.addWidget(self.__statusList)
         
         self.setLayout(self.__layout)
@@ -159,7 +160,8 @@
         self.__commitAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsCommit"),
             self.tr("Commit"), self.__commit)
-        self.__commitAct.setToolTip(self.tr("Commit the selected changes"))
+        self.__commitAct.setToolTip(self.tr(
+            "Commit the selected changes"))
         self.__commitSelectAct = self.__actionsMenu.addAction(
             self.tr("Select all for commit"), self.__commitSelectAll)
         self.__commitDeselectAct = self.__actionsMenu.addAction(
@@ -170,6 +172,12 @@
         self.__addAct = self.__actionsMenu.addAction(
             UI.PixmapCache.getIcon("vcsAdd"),
             self.tr("Add"), self.__addUntracked)
+        self.__addAct.setToolTip(self.tr(
+            "Add the selected, untracked entries"))
+        self.__addAllAct = self.__actionsMenu.addAction(
+            self.tr("Add All"), self.__addAllUntracked)
+        self.__addAllAct.setToolTip(self.tr(
+            "Add all untracked entries"))
         
         self.__actionsMenu.addSeparator()
         
@@ -185,6 +193,10 @@
         self.__sbsDiffAct.setToolTip(self.tr(
             "Shows the differences of the selected entry side-by-side in"
             " a separate dialog"))
+        self.__diffAllAct = self.__actionsMenu.addAction(
+            self.tr("All Differences"), self.__diffAll)
+        self.__diffAllAct.setToolTip(self.tr(
+            "Shows the differences of all entries in a separate dialog"))
         
         self.__actionsMenu.addSeparator()
         
@@ -211,7 +223,11 @@
             self.tr("Edit Conflict"), self.__editConflict)
         self.__editAct.setToolTip(self.tr(
             "Edit the selected conflicting file"))
-        # TODO: add menu entry for 'Conflict Resolved'
+        self.__resolvedAct = self.__actionsMenu.addAction(
+            UI.PixmapCache.getIcon("vcsResolved"),
+            self.tr("Conflict Resolved"), self.__conflictResolved)
+        self.__resolvedAct.setToolTip(self.tr(
+            "Mark the selected conflicting file as resolved"))
         
         self.__actionsButton.setMenu(self.__actionsMenu)
     
@@ -265,7 +281,7 @@
         Private method to set the button states depending on the list state.
         """
         modified = len(self.__getModifiedItems())
-        unversioned = len(self.__getUnversionedItems())
+        unversioned = len(self.__getSelectedUnversionedItems())
         commitable = len(self.__getCommitableItems())
         
         self.__commitToggleButton.setEnabled(modified)
@@ -401,14 +417,23 @@
         self.__setCheckMark(False)
     
     @pyqtSlot()
-    def __addUntracked(self):
+    def __addUntracked(self, allItems=False):
         """
         Private slot to add the selected untracked entries.
+        
+        @param allItems flag indicating to show the differences of all files
+            (defaults to False)
+        @type bool (optional)
         """
         projectPath = self.__project.getProjectPath()
         
-        names = [os.path.join(projectPath, itm.text())
-                 for itm in self.__getUnversionedItems()]
+        names = [
+            os.path.join(projectPath, itm.text())
+            for itm in self.__getUnversionedItems()
+        ] if allItems else [
+            os.path.join(projectPath, itm.text())
+            for itm in self.__getSelectedUnversionedItems()
+        ]
         
         if not names:
             EricMessageBox.information(
@@ -422,6 +447,22 @@
         vcs and vcs.vcsAdd(names)
         self.__reload()
     
+    @pyqtSlot(QListWidgetItem)
+    def __itemDoubleClicked(self, itm):
+        """
+        Private slot to handle double clicking an item.
+        
+        @param itm reference to the double clicked item
+        @type QListWidgetItem
+        """
+        projectPath = self.__project.getProjectPath()
+        
+        if itm.data(self.StatusDataRole) in "MZ":
+            # modified and conflicting items
+            name = os.path.join(projectPath, itm.text())
+            vcs = self.__project.getVcs()
+            vcs and vcs.vcsDiff(name)
+    
     ###########################################################################
     ## Menu handling methods
     ###########################################################################
@@ -431,15 +472,19 @@
         Private slot to prepare the actions button menu before it is shown.
         """
         modified = len(self.__getSelectedModifiedItems())
-        unversioned = len(self.__getUnversionedItems())
+        allModified = len(self.__getModifiedItems())
+        unversioned = len(self.__getSelectedUnversionedItems())
+        allUnversioned = len(self.__getUnversionedItems())
         missing = len(self.__getMissingItems())
         commitable = len(self.__getCommitableItems())
         commitableUnselected = len(self.__getCommitableUnselectedItems())
         conflicting = len(self.__getSelectedConflictingItems())
 
         self.__addAct.setEnabled(unversioned)
+        self.__addAllAct.setEnabled(allUnversioned)
         self.__diffAct.setEnabled(modified)
         self.__sbsDiffAct.setEnabled(modified == 1)
+        self.__diffAllAct.setEnabled(allModified)
         self.__revertAct.setEnabled(modified)
         self.__forgetAct.setEnabled(missing)
         self.__restoreAct.setEnabled(missing)
@@ -447,6 +492,7 @@
         self.__commitSelectAct.setEnabled(commitableUnselected)
         self.__commitDeselectAct.setEnabled(commitable)
         self.__editAct.setEnabled(conflicting == 1)
+        self.__resolvedAct.setEnabled(conflicting)
     
     def __getCommitableItems(self):
         """
@@ -516,6 +562,21 @@
         @return list of all items with an unversioned status
         @rtype list of QListWidgetItem
         """
+        items = []
+        for row in range(self.__statusList.count()):
+            itm = self.__statusList.item(row)
+            if itm.data(self.StatusDataRole) == "?":
+                items.append(itm)
+        return items
+    
+    def __getSelectedUnversionedItems(self):
+        """
+        Private method to retrieve all selected entries, that have an
+        unversioned status.
+        
+        @return list of all items with an unversioned status
+        @rtype list of QListWidgetItem
+        """
         return [itm for itm in self.__statusList.selectedItems()
                 if itm.data(self.StatusDataRole) == "?"]
     
@@ -541,14 +602,30 @@
                 if itm.data(self.StatusDataRole) == "Z"]
     
     @pyqtSlot()
-    def __diff(self):
+    def __addAllUntracked(self):
+        """
+        Private slot to handle the Add All action menu entry.
         """
-        Private slot to handle the Diff action menu entry.
+        self.__addUntracked(allItems=True)
+    
+    @pyqtSlot()
+    def __diff(self, allItems=False):
+        """
+        Private slot to handle the Differences action menu entry.
+        
+        @param allItems flag indicating to show the differences of all files
+            (defaults to False)
+        @type bool (optional)
         """
         projectPath = self.__project.getProjectPath()
         
-        names = [os.path.join(projectPath, itm.text())
-                 for itm in self.__getSelectedModifiedItems()]
+        names = [
+            os.path.join(projectPath, itm.text())
+            for itm in self.__getModifiedItems()
+        ] if allItems else [
+            os.path.join(projectPath, itm.text())
+            for itm in self.__getSelectedModifiedItems()
+        ]
         if not names:
             EricMessageBox.information(
                 self,
@@ -561,9 +638,16 @@
         vcs and vcs.vcsDiff(names)
     
     @pyqtSlot()
+    def __diffAll(self):
+        """
+        Private slot to handle the All Differences action menu entry.
+        """
+        self.__diff(allItems=True)
+    
+    @pyqtSlot()
     def __sbsDiff(self):
         """
-        Private slot to handle the Side-By-Side Diff action menu entry.
+        Private slot to handle the Side-By-Side Differences action menu entry.
         """
         projectPath = self.__project.getProjectPath()
         
@@ -587,6 +671,7 @@
         vcs = self.__project.getVcs()
         vcs and vcs.vcsSbsDiff(names[0])
     
+    @pyqtSlot()
     def __revert(self):
         """
         Private slot to handle the Revert action menu entry.
@@ -607,6 +692,7 @@
         vcs and vcs.vcsRevert(names)
         self.__reload()
     
+    @pyqtSlot()
     def __forgetMissing(self):
         """
         Private slot to handle the Forget action menu entry.
@@ -627,6 +713,7 @@
         vcs and vcs.vcsForget(names)
         self.__reload()
     
+    @pyqtSlot()
     def __restoreMissing(self):
         """
         Private slot to handle the Restore Missing context menu entry.
@@ -647,6 +734,7 @@
         vcs and vcs.vcsRevert(names)
         self.__reload()
     
+    @pyqtSlot()
     def __editConflict(self):
         """
         Private slot to handle the Edit Conflict action menu entry.
@@ -657,3 +745,24 @@
         filename = os.path.join(projectPath, itm.text())
         if Utilities.MimeTypes.isTextFile(filename):
             self.__vm.getEditor(filename)
+    
+    @pyqtSlot()
+    def __conflictResolved(self):
+        """
+        Private slot to handle the Conflict Resolved action menu entry.
+        """
+        projectPath = self.__project.getProjectPath()
+        
+        names = [os.path.join(projectPath, itm.text())
+                 for itm in self.__getSelectedConflictingItems()]
+        if not names:
+            EricMessageBox.information(
+                self,
+                self.tr("Conflict Resolved"),
+                self.tr("""There are no conflicting entries"""
+                        """ available/selected."""))
+            return
+        
+        vcs = self.__project.getVcs()
+        vcs and vcs.vcsResolved(names)
+        self.__reload()
--- a/eric7/eric7.py	Tue Sep 21 19:11:31 2021 +0200
+++ b/eric7/eric7.py	Wed Sep 22 18:20:06 2021 +0200
@@ -420,5 +420,3 @@
 # Generic TODOs:
 #
 # TODO: add an embedded help viewer based on QWebEngineView (right side)
-# TODO: make VCS status an embedded view (left side)
-# TODO: add a VCS diff view in the central area (view manager) (?)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/icons/breeze-dark/vcsResolved.svg	Wed Sep 22 18:20:06 2021 +0200
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   viewBox="0 0 22 22"
+   id="svg10"
+   sodipodi:docname="vcsResolved.svg"
+   inkscape:version="0.92.0 r15299">
+  <metadata
+     id="metadata14">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="640"
+     inkscape:window-height="480"
+     id="namedview12"
+     showgrid="false"
+     inkscape:current-layer="svg10" />
+  <defs
+     id="defs4">
+    <style
+       type="text/css"
+       id="style2">.ColorScheme-Text {
+        color:#eff0f1
+      }</style>
+  </defs>
+  <path
+     d="m11 1a10 3.75 0 0 0-10 3.75v12.5a10 3.75 0 0 0 9 3.7266v-1.2441a8.75 2.5 0 0 1-7.75-2.4824v-4.4355a10 3.75 0 0 0 7.75 1.9121v-1.2441a8.75 2.5 0 0 1-7.75-2.4824v-4.4355a10 3.75 0 0 0 8.75 1.9355 10 3.75 0 0 0 8.75-1.9434v3.4434h1.25v-5.25a10 3.75 0 0 0-10-3.75zm0 1.25a8.75 2.5 0 0 1 8.75 2.5 8.75 2.5 0 0 1-8.75 2.5 8.75 2.5 0 0 1-8.75-2.5 8.75 2.5 0 0 1 8.75-2.5z"
+     color="#eff0f1"
+     fill="currentColor"
+     id="path6" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#eff0f1;fill:#5fd35f;fill-opacity:1;stroke:#5fd35f;stroke-width:0.69053423;stroke-opacity:1"
+     class="ColorScheme-Text"
+     d="m 20.12312,12.466193 -5.901694,6.188665 -2.344551,-2.458488 -0.399776,0.419213 2.344551,2.458488 -0.0011,0.0012 0.399787,0.419209 0.0011,-0.0012 0.0011,0.0012 0.399771,-0.419209 -0.0011,-0.0012 5.901694,-6.188665 -0.399777,-0.419203 z"
+     id="path6-5" />
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/icons/breeze-light/vcsResolved.svg	Wed Sep 22 18:20:06 2021 +0200
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   viewBox="0 0 22 22"
+   id="svg10"
+   sodipodi:docname="vcsResolved.svg"
+   inkscape:version="0.92.0 r15299">
+  <metadata
+     id="metadata14">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="640"
+     inkscape:window-height="480"
+     id="namedview12"
+     showgrid="false"
+     inkscape:current-layer="svg10" />
+  <defs
+     id="defs4">
+    <style
+       type="text/css"
+       id="style2">.ColorScheme-Text {
+        color:#eff0f1
+      }</style>
+  </defs>
+  <path
+     d="m11 1a10 3.75 0 0 0-10 3.75v12.5a10 3.75 0 0 0 9 3.7266v-1.2441a8.75 2.5 0 0 1-7.75-2.4824v-4.4355a10 3.75 0 0 0 7.75 1.9121v-1.2441a8.75 2.5 0 0 1-7.75-2.4824v-4.4355a10 3.75 0 0 0 8.75 1.9355 10 3.75 0 0 0 8.75-1.9434v3.4434h1.25v-5.25a10 3.75 0 0 0-10-3.75zm0 1.25a8.75 2.5 0 0 1 8.75 2.5 8.75 2.5 0 0 1-8.75 2.5 8.75 2.5 0 0 1-8.75-2.5 8.75 2.5 0 0 1 8.75-2.5z"
+     color="#eff0f1"
+     fill="#232629"
+     id="path6" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#eff0f1;fill:#5fd35f;fill-opacity:1;stroke:#5fd35f;stroke-width:0.69053423;stroke-opacity:1"
+     class="ColorScheme-Text"
+     d="m 20.12312,12.466193 -5.901694,6.188665 -2.344551,-2.458488 -0.399776,0.419213 2.344551,2.458488 -0.0011,0.0012 0.399787,0.419209 0.0011,-0.0012 0.0011,0.0012 0.399771,-0.419209 -0.0011,-0.0012 5.901694,-6.188665 -0.399777,-0.419203 z"
+     id="path6-5" />
+</svg>
Binary file eric7/icons/oxygen/vcsResolved.png has changed

eric ide

mercurial