/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to viz/treeview.py

  • Committer: Jelmer Vernooij
  • Date: 2007-12-21 20:20:37 UTC
  • mto: This revision was merged to the branch mainline in revision 422.
  • Revision ID: jelmer@samba.org-20071221202037-6zvbwefvrte3e2zy
Fix URL.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 
4
4
"""
5
5
 
6
 
__copyright__ = "Copyright © 2005 Canonical Ltd."
 
6
__copyright__ = "Copyright � 2005 Canonical Ltd."
7
7
__author__    = "Daniel Schierbeck <daniel.schierbeck@gmail.com>"
8
8
 
9
 
from gi.repository import Gtk
10
 
from gi.repository import GObject
11
 
from gi.repository import Pango
 
9
import sys
 
10
import string
 
11
import gtk
 
12
import gobject
 
13
import pango
 
14
import re
 
15
import treemodel
12
16
 
13
 
from bzrlib import ui
 
17
from linegraph import linegraph, same_branch
 
18
from graphcell import CellRendererGraph
 
19
from treemodel import TreeModel
14
20
from bzrlib.revision import NULL_REVISION
15
21
 
16
 
from bzrlib.plugins.gtk import lock
17
 
from bzrlib.plugins.gtk.ui import ProgressPanel
18
 
from bzrlib.plugins.gtk.branchview import treemodel
19
 
from bzrlib.plugins.gtk.branchview.linegraph import linegraph, same_branch
20
 
from bzrlib.plugins.gtk.branchview.graphcell import CellRendererGraph
21
 
 
22
 
 
23
 
class TreeView(Gtk.VBox):
 
22
class TreeView(gtk.ScrolledWindow):
24
23
 
25
24
    __gproperties__ = {
26
 
        'branch': (GObject.TYPE_PYOBJECT,
 
25
        'branch': (gobject.TYPE_PYOBJECT,
27
26
                   'Branch',
28
27
                   'The Bazaar branch being visualized',
29
 
                   GObject.PARAM_CONSTRUCT_ONLY | GObject.PARAM_WRITABLE),
 
28
                   gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE),
30
29
 
31
 
        'revision': (GObject.TYPE_PYOBJECT,
 
30
        'revision': (gobject.TYPE_PYOBJECT,
32
31
                     'Revision',
33
32
                     'The currently selected revision',
34
 
                     GObject.PARAM_READWRITE),
 
33
                     gobject.PARAM_READWRITE),
35
34
 
36
 
        'revision-number': (GObject.TYPE_STRING,
 
35
        'revision-number': (gobject.TYPE_STRING,
37
36
                            'Revision number',
38
37
                            'The number of the selected revision',
39
38
                            '',
40
 
                            GObject.PARAM_READABLE),
 
39
                            gobject.PARAM_READABLE),
41
40
 
42
 
        'children': (GObject.TYPE_PYOBJECT,
 
41
        'children': (gobject.TYPE_PYOBJECT,
43
42
                     'Child revisions',
44
43
                     'Children of the currently selected revision',
45
 
                     GObject.PARAM_READABLE),
 
44
                     gobject.PARAM_READABLE),
46
45
 
47
 
        'parents': (GObject.TYPE_PYOBJECT,
 
46
        'parents': (gobject.TYPE_PYOBJECT,
48
47
                    'Parent revisions',
49
48
                    'Parents to the currently selected revision',
50
 
                    GObject.PARAM_READABLE),
 
49
                    gobject.PARAM_READABLE),
51
50
 
52
 
        'revno-column-visible': (GObject.TYPE_BOOLEAN,
53
 
                                 'Revision number column',
 
51
        'revno-column-visible': (gobject.TYPE_BOOLEAN,
 
52
                                 'Revision number',
54
53
                                 'Show revision number column',
55
54
                                 True,
56
 
                                 GObject.PARAM_READWRITE),
57
 
 
58
 
        'graph-column-visible': (GObject.TYPE_BOOLEAN,
59
 
                                 'Graph column',
60
 
                                 'Show graph column',
61
 
                                 True,
62
 
                                 GObject.PARAM_READWRITE),
63
 
 
64
 
        'date-column-visible': (GObject.TYPE_BOOLEAN,
 
55
                                 gobject.PARAM_READWRITE),
 
56
 
 
57
        'date-column-visible': (gobject.TYPE_BOOLEAN,
65
58
                                 'Date',
66
59
                                 'Show date column',
67
60
                                 False,
68
 
                                 GObject.PARAM_READWRITE),
 
61
                                 gobject.PARAM_READWRITE),
69
62
 
70
 
        'compact': (GObject.TYPE_BOOLEAN,
 
63
        'compact': (gobject.TYPE_BOOLEAN,
71
64
                    'Compact view',
72
65
                    'Break ancestry lines to save space',
73
66
                    True,
74
 
                    GObject.PARAM_CONSTRUCT | GObject.PARAM_READWRITE),
75
 
 
76
 
        'mainline-only': (GObject.TYPE_BOOLEAN,
77
 
                    'Mainline only',
78
 
                    'Only show the mainline history.',
79
 
                    False,
80
 
                    GObject.PARAM_CONSTRUCT | GObject.PARAM_READWRITE),
 
67
                    gobject.PARAM_CONSTRUCT | gobject.PARAM_READWRITE)
81
68
 
82
69
    }
83
70
 
84
71
    __gsignals__ = {
85
 
        'revision-selected': (GObject.SignalFlags.RUN_FIRST,
86
 
                              None,
87
 
                              ()),
88
 
        'revision-activated': (GObject.SignalFlags.RUN_FIRST,
89
 
                              None,
90
 
                              (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT)),
91
 
        'tag-added': (GObject.SignalFlags.RUN_FIRST,
92
 
                              None,
93
 
                              (GObject.TYPE_STRING, GObject.TYPE_STRING)),
94
 
        'refreshed': (GObject.SignalFlags.RUN_FIRST, None,
 
72
        'revisions-loaded': (gobject.SIGNAL_RUN_FIRST, 
 
73
                             gobject.TYPE_NONE,
 
74
                             ()),
 
75
        'revision-selected': (gobject.SIGNAL_RUN_FIRST,
 
76
                              gobject.TYPE_NONE,
95
77
                              ())
96
78
    }
97
79
 
105
87
        :param broken_line_length: After how much lines to break 
106
88
                                   branches.
107
89
        """
