/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 annotate/logview.py

  • Committer: Jelmer Vernooij
  • Date: 2006-05-19 16:56:46 UTC
  • mfrom: (0.1.25 gannotate)
  • Revision ID: jelmer@samba.org-20060519165646-0d867938fdbc9097
Merge in Dan Loda's gannotate plugin and put it in annotate/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005 Dan Loda <danloda@gmail.com>
2
 
# Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3
2
 
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
19
18
pygtk.require("2.0")
20
19
import gtk
21
20
import pango
22
 
import gobject
23
21
 
24
22
from bzrlib.osutils import format_date
25
 
from bzrlib.util.bencode import bdecode
26
 
 
27
 
class RevisionView(gtk.Notebook):
 
23
 
 
24
 
 
25
class LogView(gtk.ScrolledWindow):
28
26
    """ Custom widget for commit log details.
29
27
 
30
28
    A variety of bzr tools may need to implement such a thing. This is a
31
29
    start.
32
30
    """
33
31
 
34
 
    __gproperties__ = {
35
 
        'branch': (
36
 
            gobject.TYPE_PYOBJECT,
37
 
            'Branch',
38
 
            'The branch holding the revision being displayed',
39
 
            gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE
40
 
        ),
41
 
 
42
 
        'revision': (
43
 
            gobject.TYPE_PYOBJECT,
44
 
            'Revision',
45
 
            'The revision being displayed',
46
 
            gobject.PARAM_READWRITE
47
 
        ),
48
 
 
49
 
        'children': (
50
 
            gobject.TYPE_PYOBJECT,
51
 
            'Children',
52
 
            'Child revisions',
53
 
            gobject.PARAM_READWRITE
54
 
        ),
55
 
 
56
 
        'file-id': (
57
 
            gobject.TYPE_PYOBJECT,
58
 
            'File Id',
59
 
            'The file id',
60
 
            gobject.PARAM_READWRITE
61
 
        )
62
 
    }
63
 
 
64
 
 
65
 
    def __init__(self, branch=None):
66
 
        gtk.Notebook.__init__(self)
67
 
 
68
 
        self._create_general()
69
 
        self._create_relations()
70
 
        self._create_file_info_view()
71
 
 
72
 
        self.set_current_page(0)
73
 
        
74
 
        self._show_callback = None
75
 
        self._clicked_callback = None
76
 
 
77
 
        self._revision = None
78
 
        self._branch = branch
79
 
 
80
 
        self.update_tags()
81
 
 
82
 
        self.set_file_id(None)
83
 
 
84
 
    def do_get_property(self, property):
85
 
        if property.name == 'branch':
86
 
            return self._branch
87
 
        elif property.name == 'revision':
88
 
            return self._revision
89
 
        elif property.name == 'children':
90
 
            return self._children
91
 
        elif property.name == 'file-id':
92
 
            return self._file_id
93
 
        else:
94
 
            raise AttributeError, 'unknown property %s' % property.name
95
 
 
96
 
    def do_set_property(self, property, value):
97
 
        if property.name == 'branch':
98
 
            self._branch = value
99
 
        elif property.name == 'revision':
100
 
            self._set_revision(value)
101
 
        elif property.name == 'children':
102
 
            self.set_children(value)
103
 
        elif property.name == 'file-id':
104
 
            self._file_id = value
105
 
        else:
106
 
            raise AttributeError, 'unknown property %s' % property.name
107
 
 
108
 
    def set_show_callback(self, callback):
109
 
        self._show_callback = callback
110
 
 
111
 
    def set_file_id(self, file_id):
112
 
        """Set a specific file id that we want to track.
113
 
 
114
 
        This just effects the display of a per-file commit message.
115
 
        If it is set to None, then all commit messages will be shown.
116
 
        """
117
 
        self.set_property('file-id', file_id)
 
32
    def __init__(self, revision=None):
 
33
        gtk.ScrolledWindow.__init__(self)
 
34
        self.parent_id_widgets = []
 
35
        self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
36
        self.set_shadow_type(gtk.SHADOW_NONE)
 
