[RFC/PATCH] VcView: Add support for not using tabs for diffs



Add the ability to show diffs in a pane to the right of the treeview
when using meld to diff version-controlled files and directories.
Previously each diff was shown in its own tab.

A new preference ("Use seperate tab for each VC diff") has been added
under the "View" menu to allow users to choose whether to use tabs or
not.  The default value of this setting is "True", maintaining current
behavior.

This feature is useful as many people use wide screen monitors
where horizontal space isn't fully utilized.  Being able to see a list
of all files that have differences at all times can be useful in some
circumstances, such as reviewing modifications to a source tree prior
to committing them.

Signed-off-by: Peter Tyser <ptyser gmail com>
---
I was curious what others thought of this.  Its sort of like gedit's
left-hand filelist pane.  I prefer this layout on my work PC (24"
monitors) and widescreen laptops.  There are a couple of other
similar options that could be added to make its functionality
more like gedit.  I made the least changes I could to demonstrate
the concept, but would be open to alternate implementations.

I don't like that this fragments the UI settings a little more,
but adding a side pane to the file and directory diffs seemed
like a can of worms that I'm not prepared to open as I primarly
only use the VcView functionality of meld.

 data/ui/meldapp-ui.xml |    1 +
 data/ui/vcview.ui      |   38 +++++++++++--------
 meld/meldwindow.py     |   91 ++++++++++++++++++++++++++++++++++++++++++++----
 meld/preferences.py    |    3 +-
 meld/vcview.py         |   18 ++++++++--
 5 files changed, 124 insertions(+), 27 deletions(-)

diff --git a/data/ui/meldapp-ui.xml b/data/ui/meldapp-ui.xml
index 1c54a49..c07a814 100644
--- a/data/ui/meldapp-ui.xml
+++ b/data/ui/meldapp-ui.xml
@@ -36,6 +36,7 @@
       <menuitem action="ToolbarVisible" />
       <menuitem action="StatusbarVisible" />
       <menuitem action="Fullscreen" />
+      <menuitem action="UseVCTabs" />
       <separator/>
       <placeholder name="ViewUtilityPlaceholder" />
       <separator/>
diff --git a/data/ui/vcview.ui b/data/ui/vcview.ui
index 1f3387d..d66d459 100644
--- a/data/ui/vcview.ui
+++ b/data/ui/vcview.ui
@@ -53,27 +53,33 @@
             <property name="can_focus">True</property>
             <property name="position">250</property>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow">
+              <object class="GtkHPaned" id="hpaned">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                <property name="shadow_type">GTK_SHADOW_IN</property>
-                <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
                 <child>
-                  <object class="GtkTreeView" id="treeview">
+                  <object class="GtkScrolledWindow" id="scrolledwindow">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="headers_visible">True</property>
-                    <property name="rules_hint">False</property>
-                    <property name="reorderable">False</property>
-                    <property name="enable_search">True</property>
-                    <property name="fixed_height_mode">False</property>
-                    <property name="hover_selection">False</property>
-                    <property name="hover_expand">False</property>
-                    <signal handler="on_row_activated" last_modification_time="Sat, 03 Aug 2002 23:32:49 GMT" name="row_activated"/>
-                    <signal handler="on_button_press_event" last_modification_time="Sat, 30 Aug 2003 12:42:19 GMT" name="button_press_event"/>
-                    <signal handler="on_treeview_popup_menu" name="popup-menu"/>
+                    <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="shadow_type">GTK_SHADOW_IN</property>
+                    <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+                    <child>
+                      <object class="GtkTreeView" id="treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="headers_visible">True</property>
+                        <property name="rules_hint">False</property>
+                        <property name="reorderable">False</property>
+                        <property name="enable_search">True</property>
+                        <property name="fixed_height_mode">False</property>
+                        <property name="hover_selection">False</property>
+                        <property name="hover_expand">False</property>
+                        <signal handler="on_row_activated" last_modification_time="Sat, 03 Aug 2002 23:32:49 GMT" name="row_activated"/>
+                        <signal handler="on_button_press_event" last_modification_time="Sat, 30 Aug 2003 12:42:19 GMT" name="button_press_event"/>
+                        <signal handler="on_treeview_popup_menu" name="popup-menu"/>
+                      </object>
+                    </child>
                   </object>
                 </child>
               </object>
