/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: Jelmer Vernooij
  • Date: 2008-06-27 16:53:56 UTC
  • mto: This revision was merged to the branch mainline in revision 506.
  • Revision ID: jelmer@samba.org-20080627165356-t5ip7cyqivwye2ro
Make handle-patch not dependend on the users name being abentley and install it.

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 bzrlib.plugins.gtk import _i18n
 
18
from linegraph import linegraph, same_branch
 
19
from graphcell import CellRendererGraph
 
20
from treemodel import TreeModel
14
21
from bzrlib.revision import NULL_REVISION
15
22
 
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):
 
23
class TreeView(gtk.VBox):
24
24
 
25
25
    __gproperties__ = {
26
 
        'branch': (GObject.TYPE_PYOBJECT,
 
26
        'branch': (gobject.TYPE_PYOBJECT,
27
27
                   'Branch',
28
28
                   'The Bazaar branch being visualized',
29
 
                   GObject.PARAM_CONSTRUCT_ONLY | GObject.PARAM_WRITABLE),
 
29
                   gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE),
30
30
 
31
 
        'revision': (GObject.TYPE_PYOBJECT,
 
31
        'revision': (gobject.TYPE_PYOBJECT,
32
32
                     'Revision',
33
33
                     'The currently selected revision',
34
 
                     GObject.PARAM_READWRITE),
 
34
                     gobject.PARAM_READWRITE),
35
35
 
36
 
        'revision-number': (GObject.TYPE_STRING,
 
36
        'revision-number': (gobject.TYPE_STRING,
37
37
                            'Revision number',
38
38
                            'The number of the selected revision',
39
39
                            '',
40
 
                            GObject.PARAM_READABLE),
 
40
                            gobject.PARAM_READABLE),
41
41
 
42
 
        'children': (GObject.TYPE_PYOBJECT,
 
42
        'children': (gobject.TYPE_PYOBJECT,
43
43
                     'Child revisions',
44
44
                     'Children of the currently selected revision',
45
 
                     GObject.PARAM_READABLE),
 
45
                     gobject.PARAM_READABLE),
46
46
 
47
 
        'parents': (GObject.TYPE_PYOBJECT,
 
47
        'parents': (gobject.TYPE_PYOBJECT,
48
48
                    'Parent revisions',
49
49
                    'Parents to the currently selected revision',
50
 
                    GObject.PARAM_READABLE),
 
50
                    gobject.PARAM_READABLE),
51
51
 
52
 
        'revno-column-visible': (GObject.TYPE_BOOLEAN,
 
52
        'revno-column-visible': (gobject.TYPE_BOOLEAN,
53
53
                                 'Revision number column',
54
54
                                 'Show revision number column',
55
55
                                 True,
56
 
                                 GObject.PARAM_READWRITE),
 
56
                                 gobject.PARAM_READWRITE),
57
57
 
58
 
        'graph-column-visible': (GObject.TYPE_BOOLEAN,
 
58
        'graph-column-visible': (gobject.TYPE_BOOLEAN,
59
59
                                 'Graph column',
60
60
                                 'Show graph column',
61
61
                                 True,
62
 
                                 GObject.PARAM_READWRITE),
 
62
                                 gobject.PARAM_READWRITE),
63
63
 
64
 
        'date-column-visible': (GObject.TYPE_BOOLEAN,
 
64
        'date-column-visible': (gobject.TYPE_BOOLEAN,
65
65
                                 'Date',
66
66
                                 'Show date column',
67
67
                                 False,
68
 
                                 GObject.PARAM_READWRITE),
 
68
                                 gobject.PARAM_READWRITE),
69
69
 
70
 
        'compact': (GObject.TYPE_BOOLEAN,
 
70
        'compact': (gobject.TYPE_BOOLEAN,
71
71
                    'Compact view',
72
72
                    'Break ancestry lines to save space',
73
73
                    True,
74
 
                    GObject.PARAM_CONSTRUCT | GObject.PARAM_READWRITE),
 
74
                    gobject.PARAM_CONSTRUCT | gobject.PARAM_READWRITE),
75
75
 
76
 
        'mainline-only': (GObject.TYPE_BOOLEAN,
 
76
        'mainline-only': (gobject.TYPE_BOOLEAN,
77
77
                    'Mainline only',
78
78
                    'Only show the mainline history.',
79
79
                    False,
80
 
                    GObject.PARAM_CONSTRUCT | GObject.PARAM_READWRITE),
 
80
                    gobject.PARAM_CONSTRUCT | gobject.PARAM_READWRITE),
81
81
 
82
82
    }
