Plugins/VcsPlugins/vcsMercurial/HgStatusDialog.py

changeset 5522
e07d1df4c64a
parent 5520
2a97a4d58bc6
child 5587
ea526b78ee6c
diff -r 37089cbeb1b9 -r e07d1df4c64a Plugins/VcsPlugins/vcsMercurial/HgStatusDialog.py
--- a/Plugins/VcsPlugins/vcsMercurial/HgStatusDialog.py	Mon Feb 13 19:08:26 2017 +0100
+++ b/Plugins/VcsPlugins/vcsMercurial/HgStatusDialog.py	Tue Feb 14 19:57:58 2017 +0100
@@ -16,10 +16,10 @@
 
 import os
 
-from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer, QSize
-from PyQt5.QtGui import QTextCursor
+from PyQt5.QtCore import pyqtSlot, qVersion, Qt, QProcess, QTimer, QSize
+from PyQt5.QtGui import QTextCursor, QCursor
 from PyQt5.QtWidgets import QWidget, QDialogButtonBox, QMenu, QHeaderView, \
-    QTreeWidgetItem, QLineEdit
+    QTreeWidgetItem, QLineEdit, QToolTip
 
 from E5Gui.E5Application import e5App
 from E5Gui import E5MessageBox
@@ -30,10 +30,9 @@
 from .HgDiffGenerator import HgDiffGenerator
 
 import Preferences