diff --git a/meld/meldwindow.py b/meld/meldwindow.py
index e83ba2d..6881773 100644
--- a/meld/meldwindow.py
+++ b/meld/meldwindow.py
@@ -166,7 +166,8 @@ class MeldWindow(gnomeglade.Component):
         toggleactions = (
             ("Fullscreen",       None, _("Full Screen"), "F11", _("View the comparison in full screen"), self.on_action_fullscreen_toggled, False),
             ("ToolbarVisible",   None, _("_Toolbar"),   None, _("Show or hide the toolbar"),   self.on_menu_toolbar_toggled,   app.prefs.toolbar_visible),
-            ("StatusbarVisible", None, _("_Statusbar"), None, _("Show or hide the statusbar"), self.on_menu_statusbar_toggled, app.prefs.statusbar_visible)
+            ("StatusbarVisible", None, _("_Statusbar"), None, _("Show or hide the statusbar"), self.on_menu_statusbar_toggled, app.prefs.statusbar_visible),
+            ("UseVCTabs",        None, _("Use VC Tabs"), None, _("Use seperate tab for each VC diff"), self.on_menu_use_vc_tabs_toggled, app.prefs.use_vc_tabs)
         )
         ui_file = paths.ui_dir("meldapp-ui.xml")
         self.actiongroup = gtk.ActionGroup('MainActions')
@@ -463,6 +464,44 @@ class MeldWindow(gnomeglade.Component):
     def on_menu_statusbar_toggled(self, widget):
         app.prefs.statusbar_visible = widget.get_active()
 
+    # If enabled, diffs for files under version control will be shown in new
+    # tabs.  If disabled, they will shown in a horizontal pane of the same
+    # window as the vcview itself.
+    def on_menu_use_vc_tabs_toggled(self, widget):
+        if app.prefs.use_vc_tabs:
+            # If switching to not use tabs, try and remove all existing tabs
+            for c in reversed(self.notebook.get_children()):
+                page = c.get_data("pyobject")
+
+                # Don't remove the VcView page - it'll contain a pane with a
+                # treeview of files, as well as a pane for diffs
+                if isinstance(page, vcview.VcView):
+                    continue
+
+                self.notebook.set_current_page(self.notebook.page_num(page.widget))
+                response = self.try_remove_page(page, appquit=1)
+
+                # If the user doesn't want to close all the existing tabs, don't
+                # toggle the "Use VC Tabs" setting
+                if response == gtk.RESPONSE_CANCEL:
+                    widget.set_active(True)
+        else:
+            # If switching to use tabs, remove current diff in horizontal pane
+            diff_pane = self.hpaned.get_child2()
+            if diff_pane:
+                # Try and remove the diff pane.  If the user doesn't want to
+                # close it, don't toggle the "Use VC Tabs" setting
+                response = diff_pane.get_data("pyobject").on_delete_event()
+                if response == gtk.RESPONSE_CANCEL:
+                    widget.set_active(False)
+                else:
+                    self.hpaned.remove(self.hpaned.get_child2())
+
+        app.prefs.use_vc_tabs = widget.get_active()
+
+        # Don't show the notebook tabs if we aren't using them
+        self.notebook.set_property("show-tabs", app.prefs.use_vc_tabs)
+
     #
     # Toolbar and menu items (help)
     #
@@ -568,11 +607,45 @@ class MeldWindow(gnomeglade.Component):
                 page.on_file_changed(filename)
 
     def _append_page(self, page, icon):