37
        self._create()
 
38
 
 
39
        if revision is not None:
 
40
            self.set_revision(revision)
118
41
 
119
42
    def set_revision(self, revision):
120
 
        if revision != self._revision:
121
 
            self.set_property('revision', revision)
122
 
 
123
 
    def get_revision(self):
124
 
        return self.get_property('revision')
125
 
 
126
 
    def _set_revision(self, revision):
127
 
        if revision is None: return
128
 
 
129
 
        self._revision = revision
130
 
        if revision.committer is not None:
131
 
            self.committer.set_text(revision.committer)
132
 
        else:
133
 
            self.committer.set_text("")
134
 
        author = revision.properties.get('author', '')
135
 
        if author != '':
136
 
            self.author.set_text(author)
137
 
            self.author.show()
138
 
            self.author_label.show()
139
 
        else:
140
 
            self.author.hide()
141
 
            self.author_label.hide()
142
 
 
143
 
        if revision.timestamp is not None:
144
 
            self.timestamp.set_text(format_date(revision.timestamp,
145
 
                                                revision.timezone))
146
 
        try:
147
 
            self.branchnick_label.set_text(revision.properties['branch-nick'])
148
 
        except KeyError:
149
 
            self.branchnick_label.set_text("")
150
 
 
151
 
        self._add_parents_or_children(revision.parent_ids,
152
 
                                      self.parents_widgets,
153
 
                                      self.parents_table)
154
 
        
155
 
        file_info = revision.properties.get('file-info', None)
156
 
        if file_info is not None:
157
 
            file_info = bdecode(file_info.encode('UTF-8'))
158
 
 
159
 
        if file_info:
160
 
            if self._file_id is None:
161
 
                text = []
162
 
                for fi in file_info:
163
 
                    text.append('%(path)s\n%(message)s' % fi)
164
 
                self.file_info_buffer.set_text('\n'.join(text))
165
 
                self.file_info_box.show()
166
 
            else:
167
 
                text = []
168
 
                for fi in file_info:
169
 
                    if fi['file_id'] == self._file_id:
170
 
                        text.append(fi['message'])
171
 
                if text:
172
 
                    self.file_info_buffer.set_text('\n'.join(text))
173
 
                    self.file_info_box.show()
174
 
                else:
175
 
                    self.file_info_box.hide()
176
 
        else:
177
 
            self.file_info_box.hide()
178
 
 
179
 
    def update_tags(self):
180
 
        if self._branch is not None and self._branch.supports_tags():
181
 
            self._tagdict = self._branch.tags.get_reverse_tag_dict()
182
 
        else:
183
 
            self._tagdict = {}
184
 
 
185
 
        self._add_tags()
186
 
 
187
 
    def set_children(self, children):
188
 
        self._add_parents_or_children(children,
189
 
                                      self.children_widgets,
190
 
                                      self.children_table)
191
 
 
192
 
    def _show_clicked_cb(self, widget, revid, parentid):
193
 
        """Callback for when the show button for a parent is clicked."""
194
 
        self._show_callback(revid, parentid)
195
 
 
196
 
    def _go_clicked_cb(self, widget, revid):
197
 
        """Callback for when the go button for a parent is clicked."""
198
 
 
199
 
    def _add_tags(self, *args):
200
 
        if self._revision is None: return
201
 
 
202
 
        if self._tagdict.has_key(self._revision.revision_id):
203
 
            tags = self._tagdict[self._revision.revision_id]
204
 
        else:
205
 
            tags = []
 
43
        self.revision_id.set_text(revision.revision_id)
 
44
        self.committer.set_text(revision.committer)
 
45
        self.timestamp.set_text(format_date(revision.timestamp,
 
46
                                            revision.timezone))
 
47
        self.message_buffer.set_text(revision.message)
 
48
        self._add_parents(revision.parent_ids)
 
49
 
 
50
    def _add_parents(self, parent_ids):
 
51
        for widget in self.parent_id_widgets:
 
52
            self.table.remove(widget)
206
53
            
207
 
        if tags == []:
208
 
            self.tags_list.hide()
