The attached patch adds a simple loom browser. It's just a start
- the UI needs some more work, but better than nothing ;-)

Cheers,

Jelmer

-- 
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [EMAIL PROTECTED]
# target_branch: lp:bzr-gtk
# testament_sha1: ed77d0874baa212fff696792cae62b0b29ea89c4
# timestamp: 2008-07-31 03:11:55 +0200
# base_revision_id: [EMAIL PROTECTED]
# 
# Begin patch
=== modified file 'NEWS'
--- NEWS	2008-07-27 12:01:40 +0000
+++ NEWS	2008-07-31 01:11:43 +0000
@@ -25,6 +25,8 @@
   
   * Made merge dialog to give choice between folder and custom location (Jasper Groenewegen)
 
+  * Ad new dialog to browse looms and switch to threads in loom branches. (Jelmer Vernooij)
+
  BUG FIXES
 
   * Replace _() calls by _i18n() calls. (Vincent Ladeuil, #187283)

=== modified file '__init__.py'
--- __init__.py	2008-07-25 22:29:51 +0000
+++ __init__.py	2008-07-31 01:09:01 +0000
@@ -22,6 +22,7 @@
 gconflicts        GTK+ conflicts. 
 gdiff             Show differences in working tree in a GTK+ Window. 
 ginit             Initialise a new branch.
+gloom             GTK+ loom browse dialog
 gmerge            GTK+ merge dialog
 gmissing          GTK+ missing revisions dialog. 
 gpreferences      GTK+ preferences dialog. 
@@ -172,11 +173,29 @@
     def run(self, location="."):
         (br, path) = branch.Branch.open_containing(location)
         open_display()
-        from push import PushDialog
+        from bzrlib.plugins.gtk.push import PushDialog
         dialog = PushDialog(br.repository, br.last_revision(), br)
         dialog.run()
 
 
+class cmd_gloom(GTKCommand):
+    """ GTK+ loom.
+    
+    """
+    takes_args = [ "location?" ]
+
+    def run(self, location="."):
+        try:
+            (tree, path) = workingtree.WorkingTree.open_containing(location)
+            br = tree.branch
+        except NoWorkingTree, e:
+            (br, path) = branch.Branch.open_containing(location)
+            tree = None
+        open_display()
+        from bzrlib.plugins.gtk.loom import LoomDialog
+        dialog = LoomDialog(br, tree)
+        dialog.run()
+
 
 class cmd_gdiff(GTKCommand):
     """Show differences in working tree in a GTK+ Window.
@@ -548,6 +567,9 @@
     cmd_visualise
     ]
 
+if getattr(bzrlib.plugins, "loom", None) is not None:
+    commands.append(cmd_gloom)
+
 for cmd in commands:
     register_command(cmd)
 

=== modified file 'commit.py'
--- commit.py	2008-07-27 07:59:23 +0000
+++ commit.py	2008-07-31 00:07:21 +0000
@@ -101,7 +101,7 @@
     """Implementation of Commit."""
 
     def __init__(self, wt, selected=None, parent=None):
-        gtk.Dialog.__init__(self, title="Commit - Olive",
+        gtk.Dialog.__init__(self, title="Commit",
                                   parent=parent,
                                   flags=0,
                                   buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))

=== added file 'loom.py'
--- loom.py	1970-01-01 00:00:00 +0000
+++ loom.py	2008-07-31 01:11:43 +0000
@@ -0,0 +1,122 @@
+# Copyright (C) 2008 Jelmer Vernooij <[EMAIL PROTECTED]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+try:
+    import pygtk
+    pygtk.require("2.0")
+except:
+    pass
+
+import gtk
+import gobject
+
+from bzrlib.plugins.gtk import _i18n
+from bzrlib.plugins.gtk.diff import DiffWidget
+from bzrlib.plugins.gtk.dialog import question_dialog
+from bzrlib.plugins.loom import branch as loom_branch
+from bzrlib.plugins.loom import tree as loom_tree
+
+class LoomDialog(gtk.Dialog):
+    """Simple Loom browse dialog."""
+
+    def __init__(self, branch, tree=None, parent=None):
+        gtk.Dialog.__init__(self, title="Threads",
+                                  parent=parent,
+                                  flags=0,
+                                  buttons=(gtk.STOCK_CLOSE,gtk.RESPONSE_OK))
+        self.branch = branch
+        if tree is not None:
+            self.tree = loom_tree.LoomTreeDecorator(tree)
+        else:
+            self.tree = None
+
+        self._construct()
+        self._load_threads()
+
+    def run(self):
+        try:
+            loom_branch.require_loom_branch(self.branch)
+        except loom_branch.NotALoom:
+            response = question_dialog(
+                _i18n("Upgrade to Loom branch?"),
+                _i18n("Branch is not a loom branch. Upgrade to Loom format?"),
+                parent=self)
+                # Doesn't set a parent for the dialog..
+            if response == gtk.RESPONSE_NO:
+                return
+            assert self.branch.nick is not None
+            loom_branch.loomify(self.branch)
+        return super(LoomDialog, self).run()
+
+    def _construct(self):
+        hbox = gtk.HBox()
+
+        self._threads_scroller = gtk.ScrolledWindow()
+        self._threads_scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        self._threads_view = gtk.TreeView()
+        self._threads_scroller.add(self._threads_view)
+        self._threads_scroller.set_shadow_type(gtk.SHADOW_IN)
+        hbox.pack_start(self._threads_scroller)
+
+        self._threads_store = gtk.ListStore(
+                gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_STRING)
+        self._threads_view.set_model(self._threads_store)
+        self._threads_view.append_column(gtk.TreeViewColumn("Name", gtk.CellRendererText(), text=0))
+        self._threads_view.connect('cursor-changed', self._on_view_thread)
+        if self.tree is not None:
+            self._threads_view.connect('row-activated', self._on_switch_thread)
+
+        self._diff = DiffWidget()
+        self._diff.show()
+        hbox.pack_end(self._diff)
+
+        hbox.show_all()
+        self.vbox.pack_start(hbox)
+
+        # FIXME: Buttons: combine-thread, revert-loom, record
+        self.set_default_size(500, 350)
+
+    def _on_view_thread(self, treeview):
+        treeselection = treeview.get_selection()
+        (model, selection) = treeselection.get_selected()
+        if selection is None:
+            return
+        revid, parent_revid = model.get(selection, 1, 3)
+        if parent_revid is None:
+            return
+        self.branch.lock_read()
+        try:
+            (rev_tree, parent_tree) = tuple(self.branch.repository.revision_trees([revid, parent_revid]))
+            self._diff.set_diff(rev_tree, parent_tree)
+        finally:
+            self.branch.unlock()
+
+    def _on_switch_thread(self, treeview, path, view_column):
+        new_thread = self._threads_store.get_value(self._threads_store.get_iter(path), 0)
+        self.tree.down_thread(new_thread)
+
+    def _load_threads(self):
+        self._threads_store.clear()
+        
+        self.branch.lock_read()
+        try:
+            threads = self.branch.get_loom_state().get_threads()
+            last_revid = None
+            for name, revid, parent_ids in reversed(threads):
+                self._threads_store.append([name, revid, parent_ids, last_revid])
+                last_revid = revid
+        finally:
+            self.branch.unlock()

# Begin bundle
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
X2xJm08kjS+KGY//F3JFOFCQTAndzQ==
-- 
bzr-gtk mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.canonical.com/mailman/listinfo/bzr-gtk

Reply via email to