[PATCH] Add flat view mode option to directory diff



Hi,

I'm attaching a patch that adds a flat view mode to dir diff. I found it quite useful in some cases, especially when the folder hierarchy is pretty complex yet there are few modified files. Moreover, this change makes dir diff more consistent with vc view.

Cheers,
Piotr
From e748b24931a1c834eb30efa9f34a1704afa26f83 Mon Sep 17 00:00:00 2001
From: Piotr Piastucki <the_leech users berlios de>
Date: Wed, 2 Mar 2011 12:03:22 +0100
Subject: [PATCH 1/4] Add flat view mode to directory diff

---
 data/ui/dirdiff-ui.xml |    2 +
 meld/dirdiff.py        |   60 ++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/data/ui/dirdiff-ui.xml b/data/ui/dirdiff-ui.xml
index 70631af..daa9ebc 100644
--- a/data/ui/dirdiff-ui.xml
+++ b/data/ui/dirdiff-ui.xml
@@ -2,6 +2,7 @@
   <menubar name="Menubar">
     <menu action="ViewMenu">
       <placeholder name="ViewPlaceholder">
+        <menuitem action="Flatten" />
         <menuitem action="IgnoreCase" />
       </placeholder>
       <menu action="FileStatus">
@@ -33,6 +34,7 @@
       <toolitem action="IgnoreCase" />
     </placeholder>
     <placeholder name="FilterActions">
+      <toolitem action="Flatten" />
       <toolitem action="ShowSame" />
       <toolitem action="ShowNew" />
       <toolitem action="ShowModified" />
diff --git a/meld/dirdiff.py b/meld/dirdiff.py
index e8f4ce8..341dc59 100644
--- a/meld/dirdiff.py
+++ b/meld/dirdiff.py
@@ -159,7 +159,7 @@ def _files_same(files, regexes):
     return result
 
 
-COL_EMBLEM, COL_END = tree.COL_END, tree.COL_END + 1
+COL_EMBLEM, COL_LOCATION, COL_END = tree.COL_END, tree.COL_END+1, tree.COL_END+2
 
 ################################################################################
 #
