/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
1 by Scott James Remnant
Commit the first version of bzrk.
1
# -*- coding: UTF-8 -*-
2
"""Branch window.
3
4
This module contains the code to manage the branch information window,
5
which contains both the revision graph and details panes.
6
"""
7
8
__copyright__ = "Copyright © 2005 Canonical Ltd."
9
__author__    = "Scott James Remnant <scott@ubuntu.com>"
10
11
12
import gtk
13
import gobject
14
import pango
256.2.29 by Gary van der Merwe
Implement a TreeModel that loads revisions incrementaly.
15
import treemodel
1 by Scott James Remnant
Commit the first version of bzrk.
16
17
from bzrlib.osutils import format_date
18
256.2.5 by Gary van der Merwe
Oops - Renamed file without changeing import lines
19
from linegraph import linegraph, same_branch
1 by Scott James Remnant
Commit the first version of bzrk.
20
from graphcell import CellRendererGraph
256.2.29 by Gary van der Merwe
Implement a TreeModel that loads revisions incrementaly.
21
from treemodel import TreeModel
1 by Scott James Remnant
Commit the first version of bzrk.
22
23
24
class BranchWindow(gtk.Window):
25
    """Branch window.
26
27
    This object represents and manages a single window containing information
28
    for a particular branch.
29
    """
30
275.1.6 by Daniel Schierbeck
Made Ctrl-W call gtk.main_quit if the window has no parent.
31
    def __init__(self, parent=None):
1 by Scott James Remnant
Commit the first version of bzrk.
32
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
33
        self.set_border_width(0)
34
        self.set_title("bzrk")
35
275.1.6 by Daniel Schierbeck
Made Ctrl-W call gtk.main_quit if the window has no parent.
36
        self._parent = parent
37
38
        self.connect('key-press-event', self._on_key_pressed)
275.1.1 by Daniel Schierbeck
Close branch visualization window when 'destroy' message is received.
39
1 by Scott James Remnant
Commit the first version of bzrk.
40
        # Use three-quarters of the screen by default
41
        screen = self.get_screen()
4 by Scott James Remnant
Use the size of the first monitor rather than the entire screen
42
        monitor = screen.get_monitor_geometry(0)
43
        width = int(monitor.width * 0.75)
44
        height = int(monitor.height * 0.75)
1 by Scott James Remnant
Commit the first version of bzrk.
45
        self.set_default_size(width, height)
46
47
        # FIXME AndyFitz!
48
        icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
49
        self.set_icon(icon)
50
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
51
        self.accel_group = gtk.AccelGroup()
52
        self.add_accel_group(self.accel_group)
53
1 by Scott James Remnant
Commit the first version of bzrk.
54
        self.construct()
55
56
    def construct(self):
57
        """Construct the window contents."""
44 by David Allouche
reorganise branch window
58
        vbox = gtk.VBox(spacing=0)
59
        self.add(vbox)
60
61
        vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
280.2.1 by Gary van der Merwe
Add a message to the viz window to indicate that graph is still loading.
62
        vbox.pack_start(self.construct_loading_msg(), expand=False, fill=True)
63
        
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
64
        paned = gtk.VPaned()
65
        paned.pack1(self.construct_top(), resize=True, shrink=False)
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
66
        paned.pack2(self.construct_bottom(), resize=False, shrink=True)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
67
        paned.show()
44 by David Allouche
reorganise branch window
68
        vbox.pack_start(paned, expand=True, fill=True)
69
        vbox.set_focus_child(paned)
70
71
        vbox.show()
280.2.1 by Gary van der Merwe
Add a message to the viz window to indicate that graph is still loading.
72
    
73
    def construct_loading_msg(self):
74
        image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
75
                                                 gtk.ICON_SIZE_BUTTON)
76
        image_loading.show()
77
        
78
        label_loading = gtk.Label(_("Please wait, loading ancestral graph..."))
79
        label_loading.set_alignment(0.0, 0.5)        
80
        label_loading.show()
81
        
82
        self.loading_msg_box = gtk.HBox()
83
        self.loading_msg_box.set_spacing(5)
84
        self.loading_msg_box.set_border_width(5)        
85
        self.loading_msg_box.pack_start(image_loading, False, False)
86
        self.loading_msg_box.pack_start(label_loading, True, True)