108
 
        Gtk.VBox.__init__(self, homogeneous=False, spacing=0)
109
 
 
110
 
        self.progress_widget = ProgressPanel()
111
 
        self.pack_start(self.progress_widget, False, True, 0)
112
 
        if getattr(ui.ui_factory, "set_progress_bar_widget", None) is not None:
113
 
            # We'are using our own ui, let's tell it to use our widget.
114
 
            ui.ui_factory.set_progress_bar_widget(self.progress_widget)
115
 
 
116
 
        self.scrolled_window = Gtk.ScrolledWindow()
117
 
        self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
118
 
                                        Gtk.PolicyType.AUTOMATIC)
119
 
        self.scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
120
 
        self.scrolled_window.show()
121
 
        self.pack_start(self.scrolled_window, True, True, 0)
122
 
 
123
 
        self.scrolled_window.add(self.construct_treeview())
124
 
 
125
 
        self.path = None
 
90
        gtk.ScrolledWindow.__init__(self)
 
91
 
 
92
        self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
 
93
        self.set_shadow_type(gtk.SHADOW_IN)
 
94
 
 
95
        self.construct_treeview()
 
96
 
 
97
        self.iter   = None
126
98
        self.branch = branch
127
 
        self.revision = None
128
 
        self.index = {}
129
99
 
130
100
        self.start = start
131
101
        self.maxnum = maxnum
132
102
        self.compact = compact
133
103
 
134
 
        self.model = treemodel.TreeModel(self.branch, [])
135
 
        GObject.idle_add(self.populate)
136
 
 
137
 
        self.connect("destroy", self._on_destroy)
138
 
 
139
 
    def _on_destroy(self, *ignored):
140
 
        self.branch.unlock()
