/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: Aaron Bentley
  • Date: 2008-02-23 06:39:14 UTC
  • Revision ID: aaron@aaronbentley.com-20080223063914-49gdt7ed630rug9b
Add handle-patch script

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.VBox):
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)
 
93
        gtk.VBox.__init__(self, spacing=0)
 
94
 
 
95
        self.pack_start(self.construct_loading_msg(), expand=False, fill=True)
 
96
        self.connect('revisions-loaded', 
 
97
                lambda x: self.loading_msg_box.hide())
 
98
 
 
99
        self.scrolled_window = gtk.ScrolledWindow()
 
100
        self.scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
 
101
        self.scrolled_window.set_shadow_type(gtk.SHADOW_IN)
120
102
        self.scrolled_window.show()
121
 
        self.pack_start(self.scrolled_window, True, True, 0)
 
103
        self.pack_start(self.scrolled_window, expand=True, fill=True)
122
104
 
123
105
        self.scrolled_window.add(self.construct_treeview())
 
106
        
124
107
 
125
 
        self.path = None
 
108
        self.iter = None
126
109
        self.branch = branch
127
110
        self.revision = None
128
 
        self.index = {}
129
111
 
130
112
        self.start = start
131
113
        self.maxnum = maxnum
132
114
        self.compact = compact
133
115
 
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)
 
116
        gobject.idle_add(self.populate)
 
117
 
 
118
        self.connect("destroy", lambda x: self.branch.unlock())
144
119
 
145
120
    def do_get_property(self, property):
146
121
        if property.name == 'revno-column-visible':
147
122
            return self.revno_column.get_visible()
148
 
        elif property.name == 'graph-column-visible':
149
 
            return self.graph_column.get_visible()
150
123
        elif property.name == 'date-column-visible':
151
124
            return self.date_column.get_visible()
152
125
        elif property.name == 'compact':
153
126
            return self.compact
154
 
        elif property.name == 'mainline-only':
155
 
            return self.mainline_only
156
127
        elif property.name == 'branch':
157
128
            return self.branch
158
129
        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)
 
130
            return self.model.get_value(self.iter, treemodel.REVISION)
163
131
        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)
 
132
            return self.model.get_value(self.iter, treemodel.REVNO)
168
133
        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)
 
134
            return self.model.get_value(self.iter, treemodel.CHILDREN)
173
135
        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)
 
136
            return self.model.get_value(self.iter, treemodel.PARENTS)
178
137
        else:
179
138
            raise AttributeError, 'unknown property %s' % property.name
180
139
 
181
140
    def do_set_property(self, property, value):
182
141
        if property.name == 'revno-column-visible':
183
142
            self.revno_column.set_visible(value)
184
 
        elif property.name == 'graph-column-visible':
185
 
            self.graph_column.set_visible(value)
186
143
        elif property.name == 'date-column-visible':
187
144
            self.date_column.set_visible(value)
188
145
        elif property.name == 'compact':
189
146
            self.compact = value
190
 
        elif property.name == 'mainline-only':
191
 
            self.mainline_only = value
192
147
        elif property.name == 'branch':
193
148
            self.branch = value
194
149
        elif property.name == 'revision':
200
155
        """Return revision id of currently selected revision, or None."""
201
156
        return self.get_property('revision')
202
157
 
203
 
    def has_revision_id(self, revision_id):
204
 
        return (revision_id in self.index)
205
 
 
206
158
    def set_revision(self, revision):
207
159
        self.set_property('revision', revision)
208
160
 
211
163
 
212
164
        :param revid: Revision id of revision to display.
