* Jelmer Vernooij <[EMAIL PROTECTED]> wrote:
> * Scott Scriven wrote:
> > The changes are available in my branch:
> > 
> >   lp:~toykeeper/bzr-gtk/bzr-vis-enhancements/
>
> I like this in general. I would prefer to see the diff panel 
> below the revision metadata and file list, but I can live with 
> the current patch being merged.

It now includes an option to specify bottom-right or just bottom.  
The file list is still attached to the diff text, since it's a 
single widget.

> - Please don't use hasattr() since it swallows exceptions

Fixed.

> - Please make not showing diffs the default

Fixed.


-- Scott
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [EMAIL PROTECTED]
# target_branch: https://code.launchpad.net/~bzr-gtk/bzr-gtk/trunk
# testament_sha1: c1b530f0d543f3994fa18ed642f0538f84820b48
# timestamp: 2008-07-17 06:07:55 -0600
# source_branch: https://code.launchpad.net/~bzr-gtk/bzr-gtk/trunk
# base_revision_id: [EMAIL PROTECTED]
# 
# Begin patch
=== modified file 'NEWS'
--- NEWS	2008-07-01 21:56:25 +0000
+++ NEWS	2008-07-11 17:36:56 +0000
@@ -11,6 +11,12 @@
 
   * Add "Send Merge Directive" button in bzr viz. (Jelmer Vernooij)
 