-        nbl = notebooklabel.NotebookLabel(icon, "", lambda b: self.try_remove_page(page))
-        self.notebook.append_page( page.widget, nbl)
-        self.notebook.set_current_page( self.notebook.page_num(page.widget) )
-        self.scheduler.add_scheduler(page.scheduler)
-        page.connect("label-changed", self.on_notebook_label_changed)
+        if isinstance(page, vcview.VcView):
+            # If appending a VcView, grab the reference to its righthand
+            # horizontal pane for later use
+            self.hpaned = page.hpaned
+
+            # If diffs are not shown in tabs, don't show any tabs
+            self.notebook.set_property("show-tabs", app.prefs.use_vc_tabs)
+        if isinstance(page, filediff.FileDiff) and app.prefs.use_vc_tabs == False and \
+            hasattr(self, "hpaned"):
+            diff_pane = self.hpaned.get_child2()
+            if diff_pane:
+                # We're starting a new diff in the VcView's righthand pane, remove
+                # the existing diff if one exists
+                response = diff_pane.get_data("pyobject").on_delete_event()
+                if response == gtk.RESPONSE_CANCEL:
+                    return
+                self.hpaned.remove(diff_pane)
+            else:
+                # This is the first diff in the VcView's righthand pane.
+                # Calculate the width of the file listing TreeView in the
+                # left-hand pane and resize the diff to occupy all remaining
+                # space.  We only calculate the pane size 1 time so that if a
+                # user changes the horizontal spacing, their setting is maintained
+                treeview = self.hpaned.get_child1().get_child()
+                total_width = 0
+                for col in treeview.get_columns()[:-1]:
+                    total_width += col.get_width()
+                self.hpaned.set_position(total_width)
+
+            # Add the diff in the right-hand pane
+            self.hpaned.pack2(page.widget, True, False)
+            self.scheduler.add_scheduler(page.scheduler)
+        else:
+            # We're using tabs for new diffs
+            nbl = notebooklabel.NotebookLabel(icon, "", lambda b: self.try_remove_page(page))
+            self.notebook.append_page( page.widget, nbl)
+            self.notebook.set_current_page( self.notebook.page_num(page.widget) )
+            self.scheduler.add_scheduler(page.scheduler)
+            page.connect("label-changed", self.on_notebook_label_changed)
         page.connect("file-changed", self.on_file_changed)
         page.connect("create-diff", lambda obj,arg: self.append_diff(arg) )
         page.connect("status-changed", lambda junk,arg: self.statusbar.set_doc_status(arg) )
@@ -654,7 +727,11 @@ class MeldWindow(gnomeglade.Component):
         "Get the current doc or a dummy object if there is no current"
         index = self.notebook.get_current_page()
         if index >= 0:
-            return self.notebook.get_nth_page(index).get_data("pyobject")
+            if app.prefs.use_vc_tabs:
+                return self.notebook.get_nth_page(index).get_data("pyobject")
+            else:
+                return self.hpaned.get_child2().get_data("pyobject")
+
         class DummyDoc(object):
             def __getattr__(self, a): return lambda *x: None
         return DummyDoc()
diff --git a/meld/preferences.py b/meld/preferences.py
index 7c10bb7..69ae217 100644
--- a/meld/preferences.py
+++ b/meld/preferences.py
@@ -251,7 +251,8 @@ class MeldPreferences(prefs.Preferences):
             _("Script comment\t0\t#.*")),
         "ignore_blank_lines" : prefs.Value(prefs.BOOL, False),
         "toolbar_visible" : prefs.Value(prefs.BOOL, True),
-        "statusbar_visible" : prefs.Value(prefs.BOOL, True)
+        "statusbar_visible" : prefs.Value(prefs.BOOL, True),
+        "use_vc_tabs" : prefs.Value(prefs.BOOL, True)
     }
 
     def __init__(self):
diff --git a/meld/vcview.py b/meld/vcview.py
index 51f281b..e37f725 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -75,7 +75,7 @@ class CommitDialog(gnomeglade.Component):
         buf = self.textview.get_buffer()
         buf.set_text( gentry.child.get_text() )
 
-COL_LOCATION, COL_STATUS, COL_REVISION, COL_TAG, COL_OPTIONS, COL_END = range(tree.COL_END, tree.COL_END+6)
+COL_LOCATION, COL_STATUS, COL_REVISION, COL_TAG, COL_OPTIONS, COL_MARKER, COL_END = range(tree.COL_END, tree.COL_END+7)
 
 class VcTreeStore(tree.DiffTreeStore):
     def __init__(self):
@@ -179,6 +179,9 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
         addCol(_("Tag"), COL_TAG)
         addCol(_("Options"), COL_OPTIONS)
 
+	# Add an empty column to mark where the last "real" column ends
+        addCol("", COL_MARKER)
+
         class ConsoleStream(object):
             def __init__(self, textview):
                 self.textview = textview
@@ -363,8 +366,17 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
                 shutil.rmtree(f, ignore_errors=1)
 
     def on_delete_event(self, appquit=0):
-        self.on_quit_event()
-        return gtk.RESPONSE_OK
+        response = gtk.RESPONSE_OK
+
+        # If the vcview has a diff displayed in its righthand pane make sure
+        # it can be deleted before deleting the vcview itself
+        diff_pane = self.hpaned.get_child2()
+        if diff_pane:
+            response = diff_pane.get_data("pyobject").on_delete_event(appquit)
+        if response != gtk.RESPONSE_CANCEL:
+            self.on_quit_event()
+
+        return response
 
     def on_row_activated(self, treeview, path, tvc):
         it = self.model.get_iter(path)
-- 
1.7.1.13.gcfb88



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