213
165
        """
214
 
        self.treeview.set_cursor(
215
 
            Gtk.TreePath(path=self.index[revid]), None, False)
 
166
        self.treeview.set_cursor(self.index[revid])
216
167
        self.treeview.grab_focus()
217
168
 
218
169
    def get_children(self):
232
183
    def add_tag(self, tag, revid=None):
233
184
        if revid is None: revid = self.revision.revision_id
234
185
 
235
 
        if lock.release(self.branch):
 
186
        try:
 
187
            self.branch.unlock()
 
188
 
236
189
            try:
237
 
                lock.acquire(self.branch, lock.WRITE)
 
190
                self.branch.lock_write()
238
191
                self.model.add_tag(tag, revid)
239
192
            finally:
240
 
                lock.release(self.branch)
241
 
 
242
 
            lock.acquire(self.branch, lock.READ)
243
 
 
244
 
            self.emit('tag-added', tag, revid)
245
 
 
 
193
                self.branch.unlock()
 
194
 
 
195
        finally:
 
196
            self.branch.lock_read()
 
197
 
 
198
        self.emit('tag-added', tag, revid)
 
199
        
246
200
    def refresh(self):
247
 
        GObject.idle_add(self.populate, self.get_revision())
 
201
        self.loading_msg_box.show()
 
202
        gobject.idle_add(self.populate, self.get_revision())
248
203
 
249
204
    def update(self):
250
205
        try:
260
215
    def back(self):
261
216
        """Signal handler for the Back button."""
262
217
        parents = self.get_parents()
263
 
        if not parents:
 
218
        if not len(parents):
264
219
            return
265
220
 
266
221
        for parent_id in parents:
275
230
    def forward(self):
276
231
        """Signal handler for the Forward button."""
277
232
        children = self.get_children()
278
 
        if not children:
 
233
        if not len(children):
279
234
            return
280
235
 
281
236
        for child_id in children:
297
252
                       should be broken.
298
253
        """
299
254
 
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()
 
255
        if self.compact:
 
256
            broken_line_length = 32
 
257
        else:
 
258
            broken_line_length = None
 
259
 
 
260
        self.branch.lock_read()
 
261
        (linegraphdata, index, columns_len) = linegraph(self.branch.repository,
 
262
                                                        self.start,
 
263
                                                        self.maxnum, 
 
264
                                                        broken_line_length)
 
265
 
 
266
        self.model = TreeModel(self.branch, linegraphdata)
 
267
        self.graph_cell.columns_len = columns_len
 
268
        width = self.graph_cell.get_size(self.treeview)[2]
 
269
        if width > 500:
 
270
            width = 500
 
271
        self.graph_column.set_fixed_width(width)
 
272
        self.graph_column.set_max_width(width)
 
273
        self.index = index
 
274
        self.treeview.set_model(self.model)
 
275
 
 
276
        if revision is None:
 
277
            self.treeview.set_cursor(0)
 
278
        else:
 
279
            self.set_revision(revision)
 
280
 
 
281
        self.emit('revisions-loaded')
 
282
 
 
283
        return False
 
284
 
 
285
    def show_diff(self, revid=None, parentid=None):
 
286
        """Open a new window to show a diff between the given revisions."""
 
287
        from bzrlib.plugins.gtk.diff import DiffWindow
 
288
        window = DiffWindow(parent=self)
 
289
 
 
290
        parents = self.get_parents()
 
291
 
 
292
        if revid is None:
 
293
            revid = self.get_revision().revision_id
 
294
 
 
295
            if parentid is None and len(parents) > 0:
 
296
                parentid = parents[0]
 
297
 
 
298
        if parentid is None:
 
299
            parentid = NULL_REVISION
 
300
 
 
301
        rev_tree    = self.branch.repository.revision_tree(revid)
 
302
        parent_tree = self.branch.repository.revision_tree(parentid)
 
303
 
 
304
        description = revid + " - " + self.branch.nick
 
305
        window.set_diff(description, rev_tree, parent_tree)
 
306
        window.show()
346
307
 
347
308
    def construct_treeview(self):
348
 
        self.treeview = Gtk.TreeView()
 
309
        self.treeview = gtk.TreeView()
349
310
 
350
311
        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
 
312
        self.treeview.set_search_column(treemodel.REVNO)
 
313
        
 
314
        # Fix old PyGTK bug - by JAM
 
315
        set_tooltip = getattr(self.treeview, 'set_tooltip_column', None)
 
316
        if set_tooltip is not None:
 
317
            set_tooltip(treemodel.MESSAGE)
 
318
 
368
319
        self.treeview.connect("cursor-changed",
369
320
                self._on_selection_changed)
370
321
 
378
329
 
379
330
        self.treeview.show()
380
331
 
381
 
        cell = Gtk.CellRendererText()
 
332
        cell = gtk.CellRendererText()
382
333
        cell.set_property("width-chars", 15)
383
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
384
 
        self.revno_column = Gtk.TreeViewColumn("Revision No")
 
334
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
335
        self.revno_column = gtk.TreeViewColumn("Revision No")
385
336
        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)
 
337
        self.revno_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
338
        self.revno_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
339
        self.revno_column.pack_start(cell, expand=True)
390
340
        self.revno_column.add_attribute(cell, "text", treemodel.REVNO)
391
341
        self.treeview.append_column(self.revno_column)
392
342
 
393
343
        self.graph_cell = CellRendererGraph()