87
        self.loading_msg_box.show()
88
        
89
        return self.loading_msg_box
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
90
91
    def construct_top(self):
92
        """Construct the top-half of the window."""
1 by Scott James Remnant
Commit the first version of bzrk.
93
        scrollwin = gtk.ScrolledWindow()
94
        scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
95
        scrollwin.set_shadow_type(gtk.SHADOW_IN)
96
        scrollwin.show()
97
98
        self.treeview = gtk.TreeView()
99
        self.treeview.set_rules_hint(True)
100
        self.treeview.set_search_column(4)
280.1.2 by Daniel Schierbeck
Switched to handle the 'changed' signal from the treeview's treeselection instead of the 'cursor-changed' signal from the treeview itself, allowing more flexibility (particularly the ability to handle programmatic selections)
101
        self.treeview.get_selection().connect("changed", self._treeselection_changed_cb)
47 by Wouter van Heyst
rename _treeview_clicked_cb to correcter _treeview_row_activated_cb
102
        self.treeview.connect("row-activated", self._treeview_row_activated_cb)
226 by Jelmer Vernooij
Add context menu in bzrk.
103
        self.treeview.connect("button-release-event", 
104
                self._treeview_row_mouseclick)
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
105
        self.treeview.set_property('fixed-height-mode', True)
1 by Scott James Remnant
Commit the first version of bzrk.
106
        scrollwin.add(self.treeview)
107
        self.treeview.show()
108
256.2.27 by Gary van der Merwe
Show Revision No in tree
109
        cell = gtk.CellRendererText()
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
110
        cell.set_property("width-chars", 15)
256.4.1 by Gary van der Merwe
* Set a width and use ellips on Revision No column.
111
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
256.2.27 by Gary van der Merwe
Show Revision No in tree
112
        column = gtk.TreeViewColumn("Revision No")
113
        column.set_resizable(True)
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
114
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
115
        column.set_fixed_width(cell.get_size(self.treeview)[2])
256.2.27 by Gary van der Merwe
Show Revision No in tree
116
        column.pack_start(cell, expand=True)
256.2.29 by Gary van der Merwe
Implement a TreeModel that loads revisions incrementaly.
117
        column.add_attribute(cell, "text", treemodel.REVNO)
256.2.27 by Gary van der Merwe
Show Revision No in tree
118
        self.treeview.append_column(column)
119
256.4.1 by Gary van der Merwe
* Set a width and use ellips on Revision No column.
120
        self.graph_cell = CellRendererGraph()
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
121
        self.graph_column = gtk.TreeViewColumn()
122
        self.graph_column.set_resizable(True)
123
        self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
124
        self.graph_column.pack_start(self.graph_cell, expand=False)
125
        self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
126
        self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
127
        self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
128
        self.treeview.append_column(self.graph_column)
1 by Scott James Remnant
Commit the first version of bzrk.
129
130
        cell = gtk.CellRendererText()
131
        cell.set_property("width-chars", 40)
132
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
133
        column = gtk.TreeViewColumn("Message")
134
        column.set_resizable(True)
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
135
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
136
        column.set_fixed_width(cell.get_size(self.treeview)[2])
1 by Scott James Remnant
Commit the first version of bzrk.
137
        column.pack_start(cell, expand=True)
256.2.29 by Gary van der Merwe
Implement a TreeModel that loads revisions incrementaly.
138
        column.add_attribute(cell, "text", treemodel.MESSAGE)
1 by Scott James Remnant
Commit the first version of bzrk.
139
        self.treeview.append_column(column)
140
141
        cell = gtk.CellRendererText()
142
        cell.set_property("width-chars", 40)
143
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
144
        column = gtk.TreeViewColumn("Committer")
145
        column.set_resizable(True)
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
146
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
147
        column.set_fixed_width(cell.get_size(self.treeview)[2])
1 by Scott James Remnant
Commit the first version of bzrk.
148
        column.pack_start(cell, expand=True)
256.2.29 by Gary van der Merwe
Implement a TreeModel that loads revisions incrementaly.
149
        column.add_attribute(cell, "text", treemodel.COMMITER)
1 by Scott James Remnant
Commit the first version of bzrk.
150
        self.treeview.append_column(column)
151
152
        cell = gtk.CellRendererText()
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
153
        cell.set_property("width-chars", 40)
