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