209
 
            self.tags_label.hide()
210
 
            return
211
 
 
212
 
        self.tags_list.set_text(", ".join(tags))
213
 
 
214
 
        self.tags_list.show_all()
215
 
        self.tags_label.show_all()
216
 
        
217
 
    def _add_parents_or_children(self, revids, widgets, table):
218
 
        while len(widgets) > 0:
219
 
            widget = widgets.pop()
220
 
            table.remove(widget)
221
 
        
222
 
        table.resize(max(len(revids), 1), 2)
223
 
 
224
 
        for idx, revid in enumerate(revids):
225
 
            align = gtk.Alignment(0.0, 0.0)
226
 
            widgets.append(align)
227
 
            table.attach(align, 1, 2, idx, idx + 1,
228
 
                                      gtk.EXPAND | gtk.FILL, gtk.FILL)
 
54
        self.parent_id_widgets = []
 
55
 
 
56
        if len(parent_ids):
 
57
            self.table.resize(4 + len(parent_ids), 2)
 
58
 
 
59
            align = gtk.Alignment(1.0, 0.5)
229
60
            align.show()
230
 
 
231
 
            hbox = gtk.HBox(False, spacing=6)
232
 
            align.add(hbox)
233
 
            hbox.show()
234
 
 
235
 
            image = gtk.Image()
236
 
            image.set_from_stock(
237
 
                gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)
238
 
            image.show()
239
 
 
240
 
            if self._show_callback is not None:
241
 
                button = gtk.Button()
242
 
                button.add(image)
243
 
                button.connect("clicked", self._show_clicked_cb,
244
 
                               self._revision.revision_id, revid)
245
 
                hbox.pack_start(button, expand=False, fill=True)
246
 
                button.show()
247
 
 
248
 
            button = gtk.Button(revid)
249
 
            button.connect("clicked",
250
 
                    lambda w, r: self.set_revision(self._branch.repository.get_revision(r)), revid)
251
 
            button.set_use_underline(False)
252
 
            hbox.pack_start(button, expand=False, fill=True)
253
 
            button.show()
254
 
 
255
 
    def _create_general(self):
 
61
            self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
 
62
            self.parent_id_widgets.append(align)
 
63
 
 
64
            label = gtk.Label()
 
65
            if len(parent_ids) > 1:
 
66
                label.set_markup("<b>Parent Ids:</b>")
 
67
            else:
 
68
                label.set_markup("<b>Parent Id:</b>")
 
69
            label.show()
 
70
            align.add(label)
 
71
 
 
72
            for i, parent_id in enumerate(parent_ids):
 
73
                align = gtk.Alignment(0.0, 0.5)
 
74
                self.parent_id_widgets.append(align)
 
75
                self.table.attach(align, 1, 2, i + 3, i + 4,
 
76
                                  gtk.EXPAND | gtk.FILL, gtk.FILL)
 
77
                align.show()
 
78
                label = gtk.Label(parent_id)
 
79
                label.set_selectable(True)
 
80
                label.show()
 
81
                align.add(label)
 
82
 
 
83
    def _create(self):
256
84
        vbox = gtk.VBox(False, 6)
257
85
        vbox.set_border_width(6)
258
86
        vbox.pack_start(self._create_headers(), expand=False, fill=True)
259
87
        vbox.pack_start(self._create_message_view())
260
 
        self.append_page(vbox, tab_label=gtk.Label("General"))
261
 
        vbox.show()
262
 
 
263
 
    def _create_relations(self):
264
 
        vbox = gtk.VBox(False, 6)
265
 
        vbox.set_border_width(6)
266
 
        vbox.pack_start(self._create_parents(), expand=False, fill=True)
267
 
        vbox.pack_start(self._create_children(), expand=False, fill=True)
268
 
        self.append_page(vbox, tab_label=gtk.Label("Relations"))
 
88
        self.add_with_viewport(vbox)
269
89
        vbox.show()
270
90
 
271
91
    def _create_headers(self):
272
 
        self.table = gtk.Table(rows=5, columns=2)
 