83
83
 
84
84
    __gsignals__ = {
85
 
        'revision-selected': (GObject.SignalFlags.RUN_FIRST,
86
 
                              None,
 
85
        'revisions-loaded': (gobject.SIGNAL_RUN_FIRST, 
 
86
                             gobject.TYPE_NONE,
 
87
                             ()),
 
88
        'revision-selected': (gobject.SIGNAL_RUN_FIRST,
 
89
                              gobject.TYPE_NONE,
87
90
                              ()),
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
 
                              ())
 
91
        'revision-activated': (gobject.SIGNAL_RUN_FIRST,
 
92
                              gobject.TYPE_NONE,
 
93
                              (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)),
 
94
        'tag-added': (gobject.SIGNAL_RUN_FIRST,
 
95
                              gobject.TYPE_NONE,
 
96
                              (gobject.TYPE_STRING, gobject.TYPE_STRING))
96
97
    }
97
98
 
98
99
    def __init__(self, branch, start, maxnum, compact=True):
105
106
        :param broken_line_length: After how much lines to break 
106
107
                                   branches.
107
108
        """
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)
 
109
        gtk.VBox.__init__(self, spacing=0)
 
110
 
 
111
        self.pack_start(self.construct_loading_msg(), expand=False, fill=True)
 
112
        self.connect('revisions-loaded', 
 
113
                lambda x: self.loading_msg_box.hide())
 
114
 
 
115
        self.scrolled_window = gtk.ScrolledWindow()
 
116
        self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
 
117
                                        gtk.POLICY_AUTOMATIC)
 
118
        self.scrolled_window.set_shadow_type(gtk.SHADOW_IN)
120
119
        self.scrolled_window.show()
121
 
        self.pack_start(self.scrolled_window, True, True, 0)
 
120
        self.pack_start(self.scrolled_window, expand=True, fill=True)
122
121
 
123
122
        self.scrolled_window.add(self.construct_treeview())
 
123
        
124
124
 
125
 
        self.path = None
 
125
        self.iter = None
126
126
        self.branch = branch
127
127
        self.revision = None
128
 
        self.index = {}
129
128
 
130
129
        self.start = start
131
130
        self.maxnum = maxnum
132
131
        self.compact = compact
133
132
 
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)
 
133
        gobject.idle_add(self.populate)
 
134
 
 
135
        self.connect("destroy", lambda x: self.branch.unlock())
144
136
 
145
137
    def do_get_property(self, property):
146
138
        if property.name == 'revno-column-visible':
156
148
        elif property.name == 'branch':
157
149
            return self.branch
158
150
        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)
 
151
            return self.model.get_value(self.iter, treemodel.REVISION)
163
152
        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)
 
153
            return self.model.get_value(self.iter, treemodel.REVNO)
168
154
        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)
 
155
            return self.model.get_value(self.iter, treemodel.CHILDREN)
173
156
        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)
 
157
            return self.model.get_value(self.iter, treemodel.PARENTS)
178
158
        else:
179
159
            raise AttributeError, 'unknown property %s' % property.name
180
160
 
200
180
        """Return revision id of currently selected revision, or None."""
201
181
        return self.get_property('revision')
202
182
 
203
 
    def has_revision_id(self, revision_id):
204
 
        return (revision_id in self.index)
205
 
 
206
183
    def set_revision(self, revision):
207
184
        self.set_property('revision', revision)
208
185
 
211
188
 
212
189
        :param revid: Revision id of revision to display.
213
190
        """
214
 
        self.treeview.set_cursor(
215
 
            Gtk.TreePath(path=self.index[revid]), None, False)
 
191
        self.treeview.set_cursor(self.index[revid])
216
192
        self.treeview.grab_focus()
217
193
 
218
194
    def get_children(self):
232
208
    def add_tag(self, tag, revid=None):
233
209
        if revid is None: revid = self.revision.revision_id
234
210
 
235
 
        if lock.release(self.branch):
 
211
        try:
 
212
            self.branch.unlock()
 
213
 
236
214
            try:
