/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 branchview/treeview.py

  • Committer: Daniel Schierbeck
  • Date: 2008-01-23 16:24:25 UTC
  • mfrom: (423.1.7 trunk)
  • mto: (423.1.8 trunk)
  • mto: This revision was merged to the branch mainline in revision 429.
  • Revision ID: daniel.schierbeck@gmail.com-20080123162425-qd1zpohg46qmxbuy
Merged with trunk.

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,
 
72
        'revisions-loaded': (gobject.SIGNAL_RUN_FIRST, 
 
73
                             gobject.TYPE_NONE,
 
74
                             ()),
 
75
        'revision-selected': (gobject.SIGNAL_RUN_FIRST,
 
76
                              gobject.TYPE_NONE,
87
77
                              ()),
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,
95
 
                              ())
 
78
        'tag-added': (gobject.SIGNAL_RUN_FIRST,
 
79
                              gobject.TYPE_NONE,
 
80
                              (gobject.TYPE_STRING, gobject.TYPE_STRING))
96
81
    }
97
82
 
98
83
    def __init__(self, branch, start, maxnum, compact=True):
105
90
        :param broken_line_length: After how much lines to break 
106
91
                                   branches.
107
92
        """
108
 
        super(TreeView, self).__init__(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
 
93
        gtk.ScrolledWindow.__init__(self)
 
94
 
 
95
        self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
 
96
        self.set_shadow_type(gtk.SHADOW_IN)
 
97
 
 
98
        self.construct_treeview()
 
99
 
 
100
        self.iter = None
126
101
        self.branch = branch
127
102
        self.revision = None
128
 
        self.index = {}
129
103
 
130
104
        self.start = start
131
105
        self.maxnum = maxnum
132
106
        self.compact = compact
133
107
 
134
 
        self.model = treemodel.BranchTreeModel(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)
 
108
        gobject.idle_add(self.populate)
 
109
 
 
110
        self.connect("destroy", lambda x: self.branch.unlock())
144
111
 
145
112
    def do_get_property(self, property):
146
113
        if property.name == 'revno-column-visible':
147
114
            return self.revno_column.get_visible()
148
 
        elif property.name == 'graph-column-visible':
149
 
            return self.graph_column.get_visible()
150
115
        elif property.name == 'date-column-visible':
151
116
            return self.date_column.get_visible()
152
117
        elif property.name == 'compact':
153
118
            return self.compact
154
 
        elif property.name == 'mainline-only':
155
 
            return self.mainline_only
156
119
        elif property.name == 'branch':
157
120
            return self.branch
158
121
        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)
 
122
            return self.model.get_value(self.iter, treemodel.REVISION)
163
123
        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)
 
124
            return self.model.get_value(self.iter, treemodel.REVNO)
168
125
        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)
 
126
            return self.model.get_value(self.iter, treemodel.CHILDREN)
173
127
        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)
 
128
            return self.model.get_value(self.iter, treemodel.PARENTS)
178
129
        else:
179
130
            raise AttributeError, 'unknown property %s' % property.name
180
131
 
181
132
    def do_set_property(self, property, value):
182
133
        if property.name == 'revno-column-visible':
183
134
            self.revno_column.set_visible(value)
184
 
        elif property.name == 'graph-column-visible':
185
 
            self.graph_column.set_visible(value)
186
135
        elif property.name == 'date-column-visible':
187
136
            self.date_column.set_visible(value)
188
137
        elif property.name == 'compact':
189
138
            self.compact = value
190
 
        elif property.name == 'mainline-only':
191
 
            self.mainline_only = value
192
139
        elif property.name == 'branch':
193
140
            self.branch = value
194
141
        elif property.name == 'revision':
200
147
        """Return revision id of currently selected revision, or None."""
201
148
        return self.get_property('revision')
202
149
 
203
 
    def has_revision_id(self, revision_id):
204
 
        return (revision_id in self.index)
205
 
 
206
150
    def set_revision(self, revision):
207
151
        self.set_property('revision', revision)
208
152
 
211
155
 
212
156
        :param revid: Revision id of revision to display.
213
157
        """
214
 
        self.treeview.set_cursor(
215
 
            Gtk.TreePath(path=self.index[revid]), None, False)
 
158
        self.treeview.set_cursor(self.index[revid])
216
159
        self.treeview.grab_focus()
217
160
 
218
161
    def get_children(self):
232
175
    def add_tag(self, tag, revid=None):