394
 
        self.graph_column = Gtk.TreeViewColumn()
 
344
        self.graph_column = gtk.TreeViewColumn()
395
345
        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)
 
346
        self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
347
        self.graph_column.pack_start(self.graph_cell, expand=False)
 
348
        self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
 
349
        self.graph_column.add_attribute(self.graph_cell, "tags", treemodel.TAGS)
 
350
        self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
 
351
        self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
406
352
        self.treeview.append_column(self.graph_column)
407
353
 
408
 
        cell = Gtk.CellRendererText()
 
354
        cell = gtk.CellRendererText()
409
355
        cell.set_property("width-chars", 65)
410
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
411
 
        self.summary_column = Gtk.TreeViewColumn("Summary")
 
356
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
357
        self.summary_column = gtk.TreeViewColumn("Summary")
412
358
        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)
 
359
        self.summary_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
360
        self.summary_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
361
        self.summary_column.pack_start(cell, expand=True)
418
362
        self.summary_column.add_attribute(cell, "markup", treemodel.SUMMARY)
419
363
        self.treeview.append_column(self.summary_column)
420
364
 
421
 
        cell = Gtk.CellRendererText()
 
365
        cell = gtk.CellRendererText()
422
366
        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)
 
367
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
368
        self.committer_column = gtk.TreeViewColumn("Committer")
 
369
        self.committer_column.set_resizable(True)
 
370
        self.committer_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
371
        self.committer_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
372
        self.committer_column.pack_start(cell, expand=True)
 
373
        self.committer_column.add_attribute(cell, "text", treemodel.COMMITTER)
 
374
        self.treeview.append_column(self.committer_column)
431
375
 
432
 
        cell = Gtk.CellRendererText()
 
376
        cell = gtk.CellRendererText()
433
377
        cell.set_property("width-chars", 20)
434
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
435
 
        self.date_column = Gtk.TreeViewColumn("Date")
 
378
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
379
        self.date_column = gtk.TreeViewColumn("Date")
436
380
        self.date_column.set_visible(False)
437
381
        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)
 
382
        self.date_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
383
        self.date_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
384
        self.date_column.pack_start(cell, expand=True)
441
385
        self.date_column.add_attribute(cell, "text", treemodel.TIMESTAMP)
442
386
        self.treeview.append_column(self.date_column)
443
 
 
 
387
        
444
388
        return self.treeview
 
389
    
 
390
    def construct_loading_msg(self):
 
391
        image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
 
392
                                                 gtk.ICON_SIZE_BUTTON)
 
393
        image_loading.show()
 
394
        
 
395
        label_loading = gtk.Label(_("Please wait, loading ancestral graph..."))
 
396
        label_loading.set_alignment(0.0, 0.5)
 
397
        label_loading.show()
 
398
        
 
399
        self.loading_msg_box = gtk.HBox()
 
400
        self.loading_msg_box.set_spacing(5)
 
401
        self.loading_msg_box.set_border_width(5)        
 
402
        self.loading_msg_box.pack_start(image_loading, False, False)
 
403
        self.loading_msg_box.pack_start(label_loading, True, True)
 
404
        self.loading_msg_box.show()
 
405
        
 
406
        return self.loading_msg_box
445
407
 
446
408
    def _on_selection_changed(self, treeview):
447
409
        """callback for when the treeview changes."""
448
410
        (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
 
411
        if path is not None:
 
412
            self.iter = self.model.get_iter(path)
452
413
            self.emit('revision-selected')
453
414
 
454
415
    def _on_revision_selected(self, widget, event):
455
 
        from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
 
416
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
456
417
        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)
 
418
            menu = RevisionPopupMenu(self.branch.repository, 
 
419
                [self.get_revision().revision_id],
 
420
                self.branch)
462
421
            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())
 
422
            menu.popup(None, None, None, event.button, event.get_time())
464
423
 
465
424
    def _on_revision_activated(self, widget, path, col):
466
 
        self.emit('revision-activated', path, col)
 
425
        # TODO: more than one parent
 
426
        """Callback for when a treeview row gets activated."""
 
427
        revision_id = self.model[path][treemodel.REVID]
 
428
        parents = self.model[path][treemodel.PARENTS]
 
429
 
 
430
        if len(parents) == 0:
 
431
            parent_id = None
 
432
        else:
 
433
            parent_id = parents[0]
 
434
 
 
435
        self.show_diff(revision_id, parent_id)
 
436
        self.treeview.grab_focus()