@@ -222,6 +222,7 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
         )
 
         toggleactions = (
+            ("Flatten",     gtk.STOCK_GOTO_BOTTOM, _("Flatten"),  None, _("Flatten directories"), self.on_button_flatten_toggled, False),
             ("IgnoreCase",   gtk.STOCK_ITALIC,  _("Case"),     None, _("Ignore case of entries"), self.on_button_ignore_case_toggled, False),
             ("ShowSame",     gtk.STOCK_APPLY,   _("Same"),     None, _("Show identical"), self.on_filter_state_normal_toggled, True),
             ("ShowNew",      gtk.STOCK_ADD,     _("New"),      None, _("Show new"), self.on_filter_state_new_toggled, True),
@@ -241,7 +242,7 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
         self.create_text_filters()
         app.connect("text-filters-changed", self.on_text_filters_changed)
         for button in ("DirCompare", "DirCopyLeft", "DirCopyRight",
-                       "DirDelete", "Hide", "IgnoreCase", "ShowSame",
+                       "DirDelete", "Hide", "Flatten", "IgnoreCase", "ShowSame",
                        "ShowNew", "ShowModified", "CustomFilterMenu"):
             self.actiongroup.get_action(button).props.is_important = True
         self.map_widgets_into_lists(["treeview", "fileentry", "scrolledwindow",
@@ -257,10 +258,11 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
             self.focus_out_events.append(handler_id)
         self.on_treeview_focus_out_event(None, None)
         self.treeview_focussed = None
-
+        self.treeview_column_location = []
+        flatten = self.actiongroup.get_action("Flatten").get_active()
         for i in range(3):
             self.treeview[i].get_selection().set_mode(gtk.SELECTION_MULTIPLE)
-            column = gtk.TreeViewColumn()
+            column = gtk.TreeViewColumn(_("Name"))
             rentext = gtk.CellRendererText()
             renicon = ui.emblemcellrenderer.EmblemCellRenderer()
             column.pack_start(renicon, expand=0)
@@ -272,6 +274,15 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
                                   emblem_name=col_index(COL_EMBLEM, i),
                                   icon_tint=col_index(tree.COL_TINT, i))
             self.treeview[i].append_column(column)
+            
+            column = gtk.TreeViewColumn(_("Location"))
+            rentext = gtk.CellRendererText()
+            column.pack_start(rentext, expand=0)
+            column.set_attributes(rentext, markup=col_index(COL_LOCATION, i))
+            self.treeview_column_location.append(column)
+            self.treeview[i].set_headers_visible(flatten)
+            column.set_visible(flatten)
+            self.treeview[i].append_column(column)
             self.scrolledwindow[i].get_vadjustment().connect("value-changed", self._sync_vscroll )
             self.scrolledwindow[i].get_hadjustment().connect("value-changed", self._sync_hscroll )
         self.linediffs = [[], []]
@@ -444,6 +455,11 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
         self._update_item_state(it)
         self.scheduler.add_task( self._search_recursively_iter( path ).next )
 
+    def _set_item_location(self, it):
+        for j in range(self.model.ntree):
+            prefixlen = 1 + len( self.model.value_path( self.model.get_iter_root(), j ) )
+            self.model.set_value(it, self.model.column_index(COL_LOCATION, j), os.path.dirname(self.model.value_path(it, j))[prefixlen:])
+
     def _search_recursively_iter(self, rootpath):
         self.actiongroup.get_action("Hide").set_sensitive(False)
         yield _("[%s] Scanning %s") % (self.label_text, "")
@@ -454,11 +470,15 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
 
         shadowed_entries = []
         invalid_filenames = []
+        flatten = self.actiongroup.get_action("Flatten").get_active()
+        dirs_to_remove = []
         while len(todo):
             todo.sort() # depth first
             path = todo.pop(0)
             it = self.model.get_iter( path )
             roots = self.model.value_paths( it )
+            if flatten:
+                it = self.model.get_iter(rootpath)
             yield _("[%s] Scanning %s") % (self.label_text, roots[0][prefixlen:])
             differences = False
             encoding_errors = []
@@ -545,19 +565,35 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
                     child = self.model.add_entries(it, entries)
                     differences |= self._update_item_state(child)
                     todo.append(self.model.get_path(child))
+                    if flatten:
+                        self._set_item_location(child)
+                        keep_dir = False
+                        for pane in range(self.num_panes):
+                            state = self.model.get_state(child, pane)
+                            if state == tree.STATE_NEW or state == tree.STATE_MISSING:
+                                keep_dir = True
+                                break
+                        if not keep_dir:
+                            dirs_to_remove.append(child)
                 for names in allfiles:
                     entries = [os.path.join(r, n) for r, n in zip(roots, names)]
                     child = self.model.add_entries(it, entries)
+                    if flatten:
+                        self._set_item_location(child)
                     differences |= self._update_item_state(child)
-            else: # directory is empty, add a placeholder
+            elif not flatten: # directory is empty, add a placeholder
                 self.model.add_empty(it)
             if differences:
                 expanded.add(path)
-
         self._show_tree_wide_errors(invalid_filenames, shadowed_entries)
-
-        for path in sorted(expanded):
-            self.treeview[0].expand_to_path(path)
+        
+        for node in dirs_to_remove:
+            self.model.remove(node)
+        if flatten:
+            self.treeview[0].expand_row( (0,), 0)
+        else : 
+            for path in sorted(expanded):
+                self.treeview[0].expand_to_path(path)
         yield _("[%s] Done") % self.label_text
         self.actiongroup.get_action("Hide").set_sensitive(True)
 
@@ -816,6 +852,12 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
         if active:
             self.state_filters.append( state )
         self.refresh()
+    def on_button_flatten_toggled(self, button):
+        flatten = self.actiongroup.get_action("Flatten").get_active()
+        for i in range (self.num_panes):
+            self.treeview_column_location[i].set_visible(flatten)
+            self.treeview[i].set_headers_visible(flatten)
+        self.refresh()
     def on_filter_state_normal_toggled(self, button):
         self._update_state_filter( tree.STATE_NORMAL, button.get_active() )
     def on_filter_state_new_toggled(self, button):
-- 
1.7.1



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