[meld] Improve sensitivity handling by delegating to VC modules (bgo#698511)



commit e914fd49124fc568979cf1d8490f9bfe232f5a71
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Sun May 19 08:58:14 2013 +1000

    Improve sensitivity handling by delegating to VC modules (bgo#698511)
    
    Currently all of our sensitivity handling in VC views is done purely
    on the basis of the capabilities of a VC, and whether or not the view
    has a selection. This gives bad information in many cases, such as
    allowing an unversioned file to be reverted.
    
    This commit adds new API to the VC module interface that delegates
    the decisions about what VC actions to enable for a given selection.
    Currently only Git support this interface, but it's designed to be
    very VC-neutral.

 meld/tree.py   |    5 ++++-
 meld/vc/git.py |   28 +++++++++++++++++++++++++++-
 meld/vcview.py |   35 +++++++++++++++++++++++++++++++----
 3 files changed, 62 insertions(+), 6 deletions(-)
---
diff --git a/meld/tree.py b/meld/tree.py
index 2962908..8a341d7 100644
--- a/meld/tree.py
+++ b/meld/tree.py
@@ -153,7 +153,10 @@ class DiffTreeStore(gtk.TreeStore):
 
     def get_state(self, it, pane):
         STATE = self.column_index(COL_STATE, pane)
-        return int(self.get_value(it, STATE))
+        try:
+            return int(self.get_value(it, STATE))
+        except TypeError:
+            return None
 
     def inorder_search_down(self, it):
         while it:
diff --git a/meld/vc/git.py b/meld/vc/git.py
index e840715..403fc1c 100644
--- a/meld/vc/git.py
+++ b/meld/vc/git.py
@@ -68,6 +68,7 @@ class Vc(_vc.CachedVc):
     def __init__(self, location):
         super(Vc, self).__init__(location)
         self.diff_re = re.compile(self.GIT_DIFF_FILES_RE)
+        self._tree_cache = {}
         self._tree_meta_cache = {}
 
     def check_repo_root(self, location):
@@ -96,6 +97,32 @@ class Vc(_vc.CachedVc):
 
     # Prototyping VC interface version 2
 
+    def update_actions_for_paths(self, path_states, actions):
+        states = path_states.values()
+
+        actions["VcCompare"] = bool(path_states)
+        # TODO: We can't disable this for NORMAL, because folders don't
+        # inherit any state from their children, but committing a folder with
+        # modified children is expected behaviour.
+        actions["VcCommit"] = all(s not in (
+            _vc.STATE_NONE, _vc.STATE_IGNORED) for s in states)
+
+        actions["VcUpdate"] = True
+        # TODO: We can't do this; this shells out for each selection change...
+        # actions["VcPush"] = bool(self.get_commits_to_push())
+        actions["VcPush"] = True
+
+        actions["VcAdd"] = all(s not in (
+            _vc.STATE_NORMAL, _vc.STATE_REMOVED) for s in states)
+        actions["VcResolved"] = all(s == _vc.STATE_CONFLICT for s in states)
+        actions["VcRemove"] = (all(s not in (
+            _vc.STATE_NONE, _vc.STATE_IGNORED,
+            _vc.STATE_REMOVED) for s in states) and
+            self.root not in path_states.keys())
+        actions["VcRevert"] = all(s not in (
+            _vc.STATE_NONE, _vc.STATE_NORMAL,
+            _vc.STATE_IGNORED) for s in states)
+
     def get_commits_to_push_summary(self):
         branch_refs = self.get_commits_to_push()
         unpushed_branches = len([v for v in branch_refs.values() if v])
@@ -322,7 +349,6 @@ class Vc(_vc.CachedVc):
         # Get a list of all files in rootdir, as well as their status
         tree_state = {}
         self._update_tree_state_cache("./", tree_state)
-
         return tree_state
 
     def update_file_state(self, path):
diff --git a/meld/vcview.py b/meld/vcview.py
index 462ed33..0c898ee 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -485,6 +485,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
                 pass
 
             self.scheduler.add_task(self._search_recursively_iter(root))
+            self.scheduler.add_task(self.on_treeview_selection_changed)
             self.scheduler.add_task(self.on_treeview_cursor_changed)
 
     def get_comparison(self):
@@ -667,11 +668,36 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
         self.prefs.vc_status_filters = active_filters
         self.refresh()
 
-    def on_treeview_selection_changed(self, selection):
+    def on_treeview_selection_changed(self, selection=None):
+
+        def set_sensitive(action, sensitive):
+            self.actiongroup.get_action(action).set_sensitive(sensitive)
+
+        if selection is None:
+            selection = self.treeview.get_selection()
         model, rows = selection.get_selected_rows()
-        have_selection = bool(rows)
-        for action in self.valid_vc_actions:
-            self.actiongroup.get_action(action).set_sensitive(have_selection)
+        if hasattr(self.vc, 'update_actions_for_paths'):
+            paths = [self.model.value_path(model.get_iter(r), 0) for r in rows]
+            states = [self.model.get_state(model.get_iter(r), 0) for r in rows]
+            action_sensitivity = {
+                "VcCompare": False,
+                "VcCommit": False,
+                "VcUpdate": False,
+                "VcPush": False,
+                "VcAdd": False,
+                "VcResolved": False,
+                "VcRemove": False,
+                "VcRevert": False,
+                "VcDeleteLocally": bool(paths) and self.vc.root not in paths,
+            }
+            path_states = dict(zip(paths, states))
+            self.vc.update_actions_for_paths(path_states, action_sensitivity)
+            for action, sensitivity in action_sensitivity.items():
+                set_sensitive(action, sensitivity)
+        else:
+            have_selection = bool(rows)
+            for action in self.valid_vc_actions:
+                set_sensitive(action, have_selection)
 
     def _get_selected_files(self):
         model, rows = self.treeview.get_selection().get_selected_rows()
@@ -869,6 +895,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
                 self.treeview.grab_focus()
                 self.treeview.get_selection().select_iter(newiter)
                 self.scheduler.add_task(self._search_recursively_iter(newiter))
+                self.scheduler.add_task(self.on_treeview_selection_changed)
                 self.scheduler.add_task(self.on_treeview_cursor_changed)
         else: # XXX fixme
             self.refresh()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]