92
        self.table = gtk.Table(rows=4, columns=2)
273
93
        self.table.set_row_spacings(6)
274
94
        self.table.set_col_spacings(6)
275
95
        self.table.show()
276
 
 
 
96
        
277
97
        align = gtk.Alignment(1.0, 0.5)
278
98
        label = gtk.Label()
279
 
        label.set_markup("<b>Revision Id:</b>")
 
99
        label.set_markup("<b>Committer:</b>")
280
100
        align.add(label)
281
101
        self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
282
102
        align.show()
283
103
        label.show()
284
104
 
285
105
        align = gtk.Alignment(0.0, 0.5)
286
 
        revision_id = gtk.Label()
287
 
        revision_id.set_selectable(True)
288
 
        self.connect('notify::revision', 
289
 
                lambda w, p: revision_id.set_text(self._revision.revision_id))
290
 
        align.add(revision_id)
291
 
        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
292
 
        align.show()
293
 
        revision_id.show()
294
 
 
295
 
        align = gtk.Alignment(1.0, 0.5)
296
 
        self.author_label = gtk.Label()
297
 
        self.author_label.set_markup("<b>Author:</b>")
298
 
        align.add(self.author_label)
299
 
        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
300
 
        align.show()
301
 
        self.author_label.show()
302
 
 
303
 
        align = gtk.Alignment(0.0, 0.5)
304
 
        self.author = gtk.Label()
305
 
        self.author.set_selectable(True)
306
 
        align.add(self.author)
307
 
        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
308
 
        align.show()
309
 
        self.author.show()
310
 
        self.author.hide()
311
 
 
312
 
        align = gtk.Alignment(1.0, 0.5)
313
 
        label = gtk.Label()
314
 
        label.set_markup("<b>Committer:</b>")
315
 
        align.add(label)
316
 
        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
317
 
        align.show()
318
 
        label.show()
319
 
 
320
 
        align = gtk.Alignment(0.0, 0.5)
321
106
        self.committer = gtk.Label()
322
107
        self.committer.set_selectable(True)
323
108
        align.add(self.committer)