1 by Scott James Remnant
Commit the first version of bzrk.
154
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
155
        column = gtk.TreeViewColumn("Date")
156
        column.set_resizable(True)
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
157
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
158
        column.set_fixed_width(cell.get_size(self.treeview)[2])
1 by Scott James Remnant
Commit the first version of bzrk.
159
        column.pack_start(cell, expand=True)
256.2.29 by Gary van der Merwe
Implement a TreeModel that loads revisions incrementaly.
160
        column.add_attribute(cell, "text", treemodel.TIMESTAMP)
1 by Scott James Remnant
Commit the first version of bzrk.
161
        self.treeview.append_column(column)
162
44 by David Allouche
reorganise branch window
163
        return scrollwin
164
165
    def construct_navigation(self):
166
        """Construct the navigation buttons."""
167
        frame = gtk.Frame()
168
        frame.set_shadow_type(gtk.SHADOW_OUT)
169
        frame.show()
170
        
171
        hbox = gtk.HBox(spacing=12)
172
        frame.add(hbox)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
173
        hbox.show()
174
175
        self.back_button = gtk.Button(stock=gtk.STOCK_GO_BACK)
44 by David Allouche
reorganise branch window
176
        self.back_button.set_relief(gtk.RELIEF_NONE)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
177
        self.back_button.add_accelerator("clicked", self.accel_group, ord('['),
178
                                         0, 0)
179
        self.back_button.connect("clicked", self._back_clicked_cb)
180
        hbox.pack_start(self.back_button, expand=False, fill=True)
181
        self.back_button.show()
182
183
        self.fwd_button = gtk.Button(stock=gtk.STOCK_GO_FORWARD)
44 by David Allouche
reorganise branch window
184
        self.fwd_button.set_relief(gtk.RELIEF_NONE)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
185
        self.fwd_button.add_accelerator("clicked", self.accel_group, ord(']'),
186
                                        0, 0)
187
        self.fwd_button.connect("clicked", self._fwd_clicked_cb)
188
        hbox.pack_start(self.fwd_button, expand=False, fill=True)
189
        self.fwd_button.show()
190
44 by David Allouche
reorganise branch window
191
        return frame
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
192
193
    def construct_bottom(self):
194
        """Construct the bottom half of the window."""
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
195
        from bzrlib.plugins.gtk.logview import LogView
256.2.23 by Gary van der Merwe
Show Children
196
        self.logview = LogView(None, True, [], True)
44 by David Allouche
reorganise branch window
197
        (width, height) = self.get_size()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
198
        self.logview.set_size_request(width, int(height / 2.5))
199
        self.logview.show()
200
        self.logview.set_show_callback(self._show_clicked_cb)
201
        self.logview.set_go_callback(self._go_clicked_cb)
202
        return self.logview
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
203
40 by David Allouche
remove --robust, pyflakes fixes, update README
204
    def set_branch(self, branch, start, maxnum):
1 by Scott James Remnant
Commit the first version of bzrk.
205
        """Set the branch and start position for this window.
206
207
        Creates a new TreeModel and populates it with information about
208
        the new branch before updating the window title and model of the
209
        treeview itself.
210
        """
10 by Scott James Remnant
Add an extra window type, clicking the little icons next to a parent
211
        self.branch = branch
265.1.1 by Gary van der Merwe
Show bzr viz interface quickly.
212
        self.set_title(branch.nick + " - bzrk")
213
        gobject.idle_add(self.populate_model, start, maxnum)
214
215
    def populate_model(self, start, maxnum):
256.4.1 by Gary van der Merwe
* Set a width and use ellips on Revision No column.
216
        (linegraphdata, index, columns_len) = linegraph(self.branch,
217
                                                        start,
218
                                                        maxnum)
256.2.29 by Gary van der Merwe
Implement a TreeModel that loads revisions incrementaly.
219
        self.model = TreeModel(self.branch, linegraphdata)
256.4.1 by Gary van der Merwe
* Set a width and use ellips on Revision No column.
220
        self.graph_cell.columns_len = columns_len
256.4.4 by Gary van der Merwe
Use fixed-height-mode on treeview so that revisions data is only
221
        width = self.graph_cell.get_size(self.treeview)[2]
222
        self.graph_column.set_fixed_width(width)
223
        self.graph_column.set_max_width(width)