233
176
        if revid is None: revid = self.revision.revision_id
234
177
 
235
 
        if lock.release(self.branch):
 
178
        try:
 
179
            self.branch.unlock()
 
180
 
236
181
            try:
237
 
                lock.acquire(self.branch, lock.WRITE)
 
182
                self.branch.lock_write()
238
183
                self.model.add_tag(tag, revid)
239
184
            finally:
240
 
                lock.release(self.branch)
241
 
 
242
 
            lock.acquire(self.branch, lock.READ)
243
 
 
244
 
            self.emit('tag-added', tag, revid)
245
 
 
 
185
                self.branch.unlock()
 
186
 
 
187
        finally:
 
188
            self.branch.lock_read()
 
189
 
 
190
        self.emit('tag-added', tag, revid)
 
191
        
246
192
    def refresh(self):
247
 
        GObject.idle_add(self.populate, self.get_revision())
 
193
        gobject.idle_add(self.populate, self.get_revision())
248
194
 
249
195
    def update(self):
250
196
        try:
260
206
    def back(self):
261
207
        """Signal handler for the Back button."""
262
208
        parents = self.get_parents()
263
 
        if not parents:
 
209
        if not len(parents):
264
210
            return
265
211
 
266
212
        for parent_id in parents:
275
221
    def forward(self):
276
222
        """Signal handler for the Forward button."""
277
223
        children = self.get_children()
278
 
        if not children:
 
224
        if not len(children):
279
225
            return
280
226
 
281
227
        for child_id in children:
297
243
                       should be broken.