324
 
        self.table.attach(align, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
 
109
        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
325
110
        align.show()
326
111
        self.committer.show()
327
112
 
328
 
        align = gtk.Alignment(0.0, 0.5)
329
 
        label = gtk.Label()
330
 
        label.set_markup("<b>Branch nick:</b>")
331
 
        align.add(label)
332
 
        self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
333
 
        label.show()
334
 
        align.show()
335
 
 
336
 
        align = gtk.Alignment(0.0, 0.5)
337
 
        self.branchnick_label = gtk.Label()
338
 
        self.branchnick_label.set_selectable(True)
339
 
        align.add(self.branchnick_label)
340
 
        self.table.attach(align, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
341
 
        self.branchnick_label.show()
342
 
        align.show()
343
 
 
344
113
        align = gtk.Alignment(1.0, 0.5)
345
114
        label = gtk.Label()
346
115
        label.set_markup("<b>Timestamp:</b>")
347
116
        align.add(label)
348
 
        self.table.attach(align, 0, 1, 4, 5, gtk.FILL, gtk.FILL)
 
117
        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
349
118
        align.show()
350
119
        label.show()
351
120
 
353
122
        self.timestamp = gtk.Label()
354
123
        self.timestamp.set_selectable(True)
355
124
        align.add(self.timestamp)
356
 
        self.table.attach(align, 1, 2, 4, 5, gtk.EXPAND | gtk.FILL, gtk.FILL)
 
125
        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
357
126
        align.show()
358
127
        self.timestamp.show()
359
128
 
360
129
        align = gtk.Alignment(1.0, 0.5)
361
 
        self.tags_label = gtk.Label()
362
 
        self.tags_label.set_markup("<b>Tags:</b>")
363
 
        align.add(self.tags_label)
 
130
        label = gtk.Label()
 
131
        label.set_markup("<b>Revision Id:</b>")
 
132
        align.add(label)
 
133
        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
364
134
        align.show()
365
 
        self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
366
 
        self.tags_label.show()
 
135
        label.show()
367
136
 
368
137
        align = gtk.Alignment(0.0, 0.5)
369
 
        self.tags_list = gtk.Label()
370
 
        align.add(self.tags_list)
371
 
        self.table.attach(align, 1, 2, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL)
 
138
        self.revision_id = gtk.Label()
 
139
        self.revision_id.set_selectable(True)
 
140
        align.add(self.revision_id)
 
141
        self.table.attach(align, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
372
142
        align.show()
373
 
        self.tags_list.show()
374
 
 
375
 
        self.connect('notify::revision', self._add_tags)
 
143
        self.revision_id.show()
376
144
 
377
145
        return self.table
378
146
 
379
 
    
380
 
    def _create_parents(self):
381
 
        hbox = gtk.HBox(True, 3)
382
 
        
383
 
        self.parents_table = self._create_parents_or_children_table(
384
 
            "<b>Parents:</b>")
385
 
        self.parents_widgets = []
386
 
        hbox.pack_start(self.parents_table)
387
 
 
388
 
        hbox.show()
389
 
        return hbox
390
 
 
391
 
    def _create_children(self):
392
 
        hbox = gtk.HBox(True, 3)
393
 
        self.children_table = self._create_parents_or_children_table(
394
 
            "<b>Children:</b>")
395
 
        self.children_widgets = []
396
 
        hbox.pack_start(self.children_table)
397
 
        hbox.show()
398
 
        return hbox
399
 
        
400
 
    def _create_parents_or_children_table(self, text):
401
 
        table = gtk.Table(rows=1, columns=2)
402
 
        table.set_row_spacings(3)
403
 
        table.set_col_spacings(6)
404
 
        table.show()
405
 
 
406
 
        label = gtk.Label()
407
 
        label.set_markup(text)
408
 
        align = gtk.Alignment(0.0, 0.5)
409
 
        align.add(label)
410
 
        table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
411
 
        label.show()
412
 
        align.show()
413
 
 
414
 
        return table
415
 
 
416
147
    def _create_message_view(self):
417
 
        msg_buffer = gtk.TextBuffer()
418
 
        self.connect('notify::revision',
419
 
                lambda w, p: msg_buffer.set_text(self._revision.message))
420
 
        window = gtk.ScrolledWindow()
421
 
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
422
 
        window.set_shadow_type(gtk.SHADOW_IN)
423
 
        tv = gtk.TextView(msg_buffer)
424
 
        tv.set_editable(False)
425
 
        tv.set_wrap_mode(gtk.WRAP_WORD)
426
 
        tv.modify_font(pango.FontDescription("Monospace"))
427
 
        tv.show()
428
 
        window.add(tv)
429
 
        window.show()
430
 
        return window
431
 
 
432
 
    def _create_file_info_view(self):
433
 
        self.file_info_box = gtk.VBox(False, 6)
434
 
        self.file_info_box.set_border_width(6)
435
 
        self.file_info_buffer = gtk.TextBuffer()
436
 
        window = gtk.ScrolledWindow()
437
 
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
438
 
        window.set_shadow_type(gtk.SHADOW_IN)
439
 
        tv = gtk.TextView(self.file_info_buffer)
440
 
        tv.set_editable(False)
441
 
        tv.set_wrap_mode(gtk.WRAP_WORD)
442
 
        tv.modify_font(pango.FontDescription("Monospace"))
443
 
        tv.show()
444
 
        window.add(tv)
445
 
        window.show()
446
 
        self.file_info_box.pack_start(window)
447
 
        self.file_info_box.hide() # Only shown when there are per-file messages
448
 
        self.append_page(self.file_info_box, tab_label=gtk.Label('Per-file'))
 
148
        self.message_buffer = gtk.TextBuffer()
 
149
        tv = gtk.TextView(self.message_buffer)
 
150
        tv.set_editable(False)
 
151
        tv.set_wrap_mode(gtk.WRAP_WORD)
 
152
        tv.modify_font(pango.FontDescription("Monospace"))
 
153
        tv.show()
 
154
        return tv
449
155