141
 
        if getattr(ui.ui_factory, "set_progress_bar_widget", None) is not None:
142
 
            # We'are using our own ui, let's tell it to stop using our widget.
143
 
            ui.ui_factory.set_progress_bar_widget(None)
 
104
        gobject.idle_add(self.populate)
 
105
 
 
106
        self.connect("destroy", lambda x: self.branch.unlock())
144
107
 
145
108
    def do_get_property(self, property):
146
109
        if property.name == 'revno-column-visible':
147
110
            return self.revno_column.get_visible()
148
 
        elif property.name == 'graph-column-visible':
149
 
            return self.graph_column.get_visible()
150
111
        elif property.name == 'date-column-visible':
151
112
            return self.date_column.get_visible()
152
113
        elif property.name == 'compact':
153
114
            return self.compact
154
 
        elif property.name == 'mainline-only':
155
 
            return self.mainline_only
156
115
        elif property.name == 'branch':
157
116
            return self.branch
158
117
        elif property.name == 'revision':
159
 
            if self.path is None:
160
 
                return None
161
 
            return self.model.get_value(self.model.get_iter(self.path),
162
 
                                        treemodel.REVISION)
 
118
            return self.model.get_value(self.iter, treemodel.REVISION)
163
119
        elif property.name == 'revision-number':
164
 
            if self.path is None:
165
 
                return None
166
 
            return self.model.get_value(self.model.get_iter(self.path),
167
 
                                        treemodel.REVNO)
 
120
            return self.model.get_value(self.iter, treemodel.REVNO)
168
121
        elif property.name == 'children':
169
 
            if self.path is None:
170
 
                return None
171
 
            return self.model.get_value(self.model.get_iter(self.path),
172
 
                                        treemodel.CHILDREN)
 
122
            return self.model.get_value(self.iter, treemodel.CHILDREN)
173
123
        elif property.name == 'parents':
174
 
            if self.path is None:
175
 
                return None
176
 
            return self.model.get_value(self.model.get_iter(self.path),
177
 
                                        treemodel.PARENTS)
 
124
            return self.model.get_value(self.iter, treemodel.PARENTS)
178
125
        else:
179
126
            raise AttributeError, 'unknown property %s' % property.name
180
127
 
181
128
    def do_set_property(self, property, value):
182
129
        if property.name == 'revno-column-visible':
183
130
            self.revno_column.set_visible(value)
184
 
        elif property.name == 'graph-column-visible':
185
 
            self.graph_column.set_visible(value)
186
131
        elif property.name == 'date-column-visible':
187
132
            self.date_column.set_visible(value)
188
133
        elif property.name == 'compact':
189
134
            self.compact = value
190
 
        elif property.name == 'mainline-only':
191
 
            self.mainline_only = value
192
135
        elif property.name == 'branch':
193
136
            self.branch = value
194
137
        elif property.name == 'revision':
200
143
        """Return revision id of currently selected revision, or None."""
201
144
        return self.get_property('revision')
202
145
 
203
 
    def has_revision_id(self, revision_id):
204
 
        return (revision_id in self.index)
205
 
 
206
146
    def set_revision(self, revision):
207
147
        self.set_property('revision', revision)
208
148
 
211
151
 
212
152
        :param revid: Revision id of revision to display.
213
153
        """
214
 
        self.treeview.set_cursor(
215
 
            Gtk.TreePath(path=self.index[revid]), None, False)
 
154
        self.treeview.set_cursor(self.index[revid])
216
155
        self.treeview.grab_focus()
217
156
 
218
157
    def get_children(self):
228
167
        :return: list of revision ids.
229
168
        """
230
169
        return self.get_property('parents')
231
 
 
232
 
    def add_tag(self, tag, revid=None):
233
 
        if revid is None: revid = self.revision.revision_id
234
 
 
235
 
        if lock.release(self.branch):
236
 
            try:
237
 
                lock.acquire(self.branch, lock.WRITE)
238
 
                self.model.add_tag(tag, revid)
239
 
            finally:
240
 
                lock.release(self.branch)
241
 
 
242
 
            lock.acquire(self.branch, lock.READ)