256.2.21 by Gary van der Merwe
Refactor so that line graph is more contained.
224
        self.index = index
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
225
        self.treeview.set_model(self.model)
280.1.1 by Daniel Schierbeck
Select the tip revision when opening the visualization window
226
        self.treeview.get_selection().select_path(0)
280.2.1 by Gary van der Merwe
Add a message to the viz window to indicate that graph is still loading.
227
        self.loading_msg_box.hide()
265.1.1 by Gary van der Merwe
Show bzr viz interface quickly.
228
        return False
229
    
275.1.5 by Daniel Schierbeck
Made windows close correctly on Ctrl-W and made the application quit on Ctrl-Q.
230
    def _on_key_pressed(self, widget, event):
231
        """ Key press event handler. """
232
        keyname = gtk.gdk.keyval_name(event.keyval)
233
        func = getattr(self, '_on_key_press_' + keyname, None)
234
        if func:
235
            return func(event)
236
237
    def _on_key_press_w(self, event):
238
        if event.state & gtk.gdk.CONTROL_MASK:
239
            self.destroy()
275.1.6 by Daniel Schierbeck
Made Ctrl-W call gtk.main_quit if the window has no parent.
240
            if self._parent is None:
241
                gtk.main_quit()
275.1.5 by Daniel Schierbeck
Made windows close correctly on Ctrl-W and made the application quit on Ctrl-Q.
242
243
    def _on_key_press_q(self, event):
244
        if event.state & gtk.gdk.CONTROL_MASK:
245
            gtk.main_quit()
265.1.1 by Gary van der Merwe
Show bzr viz interface quickly.
246
    
280.1.2 by Daniel Schierbeck
Switched to handle the 'changed' signal from the treeview's treeselection instead of the 'cursor-changed' signal from the treeview itself, allowing more flexibility (particularly the ability to handle programmatic selections)
247
    def _treeselection_changed_cb(self, selection, *args):
248
        """Callback for when the treeview changes."""
249
        (model, selected_rows) = selection.get_selected_rows()
250
        if len(selected_rows) > 0:
256.2.62 by Gary van der Merwe
Merge Trunk.
251
            iter = self.model.get_iter(selected_rows[0])
252
            revision = self.model.get_value(iter, treemodel.REVISION)
253
            parents = self.model.get_value(iter, treemodel.PARENTS)
254
            children = self.model.get_value(iter, treemodel.CHILDREN)
255
            
256
            self.back_button.set_sensitive(len(parents) > 0)
257
            self.fwd_button.set_sensitive(len(children) > 0)
280.1.2 by Daniel Schierbeck
Switched to handle the 'changed' signal from the treeview's treeselection instead of the 'cursor-changed' signal from the treeview itself, allowing more flexibility (particularly the ability to handle programmatic selections)
258
            tags = []
259
            if self.branch.supports_tags():
260
                tagdict = self.branch.tags.get_reverse_tag_dict()
261
                if tagdict.has_key(revision.revision_id):
262
                    tags = tagdict[revision.revision_id]
256.2.62 by Gary van der Merwe
Merge Trunk.
263
            self.logview.set_revision(revision, tags, children)
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
264
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
265
    def _back_clicked_cb(self, *args):
266
        """Callback for when the back button is clicked."""
267
        (path, col) = self.treeview.get_cursor()
268
        revision = self.model[path][0]
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
269
        parents = self.model[path][4]
270
        if not len(parents):
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
271
            return
272
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
273
        for parent_id in parents:
274
            parent = self.revisions[self.index[parent_id]]
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
275
            if same_branch(revision, parent):
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
276
                self.treeview.set_cursor(self.index[parent_id])
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
277
                break
278
        else:
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
279
            self.treeview.set_cursor(self.index[parents[0]])
13 by Scott James Remnant
Keep the focus on the treeview
280
        self.treeview.grab_focus()
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
281
5 by Scott James Remnant
Reverse the meaning of the Back and Forward buttons so Back actually
282
    def _fwd_clicked_cb(self, *args):
283
        """Callback for when the forward button is clicked."""
284
        (path, col) = self.treeview.get_cursor()
285
        revision = self.model[path][0]
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
286
        children = self.model[path][5]
287
        if not len(children):
5 by Scott James Remnant
Reverse the meaning of the Back and Forward buttons so Back actually
288
            return