+  * Added an optional diff panel to bzr vis.  (Scott Scriven)
+
+  * Made bzr vis remember whether the toolbar is visible.  (Scott Scriven)
+
+  * Made bzr vis remember window and panel sizes.  (Scott Scriven)
+
  BUG FIXES
 
   * Replace _() calls by _i18n() calls. (Vincent Ladeuil, #187283)
@@ -30,6 +36,10 @@
 
   * List network drives in Olive. (Kevin Light, #244308)
 
+  * Removed some redundant screen redrawing in bzr vis.  (Scott Scriven)
+
+  * Fixed overflowing labels in bzr vis.  (Scott Scriven)
+
  CHANGES
 
   * Moved notify icon code to separate script. (Jelmer Vernooij)

=== modified file 'branchview/treeview.py'
--- branchview/treeview.py	2008-06-30 20:11:24 +0000
+++ branchview/treeview.py	2008-07-10 06:23:54 +0000
@@ -325,6 +325,7 @@
         if set_tooltip is not None:
             set_tooltip(treemodel.MESSAGE)
 
+        self._prev_cursor_path = None
         self.treeview.connect("cursor-changed",
                 self._on_selection_changed)
 
@@ -400,7 +401,8 @@
     def _on_selection_changed(self, treeview):
         """callback for when the treeview changes."""
         (path, focus) = treeview.get_cursor()
-        if path is not None:
+        if (path is not None) and (path != self._prev_cursor_path):
+            self._prev_cursor_path = path # avoid emitting twice per click
             self.iter = self.model.get_iter(path)
             self.emit('revision-selected')
 

=== modified file 'diff.py'
--- diff.py	2008-05-22 02:33:40 +0000
+++ diff.py	2008-07-17 11:24:26 +0000
@@ -330,9 +330,10 @@
         # text view
 
     def set_diff_text_sections(self, sections):
-        self.diff_view = DiffFileView()
+        if getattr(self, 'diff_view', None) is None:
+            self.diff_view = DiffFileView()
+            self.pack2(self.diff_view)
         self.diff_view.show()
-        self.pack2(self.diff_view)
         for oldname, newname, patch in sections:
             self.diff_view._diffs[newname] = str(patch)
             if newname is None:
@@ -346,8 +347,9 @@
         Compares the two trees and populates the window with the
         differences.
         """
-        self.diff_view = DiffView()
-        self.pack2(self.diff_view)
+        if getattr(self, 'diff_view', None) is None:
+            self.diff_view = DiffView()
+            self.pack2(self.diff_view)
         self.diff_view.show()
         self.diff_view.set_trees(rev_tree, parent_tree)
         self.rev_tree = rev_tree
@@ -380,6 +382,7 @@
                 self.model.append(titer, [ path, path ])
 
         self.treeview.expand_all()
+        self.diff_view.show_diff(None)
 
     def set_file(self, file_path):
         """Select the current file to display"""

=== modified file 'revisionview.py'
--- revisionview.py	2008-06-29 19:18:34 +0000
+++ revisionview.py	2008-07-11 15:46:32 +0000
@@ -509,7 +509,7 @@
         table.resize(max(len(revids), 1), 2)
 
         for idx, revid in enumerate(revids):
-            align = gtk.Alignment(0.0, 0.0)
+            align = gtk.Alignment(0.0, 0.0, 1, 1)
             widgets.append(align)
             table.attach(align, 1, 2, idx, idx + 1,
                                       gtk.EXPAND | gtk.FILL, gtk.FILL)
@@ -532,12 +532,16 @@
                 hbox.pack_start(button, expand=False, fill=True)
                 button.show()
 
-            button = gtk.Button(revid)
+            button = gtk.Button()
+            revid_label = gtk.Label(str(revid))
+            revid_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
+            revid_label.set_alignment(0.0, 0.5)
+            button.add(revid_label)
             button.connect("clicked",
                     lambda w, r: self.set_revision(self._repository.get_revision(r)), revid)
             button.set_use_underline(False)
-            hbox.pack_start(button, expand=False, fill=True)
-            button.show()
+            hbox.pack_start(button, expand=True, fill=True)
+            button.show_all()
 
     def _create_general(self):
         vbox = gtk.VBox(False, 6)
@@ -566,102 +570,91 @@
         self.table.set_col_spacings(6)
         self.table.show()
 
-        align = gtk.Alignment(1.0, 0.5)
+        row = 0
+
         label = gtk.Label()
+        label.set_alignment(1.0, 0.5)
         label.set_markup("<b>Revision Id:</b>")
-        align.add(label)
-        self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
         label.show()
 
-        align = gtk.Alignment(0.0, 0.5)
         revision_id = gtk.Label()
+        revision_id.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
+        revision_id.set_alignment(0.0, 0.5)
         revision_id.set_selectable(True)
         self.connect('notify::revision', 
                 lambda w, p: revision_id.set_text(self._revision.revision_id))
-        align.add(revision_id)
-        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(revision_id, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
         revision_id.show()
 
-        align = gtk.Alignment(1.0, 0.5)
+        row += 1
         self.author_label = gtk.Label()
+        self.author_label.set_alignment(1.0, 0.5)
         self.author_label.set_markup("<b>Author:</b>")
-        align.add(self.author_label)
-        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(self.author_label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
         self.author_label.show()
 
-        align = gtk.Alignment(0.0, 0.5)
         self.author = gtk.Label()
+        self.author.set_ellipsize(pango.ELLIPSIZE_END)
+        self.author.set_alignment(0.0, 0.5)
         self.author.set_selectable(True)
-        align.add(self.author)
-        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(self.author, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
         self.author.show()
         self.author.hide()
 
-        align = gtk.Alignment(1.0, 0.5)
+        row += 1
         label = gtk.Label()
+        label.set_alignment(1.0, 0.5)
         label.set_markup("<b>Committer:</b>")
-        align.add(label)
-        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
         label.show()
 
-        align = gtk.Alignment(0.0, 0.5)
         self.committer = gtk.Label()
+        self.committer.set_ellipsize(pango.ELLIPSIZE_END)
+        self.committer.set_alignment(0.0, 0.5)
         self.committer.set_selectable(True)
-        align.add(self.committer)
-        self.table.attach(align, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(self.committer, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
         self.committer.show()
 
-        align = gtk.Alignment(0.0, 0.5)
+        row += 1
         label = gtk.Label()
+        label.set_alignment(1.0, 0.5)
         label.set_markup("<b>Branch nick:</b>")
-        align.add(label)
-        self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
+        self.table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
         label.show()
-        align.show()
 
-        align = gtk.Alignment(0.0, 0.5)
         self.branchnick_label = gtk.Label()
+        self.branchnick_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
+        self.branchnick_label.set_alignment(0.0, 0.5)
         self.branchnick_label.set_selectable(True)
-        align.add(self.branchnick_label)
-        self.table.attach(align, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
+        self.table.attach(self.branchnick_label, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
         self.branchnick_label.show()
-        align.show()
 
-        align = gtk.Alignment(1.0, 0.5)
+        row += 1
         label = gtk.Label()
+        label.set_alignment(1.0, 0.5)
         label.set_markup("<b>Timestamp:</b>")
-        align.add(label)
-        self.table.attach(align, 0, 1, 4, 5, gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
         label.show()
 
-        align = gtk.Alignment(0.0, 0.5)
         self.timestamp = gtk.Label()
+        self.timestamp.set_ellipsize(pango.ELLIPSIZE_END)
+        self.timestamp.set_alignment(0.0, 0.5)
         self.timestamp.set_selectable(True)
-        align.add(self.timestamp)
-        self.table.attach(align, 1, 2, 4, 5, gtk.EXPAND | gtk.FILL, gtk.FILL)
-        align.show()
+        self.table.attach(self.timestamp, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
         self.timestamp.show()
 
-        align = gtk.Alignment(1.0, 0.5)
+        row += 1
         self.tags_label = gtk.Label()
+        self.tags_label.set_alignment(1.0, 0.5)
         self.tags_label.set_markup("<b>Tags:</b>")
-        align.add(self.tags_label)
-        align.show()
-        self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
+        self.table.attach(self.tags_label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
         self.tags_label.show()
 
-        align = gtk.Alignment(0.0, 0.5)
         self.tags_list = gtk.Label()
-        align.add(self.tags_list)
-        self.table.attach(align, 1, 2, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL)
-        align.show()
+        self.tags_list.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
+        self.tags_list.set_alignment(0.0, 0.5)
+        self.table.attach(self.tags_list, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
         self.tags_list.show()
 
         self.connect('notify::revision', self._add_tags)

=== modified file 'viz/branchwin.py'
--- viz/branchwin.py	2008-07-01 21:54:21 +0000
+++ viz/branchwin.py	2008-07-17 12:06:33 +0000
@@ -48,6 +48,8 @@
         self.maxnum      = maxnum
         self.config      = GlobalConfig()
 
+        self._sizes      = {} # window and widget sizes
+
         if self.config.get_user_option('viz-compact-view') == 'yes':
             self.compact_view = True
         else:
@@ -60,7 +62,13 @@
         monitor = screen.get_monitor_geometry(0)
         width = int(monitor.width * 0.75)
         height = int(monitor.height * 0.75)
+        # user-configured window size
+        size = self._load_size('viz-window-size')
+        if size:
+            width, height = size
         self.set_default_size(width, height)
+        self.set_size_request(width/3, height/3)
+        self.connect("size-allocate", self._on_size_allocate, 'viz-window-size')
 
         # FIXME AndyFitz!
         icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
@@ -104,13 +112,15 @@
         self.add(vbox)
 
         self.paned = gtk.VPaned()
-        self.paned.pack1(self.construct_top(), resize=True, shrink=False)
-        self.paned.pack2(self.construct_bottom(), resize=False, shrink=True)
+        self.paned.pack1(self.construct_top(), resize=False, shrink=True)
+        self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
         self.paned.show()
 
-        vbox.pack_start(self.construct_menubar(), expand=False, fill=True)
-        vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
-        
+        nav = self.construct_navigation()
+        menubar = self.construct_menubar()
+        vbox.pack_start(menubar, expand=False, fill=True)
+        vbox.pack_start(nav, expand=False, fill=True)
+
         vbox.pack_start(self.paned, expand=True, fill=True)
         vbox.set_focus_child(self.paned)
 
@@ -161,14 +171,31 @@
 
         view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
         view_menu_toolbar.set_active(True)
+        if self.config.get_user_option('viz-toolbar-visible') == 'False':
+            view_menu_toolbar.set_active(False)
+            self.toolbar.hide()
         view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
 
         view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
         view_menu_compact.set_active(self.compact_view)
         view_menu_compact.connect('activate', self._brokenlines_toggled_cb)
 
+        view_menu_diffs = gtk.CheckMenuItem("Show Diffs")
+        view_menu_diffs.set_active(False)
+        if self.config.get_user_option('viz-show-diffs') == 'True':
+            view_menu_diffs.set_active(True)
+        view_menu_diffs.connect('toggled', self._diff_visibility_changed)
+
+        view_menu_wide_diffs = gtk.CheckMenuItem("Wide Diffs")
+        view_menu_wide_diffs.set_active(False)
+        if self.config.get_user_option('viz-wide-diffs') == 'True':
+            view_menu_wide_diffs.set_active(True)
+        view_menu_wide_diffs.connect('toggled', self._diff_placement_changed)
+
         view_menu.add(view_menu_toolbar)
         view_menu.add(view_menu_compact)
+        view_menu.add(view_menu_diffs)
+        view_menu.add(view_menu_wide_diffs)
         view_menu.add(gtk.SeparatorMenuItem())
 
         self.mnu_show_revno_column = gtk.CheckMenuItem("Show Revision _Number Column")
@@ -275,6 +302,15 @@
         align = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
         align.set_padding(5, 0, 0, 0)
         align.add(self.treeview)
+        # user-configured size
+        size = self._load_size('viz-graph-size')
+        if size:
+            width, height = size
+            align.set_size_request(width, height)
+        else:
+            (width, height) = self.get_size()
+            align.set_size_request(width, int(height / 2.5))
+        align.connect('size-allocate', self._on_size_allocate, 'viz-graph-size')
         align.show()
 
         return align
@@ -302,15 +338,37 @@
 
     def construct_bottom(self):
         """Construct the bottom half of the window."""
+        if self.config.get_user_option('viz-wide-diffs') == 'True':
+            self.diff_paned = gtk.VPaned()
+        else:
+            self.diff_paned = gtk.HPaned()
+        (width, height) = self.get_size()
+        self.diff_paned.set_size_request(20, 20) # shrinkable
+
         from bzrlib.plugins.gtk.revisionview import RevisionView
         self.revisionview = RevisionView(branch=self.branch)
-        (width, height) = self.get_size()
-        self.revisionview.set_size_request(width, int(height / 2.5))
+        self.revisionview.set_size_request(width/3, int(height / 2.5))
+        # user-configured size
+        size = self._load_size('viz-revisionview-size')
+        if size:
+            width, height = size
+            self.revisionview.set_size_request(width, height)
+        self.revisionview.connect('size-allocate', self._on_size_allocate, 'viz-revisionview-size')
         self.revisionview.show()
         self.revisionview.set_show_callback(self._show_clicked_cb)
         self.revisionview.connect('notify::revision', self._go_clicked_cb)
         self.treeview.connect('tag-added', lambda w, t, r: self.revisionview.update_tags())
-        return self.revisionview
+        self.diff_paned.pack1(self.revisionview)
+
+        from bzrlib.plugins.gtk.diff import DiffWidget
+        self.diff = DiffWidget()
+        self.diff_paned.pack2(self.diff)
+
+        self.diff_paned.show_all()
+        if self.config.get_user_option('viz-show-diffs') != 'True':
+            self.diff.hide()
+
+        return self.diff_paned
 
     def _tag_selected_cb(self, menuitem, revid):
         self.treeview.set_revision_id(revid)
@@ -367,7 +425,9 @@
 
             self.revisionview.set_revision(revision)
             self.revisionview.set_children(children)
-    
+
+            self.update_diff_panel(revision, parents)
+
     def _tree_revision_activated(self, widget, path, col):
         # TODO: more than one parent
         """Callback for when a treeview row gets activated."""
@@ -439,9 +499,38 @@
 
     def _toolbar_visibility_changed(self, col):
         if col.get_active():
-            self.toolbar.show() 
+            self.toolbar.show()
         else:
             self.toolbar.hide()
+        self.config.set_user_option('viz-toolbar-visible', col.get_active())
+
+    def _make_diff_nonzero_size(self):
+        """make sure the diff isn't zero-width or zero-height"""
+        alloc = self.diff.get_allocation()
+        if (alloc.width < 10) or (alloc.height < 10):
+            width, height = self.get_size()
+            self.revisionview.set_size_request(width/3, int(height / 2.5))
+
+    def _diff_visibility_changed(self, col):
+        """Hide or show the diff panel."""
+        if col.get_active():
+            self.diff.show()
+            self._make_diff_nonzero_size()
+        else:
+            self.diff.hide()
+        self.config.set_user_option('viz-show-diffs', str(col.get_active()))
+        self.update_diff_panel()
+
+    def _diff_placement_changed(self, col):
+        """Toggle the diff panel's position."""
+        self.config.set_user_option('viz-wide-diffs', str(col.get_active()))
+
+        old = self.paned.get_child2()
+        self.paned.remove(old)
+        self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
+        self._make_diff_nonzero_size()
+
+        self.treeview.emit('revision-selected')
 
     def _show_about_cb(self, w):
         dialog = AboutDialog()
@@ -473,6 +562,34 @@
 
         self.go_menu_tags.show_all()
 
+    def _load_size(self, name):
+        """Read and parse 'name' from self.config.
+        The value is a string, formatted as WIDTHxHEIGHT
+        Returns None, or (width, height)
+        """
+        size = self.config.get_user_option(name)
+        if size:
+            width, height = [int(num) for num in size.split('x')]
+            # avoid writing config every time we start
+            self._sizes[name] = (width, height)
+            return width, height
+        return None
+
+    def _on_size_allocate(self, widget, allocation, name):
+        """When window has been resized, save the new size."""
+        width, height = 0, 0
+        if name in self._sizes:
+            width, height = self._sizes[name]
+
+        size_changed = (width != allocation.width) or \
+                (height != allocation.height)
+
+        if size_changed:
+            width, height = allocation.width, allocation.height
+            self._sizes[name] = (width, height)
+            value = '%sx%s' % (width, height)
+            self.config.set_user_option(name, value)
+
     def show_diff(self, revid=None, parentid=None):
         """Open a new window to show a diff between the given revisions."""
         from bzrlib.plugins.gtk.diff import DiffWindow
@@ -488,4 +605,25 @@
         window.set_diff(description, rev_tree, parent_tree)
         window.show()
 
-
+    def update_diff_panel(self, revision=None, parents=None):
+        """Show the current revision in the diff panel."""
+        if self.config.get_user_option('viz-show-diffs') != 'True':
+            return
+
+        if not revision: # default to selected row
+            revision = self.treeview.get_revision()
+        if (not revision) or (revision == NULL_REVISION):
+            return
+
+        if not parents: # default to selected row's parents
+            parents  = self.treeview.get_parents()
+        if len(parents) == 0:
+            parent_id = None
+        else:
+            parent_id = parents[0]
+
+        rev_tree    = self.branch.repository.revision_tree(revision.revision_id)
+        parent_tree = self.branch.repository.revision_tree(parent_id)
+
+        self.diff.set_diff(rev_tree, parent_tree)
+        self.diff.show_all()

# Begin bundle
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
aAZxO9c6EchchN/jmX+n/4u5IpwoSADQBw+A
-- 
bzr-gtk mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.canonical.com/mailman/listinfo/bzr-gtk

Reply via email to