+import UI.PixmapCache
 
 
-# TODO: convert action buttons to a tool button with menu and delete status
-#       list context menu (i.e. make it the action menu)
 class HgStatusDialog(QWidget, Ui_HgStatusDialog):
     """
     Class implementing a dialog to show the output of the hg status command
@@ -76,8 +75,6 @@
             self.process.readyReadStandardOutput.connect(self.__readStdout)
             self.process.readyReadStandardError.connect(self.__readStderr)
         
-        self.diffSplitter.setSizes([300, 300])
-        
         self.statusList.headerItem().setText(self.__lastColumn, "")
         self.statusList.header().setSortIndicator(
             self.__pathColumn, Qt.AscendingOrder)
@@ -92,86 +89,6 @@
         
         self.__selectedName = ""
         
-        if mq:
-            self.buttonsLine.setVisible(False)
-            self.addButton.setVisible(False)
-            self.diffButton.setVisible(False)
-            self.sbsDiffButton.setVisible(False)
-            self.revertButton.setVisible(False)
-            self.forgetButton.setVisible(False)
-            self.restoreButton.setVisible(False)
-            
-            self.diffEdit.setVisible(False)
-        
-        self.menuactions = []
-        self.lfActions = []
-        self.menu = QMenu()
-        if not mq:
-            self.__commitAct = self.menu.addAction(
-                self.tr("Commit changes to repository..."), self.__commit)
-            self.menuactions.append(self.__commitAct)
-            self.menuactions.append(self.menu.addAction(
-                self.tr("Select all for commit"), self.__commitSelectAll))
-            self.menuactions.append(self.menu.addAction(
-                self.tr("Deselect all from commit"),
-                self.__commitDeselectAll))
-            self.menu.addSeparator()
-            self.__addAct = self.menu.addAction(
-                self.tr("Add to repository"), self.__add)
-            self.menuactions.append(self.__addAct)
-            self.lfActions.append(self.menu.addAction(
-                self.tr("Add as Large File"),
-                lambda: self.__lfAdd("large")))
-            self.lfActions.append(self.menu.addAction(
-                self.tr("Add as Normal File"),
-                lambda: self.__lfAdd("normal")))
-            self.menu.addSeparator()
-            self.__diffAct = self.menu.addAction(
-                self.tr("Show differences"), self.__diff)
-            self.menuactions.append(self.__diffAct)
-            self.__sbsDiffAct = self.menu.addAction(
-                self.tr("Show differences side-by-side"), self.__sbsDiff)
-            self.menuactions.append(self.__sbsDiffAct)
-            self.menu.addSeparator()
-            self.__revertAct = self.menu.addAction(
-                self.tr("Revert changes"), self.__revert)
-            self.menuactions.append(self.__revertAct)
-            self.__forgetAct = self.menu.addAction(
-                self.tr("Forget missing"), self.__forget)
-            self.menuactions.append(self.__forgetAct)
-            self.__restoreAct = self.menu.addAction(
-                self.tr("Restore missing"), self.__restoreMissing)
-            self.menuactions.append(self.__restoreAct)
-            self.menu.addSeparator()
-            self.menuactions.append(self.menu.addAction(
-                self.tr("Adjust column sizes"), self.__resizeColumns))
-            for act in self.menuactions:
-                act.setEnabled(False)
-            for act in self.lfActions:
-                act.setEnabled(False)
-            
-            self.statusList.setContextMenuPolicy(Qt.CustomContextMenu)
-            self.statusList.customContextMenuRequested.connect(
-                self.__showContextMenu)
-        
-        if not mq:
-            self.__lfAddActions = []
-            self.__addButtonMenu = QMenu()
-            self.__addButtonMenu.addAction(self.tr("Add"), self.__add)
-            self.__lfAddActions.append(
-                self.__addButtonMenu.addAction(self.tr("Add as Large File"),
-                                               lambda: self.__lfAdd("large")))
-            self.__lfAddActions.append(
-                self.__addButtonMenu.addAction(self.tr("Add as Normal File"),
-                                               lambda: self.__lfAdd("normal")))
-            self.__addButtonMenu.aboutToShow.connect(self.__showAddMenu)
-            if self.vcs.isExtensionActive("largefiles"):
-                self.addButton.setMenu(self.__addButtonMenu)
-        
-        if not mq:
-            self.vcs.activeExtensionsChanged.connect(
-                self.__activeExtensionsChanged)
-        
         self.modifiedIndicators = [
             self.tr('added'),
             self.tr('modified'),
@@ -195,6 +112,105 @@
             '?': self.tr('not tracked'),
             '!': self.tr('missing'),
         }
+        
+        self.__initActionsMenu()
+        
+        if mq:
+            self.diffLabel.setVisible(False)
+            self.diffEdit.setVisible(False)
+            self.actionsButton.setEnabled(False)
+            self.diffSplitter.setSizes([600, 0])
+        else:
+            self.diffSplitter.setSizes([300, 300])
+    
+    def __initActionsMenu(self):
+        """
+        Private method to initialize the actions menu.
+        """
+        self.__actionsMenu = QMenu()
+        self.__actionsMenu.setTearOffEnabled(True)
+        if qVersion() >= "5.1.0":
+            self.__actionsMenu.setToolTipsVisible(True)
+        else:
+            self.__actionsMenu.hovered.connect(self.__actionsMenuHovered)
+        self.__actionsMenu.aboutToShow.connect(self.__showActionsMenu)
+        
+        self.__commitAct = self.__actionsMenu.addAction(
+            self.tr("Commit"), self.__commit)
+        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(
+            self.tr("Unselect all from commit"), self.__commitDeselectAll)
+        
+        self.__actionsMenu.addSeparator()
+        
+        self.__addAct = self.__actionsMenu.addAction(
+            self.tr("Add"), self.__add)
+        self.__addAct.setToolTip(self.tr("Add the selected files"))
+        self.__lfAddLargeAct = self.__actionsMenu.addAction(
+            self.tr("Add as Large Files"), lambda: self.__lfAdd("large"))
+        self.__lfAddLargeAct.setToolTip(self.tr(
+            "Add the selected files as a large files using the 'Large Files'"
+            " extension"))
+        self.__lfAddNormalAct = self.__actionsMenu.addAction(
+            self.tr("Add as Normal Files"), lambda: self.__lfAdd("normal"))
+        self.__lfAddNormalAct.setToolTip(self.tr(
+            "Add the selected files as a normal files using the 'Large Files'"
+            " extension"))
+        
+        self.__actionsMenu.addSeparator()
+        
+        self.__diffAct = self.__actionsMenu.addAction(
+            self.tr("Differences"), self.__diff)
+        self.__diffAct.setToolTip(self.tr(
+            "Shows the differences of the selected entry in a"
+            " separate dialog"))
+        self.__sbsDiffAct = self.__actionsMenu.addAction(
+            self.tr("Differences Side-By-Side"), self.__sbsDiff)
+        self.__sbsDiffAct.setToolTip(self.tr(
+            "Shows the differences of the selected entry side-by-side in"
+            " a separate dialog"))
+        
+        self.__actionsMenu.addSeparator()
+        
+        self.__revertAct = self.__actionsMenu.addAction(
+            self.tr("Revert"), self.__revert)
+        self.__revertAct.setToolTip(self.tr(
+            "Reverts the changes of the selected files"))
+        
+        self.__actionsMenu.addSeparator()
+        
+        self.__forgetAct = self.__actionsMenu.addAction(
+            self.tr("Forget missing"), self.__forget)
+        self.__forgetAct.setToolTip(self.tr(
+            "Forgets about the selected missing files"))
+        self.__restoreAct = self.__actionsMenu.addAction(
+            self.tr("Restore missing"), self.__restoreMissing)
+        self.__restoreAct.setToolTip(self.tr(
+            "Restores the selected missing files"))
+        
+        self.__actionsMenu.addSeparator()
+        
+        act = self.__actionsMenu.addAction(
+            self.tr("Adjust column sizes"), self.__resizeColumns)
+        act.setToolTip(self.tr(
+            "Adjusts the width of all columns to their contents"))
+        
+        self.actionsButton.setIcon(
+            UI.PixmapCache.getIcon("actionsToolButton.png"))
+        self.actionsButton.setMenu(self.__actionsMenu)
+    
+    def __actionsMenuHovered(self, action):
+        """
+        Private slot to show the tooltip for an action menu entry.
+        
+        @param action action to show tooltip for
+        @type QAction
+        """
+        QToolTip.showText(
+            QCursor.pos(), action.toolTip(),
+            self.__actionsMenu, self.__actionsMenu.actionGeometry(action))
     
     def closeEvent(self, e):
         """