243
 
 
244
 
            self.emit('tag-added', tag, revid)
245
 
 
 
170
        
246
171
    def refresh(self):
247
 
        GObject.idle_add(self.populate, self.get_revision())
 
172
        gobject.idle_add(self.populate, self.get_revision())
248
173
 
249
174
    def update(self):
250
175
        try:
297
222
                       should be broken.
298
223
        """
299
224
 
300
 
        if getattr(ui.ui_factory, "set_progress_bar_widget", None) is not None:
301
 
            # We'are using our own ui, let's tell it to use our widget.
302
 
            ui.ui_factory.set_progress_bar_widget(self.progress_widget)
303
 
        self.progress_bar = ui.ui_factory.nested_progress_bar()
304
 
        self.progress_bar.update("Loading ancestry graph", 0, 5)
305
 
 
306
 
        try:
307
 
            if self.compact:
308
 
                broken_line_length = 32
309
 
            else:
310
 
                broken_line_length = None
311
 
 
312
 
            show_graph = self.graph_column.get_visible()
313
 
 
314
 
            self.branch.lock_read()
315
 
            (linegraphdata, index, columns_len) = linegraph(self.branch.repository.get_graph(),
316
 
                                                            self.start,
317
 
                                                            self.maxnum, 
318
 
                                                            broken_line_length,
319
 
                                                            show_graph,
320
 
                                                            self.mainline_only,
321
 
                                                            self.progress_bar)
322
 
 
323
 
            self.model.line_graph_data = linegraphdata
324
 
            self.graph_cell.columns_len = columns_len
325
 
            width = self.graph_cell.get_preferred_width(self.treeview)[1]
326
 
            if width > 500:
327
 
                width = 500
328
 
            self.graph_column.set_fixed_width(width)
329
 
            self.graph_column.set_max_width(width)
330
 
            self.index = index
331
 
            self.treeview.set_model(self.model)
332
 
 
333
 
            if not revision or revision == NULL_REVISION:
334
 
                self.treeview.set_cursor(Gtk.TreePath(path=0), None, False)
335
 
            else:
336
 
                self.set_revision(revision)
337
 
 
338
 
            self.emit('refreshed')
339
 
            return False
340
 
        finally:
341
 
            self.progress_bar.finished()
 
225
        if self.compact:
 
226
            broken_line_length = 32
 
227
        else:
 
228
            broken_line_length = None
 
229
 
 
230
        self.branch.lock_read()
 
231
        (linegraphdata, index, columns_len) = linegraph(self.branch.repository,
 
232
                                                        self.start,
 
233
                                                        self.maxnum, 
 
234
                                                        broken_line_length)
 
235
 
 
236
        self.model = TreeModel(self.branch.repository, linegraphdata)
 
237
        self.graph_cell.columns_len = columns_len
 
238
        width = self.graph_cell.get_size(self.treeview)[2]
 
239
        if width > 500:
 
240
            width = 500
 
241
        self.graph_column.set_fixed_width(width)
 
242
        self.graph_column.set_max_width(width)
 
243
        self.index = index
 
244
        self.treeview.set_model(self.model)
 
245
 
 
246
        if revision is None:
 
247
            self.treeview.set_cursor(0)
 
248
        else:
 
249
            self.set_revision(revision)
 
250
 
 
251
        self.emit('revisions-loaded')
 
252
 
 
253
        return False
 
254
 
 
255
    def show_diff(self, revid=None, parentid=None):
 
256
        """Open a new window to show a diff between the given revisions."""
 
257
        from bzrlib.plugins.gtk.diff import DiffWindow
 
258
        window = DiffWindow(parent=self)
 
259
 
 
260
        parents = self.get_parents()
 
261
 
 
262
        if revid is None:
 
263
            revid = self.get_revision().revision_id
 
264
 
 
265
            if parentid is None and len(parents) > 0:
 
266
                parentid = parents[0]
 
267
 
 
268
        if parentid is None:
 
269
            parentid = NULL_REVISION
 
270
 
 
271
        rev_tree    = self.branch.repository.revision_tree(revid)
 
272
        parent_tree = self.branch.repository.revision_tree(parentid)
 
273
 
 
274
        description = revid + " - " + self.branch.nick
 
275
        window.set_diff(description, rev_tree, parent_tree)
 
276
        window.show()
342
277
 
343
278
    def construct_treeview(self):
344
 
        self.treeview = Gtk.TreeView()
 
279
        self.treeview = gtk.TreeView()
345
280
 
346
281
        self.treeview.set_rules_hint(True)
347
 
        # combined revno/summary interactive search
348
 
        #
349
 
        # the row in a treemodel is considered "matched" if a REVNO *starts*
350
 
        # from the key (that is the key is found in a REVNO at the offset 0)
351
 
        # or if a MESSAGE *contains* the key anywhere (that is, the key is
352
 
        # found case insensitively in a MESSAGE at any offset)
353
 
        def search_equal_func(model, column, key, iter):
354
 
            return (model.get_value(iter, treemodel.REVNO).find(key) != 0
355
 
                and model.get_value(iter, treemodel.MESSAGE).lower().find(key.lower()) == -1)
356
 
 
357
 
        self.treeview.set_search_equal_func(search_equal_func, None)
358
 
        self.treeview.set_enable_search(True)
359
 
 
360
 
        self.treeview.set_tooltip_column(treemodel.MESSAGE)
361
 
 
362
 
        self._prev_cursor_path = None
 
282
        self.treeview.set_search_column(treemodel.REVNO)
 
283
        
 
284
        # Fix old PyGTK bug - by JAM
 
285
        set_tooltip = getattr(self.treeview, 'set_tooltip_column', None)
 
286
        if set_tooltip is not None:
 
287
            set_tooltip(treemodel.MESSAGE)
 
288
 
363
289
        self.treeview.connect("cursor-changed",
364
290
                self._on_selection_changed)
365
291
 
371
297
 
372
298
        self.treeview.set_property('fixed-height-mode', True)
373
299
 
 
300
        self.add(self.treeview)
374
301
        self.treeview.show()
375
302
 
376
 
        cell = Gtk.CellRendererText()
 
303
        cell = gtk.CellRendererText()
377
304
        cell.set_property("width-chars", 15)
378
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
379
 
        self.revno_column = Gtk.TreeViewColumn("Revision No")
 
305
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
306
        self.revno_column = gtk.TreeViewColumn("Revision No")
380
307
        self.revno_column.set_resizable(True)
381
 
        self.revno_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
382
 
        self.revno_column.set_fixed_width(
383
 
            cell.get_preferred_width(self.treeview)[1])
384
 
        self.revno_column.pack_start(cell, True)
 
308
        self.revno_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
309
        self.revno_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
310
        self.revno_column.pack_start(cell, expand=True)
385
311
        self.revno_column.add_attribute(cell, "text", treemodel.REVNO)
386
312
        self.treeview.append_column(self.revno_column)
387
313
 
388
314
        self.graph_cell = CellRendererGraph()
389
 
        self.graph_column = Gtk.TreeViewColumn()
 
315
        self.graph_column = gtk.TreeViewColumn()
390
316
        self.graph_column.set_resizable(True)
391
 
        self.graph_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
392
 
        self.graph_column.pack_start(self.graph_cell, True)
 
317
        self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
318
        self.graph_column.pack_start(self.graph_cell, expand=False)
393
319
        self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
394
 
        self.graph_column.add_attribute(self.graph_cell, "tags", treemodel.TAGS)
395
320
        self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
396
321
        self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
397
322
        self.treeview.append_column(self.graph_column)
398
323
 
399
 
        cell = Gtk.CellRendererText()
 
324
        cell = gtk.CellRendererText()
400
325
        cell.set_property("width-chars", 65)
401
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
402
 
        self.summary_column = Gtk.TreeViewColumn("Summary")
403
 
        self.summary_column.set_resizable(True)
404
 
        self.summary_column.set_expand(True)
405
 
        self.summary_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
406
 
        self.summary_column.set_fixed_width(
407
 
            cell.get_preferred_width(self.treeview)[1])
408
 
        self.summary_column.pack_start(cell, True)
409
 
        self.summary_column.add_attribute(cell, "markup", treemodel.SUMMARY)
410
 
        self.treeview.append_column(self.summary_column)
 
326
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
327
        self.msg_column = gtk.TreeViewColumn("Message")
 
328
        self.msg_column.set_resizable(True)
 
329
        self.msg_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
330
        self.msg_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
331
        self.msg_column.pack_start(cell, expand=True)
 
332
        self.msg_column.add_attribute(cell, "text", treemodel.MESSAGE)
 
333
        self.treeview.append_column(self.msg_column)
411
334
 
412
 
        cell = Gtk.CellRendererText()
 
335
        cell = gtk.CellRendererText()
413
336
        cell.set_property("width-chars", 15)
414
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
415
 
        self.authors_column = Gtk.TreeViewColumn("Author(s)")
416
 
        self.authors_column.set_resizable(False)
417
 
        self.authors_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
418
 
        self.authors_column.set_fixed_width(200)
419
 
        self.authors_column.pack_start(cell, True)
420
 
        self.authors_column.add_attribute(cell, "text", treemodel.AUTHORS)
421
 
        self.treeview.append_column(self.authors_column)
 
337
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
338
        self.committer_column = gtk.TreeViewColumn("Committer")
 
339
        self.committer_column.set_resizable(True)
 
340
        self.committer_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
341
        self.committer_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
342
        self.committer_column.pack_start(cell, expand=True)
 
343
        self.committer_column.add_attribute(cell, "text", treemodel.COMMITER)
 
344
        self.treeview.append_column(self.committer_column)
422
345
 
423
 
        cell = Gtk.CellRendererText()
 
346
        cell = gtk.CellRendererText()
424
347
        cell.set_property("width-chars", 20)
425
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
426
 
        self.date_column = Gtk.TreeViewColumn("Date")
 
348
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
349
        self.date_column = gtk.TreeViewColumn("Date")
427
350
        self.date_column.set_visible(False)
428
351
        self.date_column.set_resizable(True)
429
 
        self.date_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
430
 
        self.date_column.set_fixed_width(130)
431
 
        self.date_column.pack_start(cell, True)
 
352
        self.date_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
353
        self.date_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
354
        self.date_column.pack_start(cell, expand=True)
432
355
        self.date_column.add_attribute(cell, "text", treemodel.TIMESTAMP)
433
356
        self.treeview.append_column(self.date_column)
434
357
 
435
 
        return self.treeview
436
 
 
437
358
    def _on_selection_changed(self, treeview):
438
359
        """callback for when the treeview changes."""
439
360
        (path, focus) = treeview.get_cursor()
440
 
        if (path is not None) and (path != self._prev_cursor_path):
441
 
            self._prev_cursor_path = path # avoid emitting twice per click
442
 
            self.path = path
 
361
        if path is not None:
 
362
            self.iter = self.model.get_iter(path)
443
363
            self.emit('revision-selected')
444
364
 
445
365
    def _on_revision_selected(self, widget, event):
446
 
        from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
 
366
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
447
367
        if event.button == 3:
448
 
            menu = RevisionMenu(self.branch.repository, 
 
368
            menu = RevisionPopupMenu(self.branch.repository, 
449
369
                [self.get_revision().revision_id],
450
370
                self.branch)
451
 
            menu.connect('tag-added', lambda w, t, r: self.add_tag(t, r))
452
371
            menu.popup(None, None, None, event.button, event.get_time())
453
372
 
454
373
    def _on_revision_activated(self, widget, path, col):
455
 
        self.emit('revision-activated', path, col)
 
374
        # TODO: more than one parent
 
375
        """Callback for when a treeview row gets activated."""
 
376
        revision_id = self.model[path][treemodel.REVID]
 
377
        parents = self.model[path][treemodel.PARENTS]
 
378
 
 
379
        if len(parents) == 0:
 
380
            parent_id = None
 
381
        else:
 
382
            parent_id = parents[0]
 
383
 
 
384
        self.show_diff(revision_id, parent_id)
 
385
        self.treeview.grab_focus()