237
 
                lock.acquire(self.branch, lock.WRITE)
 
215
                self.branch.lock_write()
238
216
                self.model.add_tag(tag, revid)
239
217
            finally:
240
 
                lock.release(self.branch)
241
 
 
242
 
            lock.acquire(self.branch, lock.READ)
243
 
 
244
 
            self.emit('tag-added', tag, revid)
245
 
 
 
218
                self.branch.unlock()
 
219
 
 
220
        finally:
 
221
            self.branch.lock_read()
 
222
 
 
223
        self.emit('tag-added', tag, revid)
 
224
        
246
225
    def refresh(self):
247
 
        GObject.idle_add(self.populate, self.get_revision())
 
226
        self.loading_msg_box.show()
 
227
        gobject.idle_add(self.populate, self.get_revision())
248
228
 
249
229
    def update(self):
250
230
        try:
260
240
    def back(self):
261
241
        """Signal handler for the Back button."""
262
242
        parents = self.get_parents()
263
 
        if not parents:
 
243
        if not len(parents):
264
244
            return
265
245
 
266
246
        for parent_id in parents:
275
255
    def forward(self):
276
256
        """Signal handler for the Forward button."""
277
257
        children = self.get_children()
278
 
        if not children:
 
258
        if not len(children):
279
259
            return
280
260
 
281
261
        for child_id in children:
297
277
                       should be broken.