@@ -252,17 +268,6 @@
         if diffSplitterState is not None:
             self.diffSplitter.restoreState(diffSplitterState)
     
-    def __activeExtensionsChanged(self):
-        """
-        Private slot handling a change in the activated extensions.
-        """
-        if self.vcs.isExtensionActive("largefiles"):
-            if self.addButton.menu() is None:
-                self.addButton.setMenu(self.__addButtonMenu)
-        else:
-            if self.addButton.menu() is not None:
-                self.addButton.setMenu(None)
-    
     def __resort(self):
         """
         Private method to resort the tree.
@@ -315,18 +320,7 @@
         self.intercept = False
         self.args = fn
         
-        for act in self.menuactions:
-            act.setEnabled(False)
-        for act in self.lfActions:
-            act.setEnabled(False)
-        
-        self.addButton.setEnabled(False)
-        self.commitButton.setEnabled(False)
-        self.diffButton.setEnabled(False)
-        self.sbsDiffButton.setEnabled(False)
-        self.revertButton.setEnabled(False)
-        self.forgetButton.setEnabled(False)
-        self.restoreButton.setEnabled(False)
+        self.actionsButton.setEnabled(False)
         
         self.statusFilterCombo.clear()
         self.__statusFilters = []
@@ -427,15 +421,12 @@
         self.__statusFilters.insert(0, "<{0}>".format(self.tr("all")))
         self.statusFilterCombo.addItems(self.__statusFilters)
         
-        for act in self.menuactions:
-            act.setEnabled(True)
+        if not self.__mq:
+            self.actionsButton.setEnabled(True)
         
         self.__resort()
         self.__resizeColumns()
         
-        self.__updateButtons()
-        self.__updateCommitButton()
-        
         self.__refreshDiff()
     
     def on_buttonBox_clicked(self, button):
@@ -578,28 +569,6 @@
         
         self.start(self.args)
     
-    def __updateButtons(self):
-        """
-        Private method to update the VCS buttons status.
-        """
-        modified = len(self.__getModifiedItems())
-        unversioned = len(self.__getUnversionedItems())
-        missing = len(self.__getMissingItems())
-
-        self.addButton.setEnabled(unversioned)
-        self.diffButton.setEnabled(modified)
-        self.sbsDiffButton.setEnabled(modified == 1)
-        self.revertButton.setEnabled(modified)
-        self.forgetButton.setEnabled(missing)
-        self.restoreButton.setEnabled(missing)
-    
-    def __updateCommitButton(self):
-        """
-        Private method to update the Commit button status.
-        """
-        commitable = len(self.__getCommitableItems())
-        self.commitButton.setEnabled(commitable)
-    
     @pyqtSlot(str)
     def on_statusFilterCombo_activated(self, txt):
         """
@@ -616,88 +585,26 @@
                 topItem = self.statusList.topLevelItem(topIndex)
                 topItem.setHidden(topItem.text(self.__statusColumn) != txt)
     