298
244
        """
299
245
 
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(
316
 
                self.branch.repository.get_graph(),
317
 
                self.start,
318
 
                self.maxnum, 
319
 
                broken_line_length,
320
 
                show_graph,
321
 
                self.mainline_only,
322
 
                self.progress_bar)
323
 
 
324
 
            self.model.set_line_graph_data(linegraphdata)
325
 
            self.graph_cell.columns_len = columns_len
326
 
            width = self.graph_cell.get_preferred_width(self.treeview)[1]
327
 
            if width > 500:
328
 
                width = 500
329
 
            elif width == 0:
330
 
                # The get_preferred_width() call got an insane value.
331
 
                width = 200
332
 
            self.graph_column.set_fixed_width(width)
333
 
            self.graph_column.set_max_width(width)
334
 
            self.index = index
335
 
            self.treeview.set_model(self.model)
336
 
 
337
 
            if not revision or revision == NULL_REVISION:
338
 
                self.treeview.set_cursor(Gtk.TreePath(path=0), None, False)
339
 
            else:
340
 
                self.set_revision(revision)
341
 
 
342
 
            self.emit('refreshed')
343
 
            return False
344
 
        finally:
345
 
            self.progress_bar.finished()
 
246
        if self.compact:
 
247
            broken_line_length = 32
 
248
        else:
 
249
            broken_line_length = None
 
250
 
 
251
        self.branch.lock_read()
 
252
        (linegraphdata, index, columns_len) = linegraph(self.branch.repository,
 
253
                                                        self.start,
 
254
                                                        self.maxnum, 
 
255
                                                        broken_line_length)
 
256
 
 
257
        self.model = TreeModel(self.branch, linegraphdata)
 
258
        self.graph_cell.columns_len = columns_len
 
259
        width = self.graph_cell.get_size(self.treeview)[2]
 
260
        if width > 500:
 
261
            width = 500
 
262
        self.graph_column.set_fixed_width(width)
 
263
        self.graph_column.set_max_width(width)
 
264
        self.index = index
 
265
        self.treeview.set_model(self.model)
 
266
 
 
267
        if revision is None:
 
268
            self.treeview.set_cursor(0)
 
269
        else:
 
270
            self.set_revision(revision)
 
271
 
 
272
        self.emit('revisions-loaded')
 
273
 
 
274
        return False
 
275
 
 
276
    def show_diff(self, revid=None, parentid=None):
 
277
        """Open a new window to show a diff between the given revisions."""
 
278
        from bzrlib.plugins.gtk.diff import DiffWindow
 
279
        window = DiffWindow(parent=self)
 
280
 
 
281
        parents = self.get_parents()
 
282
 
 
283
        if revid is None:
 
284
            revid = self.get_revision().revision_id
 
285
 
 
286
            if parentid is None and len(parents) > 0:
 
287
                parentid = parents[0]
 
288
 
 
289
        if parentid is None:
 
290
            parentid = NULL_REVISION
 
291
 
 
292
        rev_tree    = self.branch.repository.revision_tree(revid)
 
293
        parent_tree = self.branch.repository.revision_tree(parentid)
 
294
 
 
295
        description = revid + " - " + self.branch.nick
 
296
        window.set_diff(description, rev_tree, parent_tree)
 
297
        window.show()
346
298
 
347
299
    def construct_treeview(self):
348
 
        self.treeview = Gtk.TreeView()
 
300
        self.treeview = gtk.TreeView()
349
301
 
350
302
        self.treeview.set_rules_hint(True)
351
 
        # combined revno/summary interactive search
352
 
        #
353
 
        # the row in a treemodel is considered "matched" if a REVNO *starts*
354
 
        # from the key (that is the key is found in a REVNO at the offset 0)
355
 
        # or if a MESSAGE *contains* the key anywhere (that is, the key is
356
 
        # found case insensitively in a MESSAGE at any offset)
357
 
        def search_equal_func(model, column, key, iter, ignored):
358
 
            return (model.get_value(iter, treemodel.REVNO).find(key) != 0
359
 
                and model.get_value(iter, treemodel.MESSAGE).lower().find(key.lower()) == -1)
360
 
 
361
 
        self.treeview.set_search_equal_func(search_equal_func, None)
362
 
        self.treeview.set_enable_search(True)
363
 
 
364
 
        self.treeview.set_tooltip_column(treemodel.MESSAGE)
365
 
        self.treeview.set_headers_visible(True)
366
 
 
367
 
        self._prev_cursor_path = None
 
303
        self.treeview.set_search_column(treemodel.REVNO)
 
304
        
 
305
        # Fix old PyGTK bug - by JAM
 
306
        set_tooltip = getattr(self.treeview, 'set_tooltip_column', None)
 
307
        if set_tooltip is not None:
 
308
            set_tooltip(treemodel.MESSAGE)
 
309
 
368
310
        self.treeview.connect("cursor-changed",
369
311
                self._on_selection_changed)
370
312
 
376
318
 
377
319
        self.treeview.set_property('fixed-height-mode', True)
378
320
 
 
321
        self.add(self.treeview)
379
322
        self.treeview.show()
380
323
 
381
 
        cell = Gtk.CellRendererText()
 
324
        cell = gtk.CellRendererText()
382
325
        cell.set_property("width-chars", 15)
383
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
384
 
        self.revno_column = Gtk.TreeViewColumn("Revision No")
 
326
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
327
        self.revno_column = gtk.TreeViewColumn("Revision No")
385
328
        self.revno_column.set_resizable(True)
386
 
        self.revno_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
387
 
        self.revno_column.set_fixed_width(
388
 
            cell.get_preferred_width(self.treeview)[1])
389
 
        self.revno_column.pack_start(cell, True)
 
329
        self.revno_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
330
        self.revno_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
331
        self.revno_column.pack_start(cell, expand=True)
390
332
        self.revno_column.add_attribute(cell, "text", treemodel.REVNO)
391
333
        self.treeview.append_column(self.revno_column)
392
334
 
393
335
        self.graph_cell = CellRendererGraph()
394
 
        self.graph_column = Gtk.TreeViewColumn()
 
336
        self.graph_column = gtk.TreeViewColumn()
395
337
        self.graph_column.set_resizable(True)
396
 
        self.graph_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
397
 
        self.graph_column.pack_start(self.graph_cell, True)
398
 
        self.graph_column.add_attribute(
399
 
            self.graph_cell, "node", treemodel.NODE)
400
 
        self.graph_column.add_attribute(
401
 
            self.graph_cell, "tags", treemodel.TAGS)
402
 
        self.graph_column.add_attribute(
403
 
            self.graph_cell, "in-lines", treemodel.LAST_LINES)
404
 
        self.graph_column.add_attribute(
405
 
            self.graph_cell, "out-lines", treemodel.LINES)
 
338
        self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
339
        self.graph_column.pack_start(self.graph_cell, expand=False)
 
340
        self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
 
341
        self.graph_column.add_attribute(self.graph_cell, "tags", treemodel.TAGS)
 
342
        self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
 
343
        self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
406
344
        self.treeview.append_column(self.graph_column)
407
345
 
408
 
        cell = Gtk.CellRendererText()
 
346
        cell = gtk.CellRendererText()
409
347
        cell.set_property("width-chars", 65)
410
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
411
 
        self.summary_column = Gtk.TreeViewColumn("Summary")
 
348
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
349
        self.summary_column = gtk.TreeViewColumn("Summary")
412
350
        self.summary_column.set_resizable(True)
413
 
        self.summary_column.set_expand(True)
414
 
        self.summary_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
415
 
        self.summary_column.set_fixed_width(
416
 
            cell.get_preferred_width(self.treeview)[1])
417
 
        self.summary_column.pack_start(cell, True)
 
351
        self.summary_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
352
        self.summary_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
353
        self.summary_column.pack_start(cell, expand=True)
418
354
        self.summary_column.add_attribute(cell, "markup", treemodel.SUMMARY)
419
355
        self.treeview.append_column(self.summary_column)
420
356
 
421
 
        cell = Gtk.CellRendererText()
 
357
        cell = gtk.CellRendererText()
422
358
        cell.set_property("width-chars", 15)
423
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
424
 
        self.authors_column = Gtk.TreeViewColumn("Author(s)")
425
 
        self.authors_column.set_resizable(False)
426
 
        self.authors_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
427
 
        self.authors_column.set_fixed_width(200)
428
 
        self.authors_column.pack_start(cell, True)
429
 
        self.authors_column.add_attribute(cell, "text", treemodel.AUTHORS)
430
 
        self.treeview.append_column(self.authors_column)
 
359
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
360
        self.committer_column = gtk.TreeViewColumn("Committer")
 
361
        self.committer_column.set_resizable(True)
 
362
        self.committer_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
363
        self.committer_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
364
        self.committer_column.pack_start(cell, expand=True)
 
365
        self.committer_column.add_attribute(cell, "text", treemodel.COMMITTER)
 
366
        self.treeview.append_column(self.committer_column)
431
367
 
432
 
        cell = Gtk.CellRendererText()
 
368
        cell = gtk.CellRendererText()
433
369
        cell.set_property("width-chars", 20)
434
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
435
 
        self.date_column = Gtk.TreeViewColumn("Date")
 
370
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
371
        self.date_column = gtk.TreeViewColumn("Date")
436
372
        self.date_column.set_visible(False)
437
373
        self.date_column.set_resizable(True)
438
 
        self.date_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
439
 
        self.date_column.set_fixed_width(130)
440
 
        self.date_column.pack_start(cell, True)
 
374
        self.date_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
375
        self.date_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
376
        self.date_column.pack_start(cell, expand=True)
441
377
        self.date_column.add_attribute(cell, "text", treemodel.TIMESTAMP)
442
378
        self.treeview.append_column(self.date_column)
443
379
 
444
 
        return self.treeview
445
 
 
446
380
    def _on_selection_changed(self, treeview):
447
381
        """callback for when the treeview changes."""
448
382
        (path, focus) = treeview.get_cursor()
449
 
        if (path is not None) and (path != self._prev_cursor_path):
450
 
            self._prev_cursor_path = path # avoid emitting twice per click
451
 
            self.path = path
 
383
        if path is not None:
 
384
            self.iter = self.model.get_iter(path)
452
385
            self.emit('revision-selected')
453
386
 
454
387
    def _on_revision_selected(self, widget, event):
455
 
        from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
 
388
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
456
389
        if event.button == 3:
457
 
            revs = []
458
 
            rev = self.get_revision()
459
 
            if rev is not None:
460
 
                revs.append(rev.revision_id)
461
 
            menu = RevisionMenu(self.branch.repository, revs, self.branch)
462
 
            menu.connect('tag-added', lambda w, t, r: self.add_tag(t, r))
463
 
            menu.popup(None, None, None, None, event.button, event.get_time())
 
390
            menu = RevisionPopupMenu(self.branch.repository, 
 
391
                [self.get_revision().revision_id],
 
392
                self.branch)
 
393
            menu.popup(None, None, None, event.button, event.get_time())
464
394
 
465
395
    def _on_revision_activated(self, widget, path, col):
466
 
        self.emit('revision-activated', path, col)
 
396
        # TODO: more than one parent
 
397
        """Callback for when a treeview row gets activated."""
 
398
        revision_id = self.model[path][treemodel.REVID]
 
399
        parents = self.model[path][treemodel.PARENTS]
 
400
 
 
401
        if len(parents) == 0:
 
402
            parent_id = None
 
403
        else:
 
404
            parent_id = parents[0]
 
405
 
 
406
        self.show_diff(revision_id, parent_id)
 
407
        self.treeview.grab_focus()