298
278
        """
299
279
 
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()
 
280
        if self.compact:
 
281
            broken_line_length = 32
 
282
        else:
 
283
            broken_line_length = None
 
284
        
 
285
        show_graph = self.graph_column.get_visible()
 
286
 
 
287
        self.branch.lock_read()
 
288
        (linegraphdata, index, columns_len) = linegraph(self.branch.repository,
 
289
                                                        self.start,
 
290
                                                        self.maxnum, 
 
291
                                                        broken_line_length,
 
292
                                                        show_graph,
 
293
                                                        self.mainline_only)
 
294
 
 
295
        self.model = TreeModel(self.branch, linegraphdata)
 
296
        self.graph_cell.columns_len = columns_len
 
297
        width = self.graph_cell.get_size(self.treeview)[2]
 
298
        if width > 500:
 
299
            width = 500
 
300
        self.graph_column.set_fixed_width(width)
 
301
        self.graph_column.set_max_width(width)
 
302
        self.index = index
 
303
        self.treeview.set_model(self.model)
 
304
 
 
305
        if not revision or revision == NULL_REVISION:
 
306
            self.treeview.set_cursor(0)
 
307
        else:
 
308
            self.set_revision(revision)
 
309
 
 
310
        self.emit('revisions-loaded')
 
311
 
 
312
        return False
346
313
 
347
314
    def construct_treeview(self):
348
 
        self.treeview = Gtk.TreeView()
 
315
        self.treeview = gtk.TreeView()
349
316
 
350
317
        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
 
318
        self.treeview.set_search_column(treemodel.REVNO)
 
319
        
 
320
        # Fix old PyGTK bug - by JAM
 
321
        set_tooltip = getattr(self.treeview, 'set_tooltip_column', None)
 
322
        if set_tooltip is not None:
 
323
            set_tooltip(treemodel.MESSAGE)
 
324
 
368
325
        self.treeview.connect("cursor-changed",
369
326
                self._on_selection_changed)
370
327
 
378
335
 
379
336
        self.treeview.show()
380
337
 
381
 
        cell = Gtk.CellRendererText()
 
338
        cell = gtk.CellRendererText()
382
339
        cell.set_property("width-chars", 15)
383
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
384
 
        self.revno_column = Gtk.TreeViewColumn("Revision No")
385
 
        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)
 
340
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
341
        self.revno_column = gtk.TreeViewColumn("Revision No")
 
342
        self.revno_column.set_resizable(False)
 
343
        self.revno_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
344
        self.revno_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
345
        self.revno_column.pack_start(cell, expand=True)
390
346
        self.revno_column.add_attribute(cell, "text", treemodel.REVNO)
391
347
        self.treeview.append_column(self.revno_column)
392
348
 
393
349
        self.graph_cell = CellRendererGraph()
394
 
        self.graph_column = Gtk.TreeViewColumn()
395
 
        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)
 
350
        self.graph_column = gtk.TreeViewColumn()
 
351
        self.graph_column.set_resizable(False)
 
352
        self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
353
        self.graph_column.pack_start(self.graph_cell, expand=True)
 
354
        self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
 
355
        self.graph_column.add_attribute(self.graph_cell, "tags", treemodel.TAGS)
 
356
        self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
 
357
        self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
406
358
        self.treeview.append_column(self.graph_column)
407
359
 
408
 
        cell = Gtk.CellRendererText()
 
360
        cell = gtk.CellRendererText()
409
361
        cell.set_property("width-chars", 65)
410
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
411
 
        self.summary_column = Gtk.TreeViewColumn("Summary")
412
 
        self.summary_column.set_resizable(True)
 
362
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
363
        self.summary_column = gtk.TreeViewColumn("Summary")
 
364
        self.summary_column.set_resizable(False)
413
365
        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)
 
366
        self.summary_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
367
        self.summary_column.set_fixed_width(cell.get_size(self.treeview)[2])
 
368
        self.summary_column.pack_start(cell, expand=True)
418
369
        self.summary_column.add_attribute(cell, "markup", treemodel.SUMMARY)
419
370
        self.treeview.append_column(self.summary_column)
420
371
 
421
 
        cell = Gtk.CellRendererText()
 
372
        cell = gtk.CellRendererText()
422
373
        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)
 
374
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
375
        self.committer_column = gtk.TreeViewColumn("Committer")
 
376
        self.committer_column.set_resizable(False)
 
377
        self.committer_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
378
        self.committer_column.set_fixed_width(200)
 
379
        self.committer_column.pack_start(cell, expand=True)
 
380
        self.committer_column.add_attribute(cell, "text", treemodel.COMMITTER)
 
381
        self.treeview.append_column(self.committer_column)
431
382
 
432
 
        cell = Gtk.CellRendererText()
 
383
        cell = gtk.CellRendererText()
433
384
        cell.set_property("width-chars", 20)
434
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
435
 
        self.date_column = Gtk.TreeViewColumn("Date")
 
385
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
386
        self.date_column = gtk.TreeViewColumn("Date")
436
387
        self.date_column.set_visible(False)
437
 
        self.date_column.set_resizable(True)
438
 
        self.date_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
 
388
        self.date_column.set_resizable(False)
 
389
        self.date_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
439
390
        self.date_column.set_fixed_width(130)
440
 
        self.date_column.pack_start(cell, True)
 
391
        self.date_column.pack_start(cell, expand=True)
441
392
        self.date_column.add_attribute(cell, "text", treemodel.TIMESTAMP)
442
393
        self.treeview.append_column(self.date_column)
443
 
 
 
394
        
444
395
        return self.treeview
 
396
    
 
397
    def construct_loading_msg(self):
 
398
        image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
 
399
                                                 gtk.ICON_SIZE_BUTTON)
 
400
        image_loading.show()
 
401
        
 
402
        label_loading = gtk.Label(
 
403
            _i18n("Please wait, loading ancestral graph..."))
 
404
        label_loading.set_alignment(0.0, 0.5)
 
405
        label_loading.show()
 
406
        
 
407
        self.loading_msg_box = gtk.HBox()
 
408
        self.loading_msg_box.set_spacing(5)
 
409
        self.loading_msg_box.set_border_width(5)        
 
410
        self.loading_msg_box.pack_start(image_loading, False, False)
 
411
        self.loading_msg_box.pack_start(label_loading, True, True)
 
412
        self.loading_msg_box.show()
 
413
        
 
414
        return self.loading_msg_box
445
415
 
446
416
    def _on_selection_changed(self, treeview):
447
417
        """callback for when the treeview changes."""
448
418
        (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
 
419
        if path is not None:
 
420
            self.iter = self.model.get_iter(path)
452
421
            self.emit('revision-selected')
453
422
 
454
423
    def _on_revision_selected(self, widget, event):
455
 
        from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
 
424
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
456
425
        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)
 
426
            menu = RevisionPopupMenu(self.branch.repository, 
 
427
                [self.get_revision().revision_id],
 
428
                self.branch)
462
429
            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())
 
430
            menu.popup(None, None, None, event.button, event.get_time())
464
431
 
465
432
    def _on_revision_activated(self, widget, path, col):
466
433
        self.emit('revision-activated', path, col)