-    @pyqtSlot(QTreeWidgetItem, int)
-    def on_statusList_itemChanged(self, item, column):
-        """
-        Private slot to act upon item changes.
-        
-        @param item reference to the changed item (QTreeWidgetItem)
-        @param column index of column that changed (integer)
-        """
-        if column == self.__toBeCommittedColumn:
-            self.__updateCommitButton()
-    
     @pyqtSlot()
     def on_statusList_itemSelectionChanged(self):
         """
         Private slot to act upon changes of selected items.
         """
-        self.__updateButtons()
         self.__generateDiffs()
     
-    @pyqtSlot()
-    def on_commitButton_clicked(self):
-        """
-        Private slot to handle the press of the Commit button.
-        """
-        self.__commit()
-    
-    @pyqtSlot()
-    def on_addButton_clicked(self):
-        """
-        Private slot to handle the press of the Add button.
-        """
-        self.__add()
-    
-    @pyqtSlot()
-    def on_diffButton_clicked(self):
-        """
-        Private slot to handle the press of the Differences button.
-        """
-        self.__diff()
-    
-    @pyqtSlot()
-    def on_sbsDiffButton_clicked(self):
-        """
-        Private slot to handle the press of the Side-by-Side Diff button.
-        """
-        self.__sbsDiff()
-    
-    @pyqtSlot()
-    def on_revertButton_clicked(self):
-        """
-        Private slot to handle the press of the Revert button.
-        """
-        self.__revert()
-    
-    @pyqtSlot()
-    def on_forgetButton_clicked(self):
-        """
-        Private slot to handle the press of the Forget button.
-        """
-        self.__forget()
-    
-    @pyqtSlot()
-    def on_restoreButton_clicked(self):
-        """
-        Private slot to handle the press of the Restore button.
-        """
-        self.__restoreMissing()
-    
     ###########################################################################
-    ## Context menu handling methods
+    ## Menu handling methods
     ###########################################################################
     
-    def __showContextMenu(self, coord):
+    def __showActionsMenu(self):
         """
-        Private slot to show the context menu of the status list.
-        
-        @param coord the position of the mouse pointer (QPoint)
+        Private slot to prepare the actions button menu before it is shown.
         """
         modified = len(self.__getModifiedItems())
         unversioned = len(self.__getUnversionedItems())
         missing = len(self.__getMissingItems())
         commitable = len(self.__getCommitableItems())
+        commitableUnselected = len(self.__getCommitableUnselectedItems())
 
         self.__addAct.setEnabled(unversioned)
         self.__diffAct.setEnabled(modified)
@@ -706,22 +613,15 @@
         self.__forgetAct.setEnabled(missing)
         self.__restoreAct.setEnabled(missing)
         self.__commitAct.setEnabled(commitable)
+        self.__commitSelectAct.setEnabled(commitableUnselected)
+        self.__commitDeselectAct.setEnabled(commitable)
         
         if self.vcs.isExtensionActive("largefiles"):
-            enable = len(self.__getUnversionedItems()) > 0
+            enable = bool(unversioned)
         else:
             enable = False
-        for act in self.lfActions:
-            act.setEnabled(enable)
-        self.menu.popup(self.statusList.mapToGlobal(coord))
-    
-    def __showAddMenu(self):
-        """
-        Private slot to prepare the Add button menu before it is shown.
-        """
-        enable = self.vcs.isExtensionActive("largefiles")
-        for act in self.__lfAddActions:
-            act.setEnabled(enable)
+        self.__lfAddLargeAct.setEnabled(enable)
+        self.__lfAddNormalAct.setEnabled(enable)
     
     def __commit(self):
         """
@@ -928,6 +828,21 @@
                 commitableItems.append(itm)
         return commitableItems
     
+    def __getCommitableUnselectedItems(self):
+        """
+        Private method to retrieve all entries the user may commit but hasn't
+        selected.
+        
+        @return list of all items, the user has checked
+        """
+        items = []
+        for index in range(self.statusList.topLevelItemCount()):
+            itm = self.statusList.topLevelItem(index)
+            if itm.flags() & Qt.ItemIsUserCheckable and \
+               itm.checkState(self.__toBeCommittedColumn) == Qt.Unchecked:
+                items.append(itm)
+        return items
+    
     def __getModifiedItems(self):
         """
         Private method to retrieve all entries, that have a modified status.

eric ide

mercurial