289
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
290
        for child_id in children:
291
            child = self.revisions[self.index[child_id]]
5 by Scott James Remnant
Reverse the meaning of the Back and Forward buttons so Back actually
292
            if same_branch(child, revision):
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
293
                self.treeview.set_cursor(self.index[child_id])
5 by Scott James Remnant
Reverse the meaning of the Back and Forward buttons so Back actually
294
                break
295
        else:
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
296
            self.treeview.set_cursor(self.index[children[0]])
13 by Scott James Remnant
Keep the focus on the treeview
297
        self.treeview.grab_focus()
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
298
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
299
    def _go_clicked_cb(self, revid):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
300
        """Callback for when the go button for a parent is clicked."""
256.2.4 by Gary van der Merwe
First go at using bzrlib graph code
301
        self.treeview.set_cursor(self.index[revid])
13 by Scott James Remnant
Keep the focus on the treeview
302
        self.treeview.grab_focus()
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
303
152 by Jelmer Vernooij
Cleanup some more code.
304
    def show_diff(self, branch, revid, parentid):
305
        """Open a new window to show a diff between the given revisions."""
306
        from bzrlib.plugins.gtk.diff import DiffWindow
307
        window = DiffWindow()
226 by Jelmer Vernooij
Add context menu in bzrk.
308
        (parent_tree, rev_tree) = branch.repository.revision_trees([parentid, 
309
                                                                   revid])
152 by Jelmer Vernooij
Cleanup some more code.
310
        description = revid + " - " + branch.nick
311
        window.set_diff(description, rev_tree, parent_tree)
312
        window.show()
313
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
314
    def _show_clicked_cb(self, revid, parentid):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
315
        """Callback for when the show button for a parent is clicked."""
152 by Jelmer Vernooij
Cleanup some more code.
316
        self.show_diff(self.branch, revid, parentid)
13 by Scott James Remnant
Keep the focus on the treeview
317
        self.treeview.grab_focus()
46 by Wouter van Heyst
show diff on row activation, LP# 44591
318
226 by Jelmer Vernooij
Add context menu in bzrk.
319
    def _treeview_row_mouseclick(self, widget, event):
320
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
228 by Jelmer Vernooij
Remove unused code, prefer questions to check boxes.
321
        if event.button == 3:
322
            menu = RevisionPopupMenu(self.branch.repository, 
230 by Jelmer Vernooij
Initial work towards supporting multiple revisions.
323
                [x.revision_id for x in self.selected_revisions()],
324
                self.branch)
228 by Jelmer Vernooij
Remove unused code, prefer questions to check boxes.
325
            menu.popup(None, None, None, event.button, event.get_time())
226 by Jelmer Vernooij
Add context menu in bzrk.
326
327
    def selected_revision(self, path):
256.2.63 by Gary van der Merwe
Fix bug with revision menu.
328
        return self.model[path][treemodel.REVISION]
226 by Jelmer Vernooij
Add context menu in bzrk.
329
330
    def selected_revisions(self):
331
        return [self.selected_revision(path) for path in \
332
                self.treeview.get_selection().get_selected_rows()[1]]
333
47 by Wouter van Heyst
rename _treeview_clicked_cb to correcter _treeview_row_activated_cb
334
    def _treeview_row_activated_cb(self, widget, path, col):
46 by Wouter van Heyst
show diff on row activation, LP# 44591
335
        # TODO: more than one parent
47 by Wouter van Heyst
rename _treeview_clicked_cb to correcter _treeview_row_activated_cb
336
        """Callback for when a treeview row gets activated."""
289.1.1 by Gary van der Merwe
Fix vizchanges regression: Dbl click on a revision was not bringing up
337
        revision_id = self.model[path][treemodel.REVID]
338
        parents = self.model[path][treemodel.PARENTS]
339
        if len(parents) == 0:
74 by Jelmer Vernooij
Fix exception when double-clicking revision without parents.
340
            # Ignore revisions without parent
341
            return
289.1.1 by Gary van der Merwe
Fix vizchanges regression: Dbl click on a revision was not bringing up
342
        parent_id = parents[0]
343
        self.show_diff(self.branch, revision_id, parent_id)
46 by Wouter van Heyst
show diff on row activation, LP# 44591
344
        self.treeview.grab_focus()