/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
 
import webbrowser
24
21
 
25
 
from bzrlib.plugins.gtk import icon_path
26
22
from bzrlib.osutils import format_date
27
 
from bzrlib.util.bencode import bdecode
28
 
 
29
 
try:
30
 
    from bzrlib.plugins.gtk import seahorse
31
 
except ImportError:
32
 
    has_seahorse = False
33
 
else:
34
 
    has_seahorse = True
35
 
 
36
 
PAGE_GENERAL = 0
37
 
PAGE_RELATIONS = 1
38
 
PAGE_SIGNATURE = 2
39
 
PAGE_BUGS = 3
40
 
 
41
 
 
42
 
def _open_link(widget, uri):
43
 
    for cmd in ['sensible-browser', 'xdg-open']:
44
 
        if webbrowser._iscommand(cmd):
45
 
            webbrowser._tryorder.insert(0, '%s "%%s"' % cmd)
46
 
    webbrowser.open(uri)
47
 
 
48
 
gtk.link_button_set_uri_hook(_open_link)
49
 
 
50
 
class BugsTab(gtk.VBox):
51
 
 
52
 
    def __init__(self):
53
 
        super(BugsTab, self).__init__(False, 6)
54
 
    
55
 
        table = gtk.Table(rows=2, columns=2)
56
 
 
57
 
        table.set_row_spacings(6)
58
 
        table.set_col_spacing(0, 16)
59
 
 
60
 
        image = gtk.Image()
61
 
        image.set_from_file(icon_path("bug.png"))
62
 
        table.attach(image, 0, 1, 0, 1, gtk.FILL)
63
 
 
64
 
        align = gtk.Alignment(0.0, 0.1)
65
 
        self.label = gtk.Label()
66
 
        align.add(self.label)
67
 
        table.attach(align, 1, 2, 0, 1, gtk.FILL)
68
 
 
69
 
        treeview = self.construct_treeview()
70
 
        table.attach(treeview, 1, 2, 1, 2, gtk.FILL | gtk.EXPAND)
71
 
 
72
 
        self.set_border_width(6)
73
 
        self.pack_start(table, expand=False)
74
 
 
75
 
        self.clear()
76
 
        self.show_all()
77
 
 
78
 
    def set_revision(self, revision):
79
 
        if revision is None:
80
 
            return
81
 
 
82
 
        self.clear()
83
 
        bugs_text = revision.properties.get('bugs', '')
84
 
        for bugline in bugs_text.splitlines():
85
 
                (url, status) = bugline.split(" ")
86
 
                if status == "fixed":
87
 
                    self.add_bug(url, status)
88
 
        
89
 
        if self.num_bugs == 0:
90
 
            return
91
 
        elif self.num_bugs == 1:
92
 
            label = "bug"
93
 
        else:
94
 
            label = "bugs"
95
 
 
96
 
        self.label.set_markup("<b>Bugs fixed</b>\n" +
97
 
                              "This revision claims to fix " +
98
 
                              "%d %s." % (self.num_bugs, label))
99
 
 
100
 
    def construct_treeview(self):
101
 
        self.bugs = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
102
 
        self.treeview = gtk.TreeView(self.bugs)
103
 
        self.treeview.set_headers_visible(False)
104
 
 
105
 
        uri_column = gtk.TreeViewColumn('Bug URI', gtk.CellRendererText(), text=0)
106
 
        self.treeview.append_column(uri_column)
107
 
 
108
 
        self.treeview.connect('row-activated', self.on_row_activated)
109
 
 
110
 
        win = gtk.ScrolledWindow()
111
 
        win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
112
 
        win.set_shadow_type(gtk.SHADOW_IN)
113
 
        win.add(self.treeview)
114
 
 
115
 
        return win
116
 
 
117
 
    def clear(self):
118
 
        self.num_bugs = 0
119
 
        self.bugs.clear()
120
 
        self.set_sensitive(False)
121
 
        self.label.set_markup("<b>No bugs fixed</b>\n" +
122
 
                              "This revision does not claim to fix any bugs.")
123
 
 
124
 
    def add_bug(self, url, status):
125
 
        self.num_bugs += 1
126
 
        self.bugs.append([url, status])
127
 
        self.set_sensitive(True)
128
 
 
129
 
    def get_num_bugs(self):
130
 
        return self.num_bugs
131
 
 
132
 
    def on_row_activated(self, treeview, path, column):
133
 
        uri = self.bugs.get_value(self.bugs.get_iter(path), 0)
134
 
        _open_link(self, uri)
135
 
 
136
 
 
137
 
class SignatureTab(gtk.VBox):
138
 
 
139
 
    def __init__(self, repository):
140
 
        self.key = None
141
 
        self.revision = None
142
 
        self.repository = repository
143
 
 
144
 
        super(SignatureTab, self).__init__(False, 6)
145
 
        signature_box = gtk.Table(rows=3, columns=3)
146
 
        signature_box.set_col_spacing(0, 16)
147
 
        signature_box.set_col_spacing(1, 12)
148
 
        signature_box.set_row_spacings(6)
149
 
 
150
 
        self.signature_image = gtk.Image()
151
 
        signature_box.attach(self.signature_image, 0, 1, 0, 1, gtk.FILL)
152
 
 
153
 
        align = gtk.Alignment(0.0, 0.1)
154
 
        self.signature_label = gtk.Label()
155
 
        align.add(self.signature_label)
156
 
        signature_box.attach(align, 1, 3, 0, 1, gtk.FILL)
157
 
 
158
 
        align = gtk.Alignment(0.0, 0.5)
159
 
        self.signature_key_id_label = gtk.Label()
160
 
        self.signature_key_id_label.set_markup("<b>Key Id:</b>")
161
 
        align.add(self.signature_key_id_label)
162
 
        signature_box.attach(align, 1, 2, 1, 2, gtk.FILL, gtk.FILL)
163
 
 
164
 
        align = gtk.Alignment(0.0, 0.5)
165
 
        self.signature_key_id = gtk.Label()
166
 
        self.signature_key_id.set_selectable(True)
167
 
        align.add(self.signature_key_id)
168
 
        signature_box.attach(align, 2, 3, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
169
 
 
170
 
        align = gtk.Alignment(0.0, 0.5)
171
 
        self.signature_fingerprint_label = gtk.Label()
172
 
        self.signature_fingerprint_label.set_markup("<b>Fingerprint:</b>")
173
 
        align.add(self.signature_fingerprint_label)
174
 
        signature_box.attach(align, 1, 2, 2, 3, gtk.FILL, gtk.FILL)
175
 
 
176
 
        align = gtk.Alignment(0.0, 0.5)
177
 
        self.signature_fingerprint = gtk.Label()
178
 
        self.signature_fingerprint.set_selectable(True)
179
 
        align.add(self.signature_fingerprint)
180
 
        signature_box.attach(align, 2, 3, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
181
 
 
182
 
        align = gtk.Alignment(0.0, 0.5)
183
 
        self.signature_trust_label = gtk.Label()
184
 
        self.signature_trust_label.set_markup("<b>Trust:</b>")
185
 
        align.add(self.signature_trust_label)
186
 
        signature_box.attach(align, 1, 2, 3, 4, gtk.FILL, gtk.FILL)
187
 
 
188
 
        align = gtk.Alignment(0.0, 0.5)
189
 
        self.signature_trust = gtk.Label()
190
 
        self.signature_trust.set_selectable(True)
191
 
        align.add(self.signature_trust)
192
 
        signature_box.attach(align, 2, 3, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
193
 
 
194
 
        self.set_border_width(6)
195
 
        self.pack_start(signature_box, expand=False)
196
 
        self.show_all()
197
 
 
198
 
    def set_revision(self, revision):
199
 
        self.revision = revision
200
 
        revid = revision.revision_id
201
 
 
202
 
        if self.repository.has_signature_for_revision_id(revid):
203
 
            crypttext = self.repository.get_signature_text(revid)
204
 
            self.show_signature(crypttext)
205
 
        else:
206
 
            self.show_no_signature()
207
 
 
208
 
    def show_no_signature(self):
209
 
        self.signature_key_id_label.hide()
210
 
        self.signature_key_id.set_text("")
211
 
 
212
 
        self.signature_fingerprint_label.hide()
213
 
        self.signature_fingerprint.set_text("")
214
 
 
215
 
        self.signature_trust_label.hide()
216
 
        self.signature_trust.set_text("")
217
 
 
218
 
        self.signature_image.set_from_file(icon_path("sign-unknown.png"))
219
 
        self.signature_label.set_markup("<b>Authenticity unknown</b>\n" +
220
 
                                        "This revision has not been signed.")
221
 
 
222
 
    def show_signature(self, crypttext):
223
 
        key = seahorse.verify(crypttext)
224
 
 
225
 
        if key and key.is_available():
226
 
            if key.is_trusted():
227
 
                if key.get_display_name() == self.revision.committer:
228
 
                    self.signature_image.set_from_file(icon_path("sign-ok.png"))
229
 
                    self.signature_label.set_markup("<b>Authenticity confirmed</b>\n" +
230
 
                                                    "This revision has been signed with " +
231
 
                                                    "a trusted key.")
232
 
                else:
233
 
                    self.signature_image.set_from_file(icon_path("sign-bad.png"))
234
 
                    self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
235
 
                                                    "Revision committer is not the same as signer.")
236
 
            else:
237
 
                self.signature_image.set_from_file(icon_path("sign-bad.png"))
238
 
                self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
239
 
                                                "This revision has been signed, but the " +
240
 
                                                "key is not trusted.")
241
 
        else:
242
 
            self.show_no_signature()
243
 
            self.signature_image.set_from_file(icon_path("sign-bad.png"))
244
 
            self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
245
 
                                            "Signature key not available.")
246
 
            return
247
 
 
248
 
        trust = key.get_trust()
249
 
 
250
 
        if trust <= seahorse.TRUST_NEVER:
251
 
            trust_text = 'never trusted'
252
 
        elif trust == seahorse.TRUST_UNKNOWN:
253
 
            trust_text = 'not trusted'
254
 
        elif trust == seahorse.TRUST_MARGINAL:
255
 
            trust_text = 'marginally trusted'
256
 
        elif trust == seahorse.TRUST_FULL:
257
 
            trust_text = 'fully trusted'
258
 
        elif trust == seahorse.TRUST_ULTIMATE:
259
 
            trust_text = 'ultimately trusted'
260
 
 
261
 
        self.signature_key_id_label.show()
262
 
        self.signature_key_id.set_text(key.get_id())
263
 
 
264
 
        fingerprint = key.get_fingerprint()
265
 
        if fingerprint == "":
266
 
            fingerprint = '<span foreground="dim grey">N/A</span>'
267
 
 
268
 
        self.signature_fingerprint_label.show()
269
 
        self.signature_fingerprint.set_markup(fingerprint)
270
 
 
271
 
        self.signature_trust_label.show()
272
 
        self.signature_trust.set_text('This key is ' + trust_text)
273
 
 
274
 
 
275
 
class RevisionView(gtk.Notebook):
 
23
 
 
24
 
 
25
class LogView(gtk.ScrolledWindow):
276
26
    """ Custom widget for commit log details.
277
27
 
278
28
    A variety of bzr tools may need to implement such a thing. This is a
279
29
    start.
280
30
    """
281
31
 
282
 
    __gproperties__ = {
283
 
        'branch': (
284
 
            gobject.TYPE_PYOBJECT,
285
 
            'Branch',
286
 
            'The branch holding the revision being displayed',
287
 
            gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE
288
 
        ),
289
 
 
290
 
        'revision': (
291
 
            gobject.TYPE_PYOBJECT,
292
 
            'Revision',
293
 
            'The revision being displayed',
294
 
            gobject.PARAM_READWRITE
295
 
        ),
296
 
 
297
 
        'children': (
298
 
            gobject.TYPE_PYOBJECT,
299
 
            'Children',
300
 
            'Child revisions',
301
 
            gobject.PARAM_READWRITE
302
 
        ),
303
 
 
304
 
        'file-id': (
305
 
            gobject.TYPE_PYOBJECT,
306
 
            'File Id',
307
 
            'The file id',
308
 
            gobject.PARAM_READWRITE
309
 
        )
310
 
    }
311
 
 
312
 
    def __init__(self, branch=None, repository=None):
313
 
        gtk.Notebook.__init__(self)
314
 
 
315
 
        self._revision = None
316
 
        self._branch = branch
317
 
        if branch is not None:
318
 
            self._repository = branch.repository
319
 
        else:
320
 
            self._repository = repository
321
 
 
322
 
        self._create_general()
323
 
        self._create_relations()
324
 
        # Disabled because testaments aren't verified yet:
325
 
        # if has_seahorse:
326
 
        #    self._create_signature()
327
 
        self._create_file_info_view()
328
 
        self._create_bugs()
329
 
 
330
 
        self.set_current_page(PAGE_GENERAL)
331
 
        self.connect_after('switch-page', self._switch_page_cb)
332
 
        
333
 
        self._show_callback = None
334
 
        self._clicked_callback = None
335
 
 
336
 
        self._revision = None
337
 
        self._branch = branch
338
 
 
339
 
        self.update_tags()
340
 
 
341
 
        self.set_file_id(None)
342
 
 
343
 
    def do_get_property(self, property):
344
 
        if property.name == 'branch':
345
 
            return self._branch
346
 
        elif property.name == 'revision':
347
 
            return self._revision
348
 
        elif property.name == 'children':
349
 
            return self._children
350
 
        elif property.name == 'file-id':
351
 
            return self._file_id
352
 
        else:
353
 
            raise AttributeError, 'unknown property %s' % property.name
354
 
 
355
 
    def do_set_property(self, property, value):
356
 
        if property.name == 'branch':
357
 
            self._branch = value
358
 
        elif property.name == 'revision':
359
 
            self._set_revision(value)
360
 
        elif property.name == 'children':
361
 
            self.set_children(value)
362
 
        elif property.name == 'file-id':
363
 
            self._file_id = value
364
 
        else:
365
 
            raise AttributeError, 'unknown property %s' % property.name
366
 
 
367
 
    def set_show_callback(self, callback):
368
 
        self._show_callback = callback
369
 
 
370
 
    def set_file_id(self, file_id):
371
 
        """Set a specific file id that we want to track.
372
 
 
373
 
        This just effects the display of a per-file commit message.
374
 
        If it is set to None, then all commit messages will be shown.
375
 
        """
376
 
        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)
377
41
 
378
42
    def set_revision(self, revision):
379
 
        if revision != self._revision:
380
 
            self.set_property('revision', revision)
381
 
 
382
 
    def get_revision(self):
383
 
        return self.get_property('revision')
384
 
 
385
 
    def _set_revision(self, revision):
386
 
        if revision is None: return
387
 
 
388
 
        self._revision = revision
389
 
        if revision.committer is not None:
390
 
            self.committer.set_text(revision.committer)
391
 
        else:
392
 
            self.committer.set_text("")
393
 
        author = revision.properties.get('author', '')
394
 
        if author != '':
395
 
            self.author.set_text(author)
396
 
            self.author.show()
397
 
            self.author_label.show()
398
 
        else:
399
 
            self.author.hide()
400
 
            self.author_label.hide()
401
 
 
402
 
        if revision.timestamp is not None:
403
 
            self.timestamp.set_text(format_date(revision.timestamp,
404
 
                                                revision.timezone))
405
 
        try:
406
 
            self.branchnick_label.set_text(revision.properties['branch-nick'])
407
 
        except KeyError:
408
 
            self.branchnick_label.set_text("")
409
 
 
410
 
        self._add_parents_or_children(revision.parent_ids,
411
 
                                      self.parents_widgets,
412
 
                                      self.parents_table)
413
 
        
414
 
        file_info = revision.properties.get('file-info', None)
415
 
        if file_info is not None:
416
 
            file_info = bdecode(file_info.encode('UTF-8'))
417
 
 
418
 
        if file_info:
419
 
            if self._file_id is None:
420
 
                text = []
421
 
                for fi in file_info:
422
 
                    text.append('%(path)s\n%(message)s' % fi)
423
 
                self.file_info_buffer.set_text('\n'.join(text))
424
 
                self.file_info_box.show()
425
 
            else:
426
 
                text = []
427
 
                for fi in file_info:
428
 
                    if fi['file_id'] == self._file_id:
429
 
                        text.append(fi['message'])
430
 
                if text:
431
 
                    self.file_info_buffer.set_text('\n'.join(text))
432
 
                    self.file_info_box.show()
433
 
                else:
434
 
                    self.file_info_box.hide()
435
 
        else:
436
 
            self.file_info_box.hide()
437
 
 
438
 
    def update_tags(self):
439
 
        if self._branch is not None and self._branch.supports_tags():
440
 
            self._tagdict = self._branch.tags.get_reverse_tag_dict()
441
 
        else:
442
 
            self._tagdict = {}
443
 
 
444
 
        self._add_tags()
445
 
 
446
 
    def _update_signature(self, widget, param):
447
 
        if self.get_current_page() == PAGE_SIGNATURE:
448
 
            self.signature_table.set_revision(self._revision)
449
 
 
450
 
    def _update_bugs(self, widget, param):
451
 
        self.bugs_page.set_revision(self._revision)
452
 
        label = self.get_tab_label(self.bugs_page)
453
 
        label.set_sensitive(self.bugs_page.get_num_bugs() != 0)
454
 
 
455
 
    def set_children(self, children):
456
 
        self._add_parents_or_children(children,
457
 
                                      self.children_widgets,
458
 
                                      self.children_table)
459
 
 
460
 
    def _switch_page_cb(self, notebook, page, page_num):
461
 
        if page_num == PAGE_SIGNATURE:
462
 
            self.signature_table.set_revision(self._revision)
463
 
 
464
 
 
465
 
 
466
 
    def _show_clicked_cb(self, widget, revid, parentid):
467
 
        """Callback for when the show button for a parent is clicked."""
468
 
        self._show_callback(revid, parentid)
469
 
 
470
 
    def _go_clicked_cb(self, widget, revid):
471
 
        """Callback for when the go button for a parent is clicked."""
472
 
 
473
 
    def _add_tags(self, *args):
474
 
        if self._revision is None:
475
 
            return
476
 
 
477
 
        if self._tagdict.has_key(self._revision.revision_id):
478
 
            tags = self._tagdict[self._revision.revision_id]
479
 
        else:
480
 
            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)
481
53
            
482
 
        if tags == []:
483
 
            self.tags_list.hide()
484
 
            self.tags_label.hide()
485
 
            return
486
 
 
487
 
        self.tags_list.set_text(", ".join(tags))
488
 
 
489
 
        self.tags_list.show_all()
490
 
        self.tags_label.show_all()
491
 
        
492
 
    def _add_parents_or_children(self, revids, widgets, table):
493
 
        while len(widgets) > 0:
494
 
            widget = widgets.pop()
495
 
            table.remove(widget)
496
 
        
497
 
        table.resize(max(len(revids), 1), 2)
498
 
 
499
 
        for idx, revid in enumerate(revids):
500
 
            align = gtk.Alignment(0.0, 0.0)
501
 
            widgets.append(align)
502
 
            table.attach(align, 1, 2, idx, idx + 1,
503
 
                                      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)
504
60
            align.show()
505
 
 
506
 
            hbox = gtk.HBox(False, spacing=6)
507
 
            align.add(hbox)
508
 
            hbox.show()
509
 
 
510
 
            image = gtk.Image()
511
 
            image.set_from_stock(
512
 
                gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)
513
 
            image.show()
514
 
 
515
 
            if self._show_callback is not None:
516
 
                button = gtk.Button()
517
 
                button.add(image)
518
 
                button.connect("clicked", self._show_clicked_cb,
519
 
                               self._revision.revision_id, revid)
520
 
                hbox.pack_start(button, expand=False, fill=True)
521
 
                button.show()
522
 
 
523
 
            button = gtk.Button(revid)
524
 
            button.connect("clicked",
525
 
                    lambda w, r: self.set_revision(self._repository.get_revision(r)), revid)
526
 
            button.set_use_underline(False)
527
 
            hbox.pack_start(button, expand=False, fill=True)
528
 
            button.show()
529
 
 
530
 
    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):
531
84
        vbox = gtk.VBox(False, 6)
532
85
        vbox.set_border_width(6)
533
86
        vbox.pack_start(self._create_headers(), expand=False, fill=True)
534
87
        vbox.pack_start(self._create_message_view())
535
 
        self.append_page(vbox, tab_label=gtk.Label("General"))
536
 
        vbox.show()
537
 
 
538
 
    def _create_relations(self):
539
 
        vbox = gtk.VBox(False, 6)
540
 
        vbox.set_border_width(6)
541
 
        vbox.pack_start(self._create_parents(), expand=False, fill=True)
542
 
        vbox.pack_start(self._create_children(), expand=False, fill=True)
543
 
        self.append_page(vbox, tab_label=gtk.Label("Relations"))
544
 
        vbox.show()
545
 
 
546
 
    def _create_signature(self):
547
 
        self.signature_table = SignatureTab(self._repository)
548
 
        self.append_page(self.signature_table, tab_label=gtk.Label('Signature'))
549
 
        self.connect_after('notify::revision', self._update_signature)
 
88
        self.add_with_viewport(vbox)
 
89
        vbox.show()
550
90
 
551
91
    def _create_headers(self):
552
 
        self.table = gtk.Table(rows=5, columns=2)
 
92
        self.table = gtk.Table(rows=4, columns=2)
553
93
        self.table.set_row_spacings(6)
554
94
        self.table.set_col_spacings(6)
555
95
        self.table.show()
556
 
 
 
96
        
557
97
        align = gtk.Alignment(1.0, 0.5)
558
98
        label = gtk.Label()
559
 
        label.set_markup("<b>Revision Id:</b>")
 
99
        label.set_markup("<b>Committer:</b>")
560
100
        align.add(label)
561
101
        self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
562
102
        align.show()
563
103
        label.show()
564
104
 
565
105
        align = gtk.Alignment(0.0, 0.5)
566
 
        revision_id = gtk.Label()
567
 
        revision_id.set_selectable(True)
568
 
        self.connect('notify::revision', 
569
 
                lambda w, p: revision_id.set_text(self._revision.revision_id))
570
 
        align.add(revision_id)
571
 
        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
572
 
        align.show()
573
 
        revision_id.show()
574
 
 
575
 
        align = gtk.Alignment(1.0, 0.5)
576
 
        self.author_label = gtk.Label()
577
 
        self.author_label.set_markup("<b>Author:</b>")
578
 
        align.add(self.author_label)
579
 
        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
580
 
        align.show()
581
 
        self.author_label.show()
582
 
 
583
 
        align = gtk.Alignment(0.0, 0.5)
584
 
        self.author = gtk.Label()
585
 
        self.author.set_selectable(True)
586
 
        align.add(self.author)
587
 
        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
588
 
        align.show()
589
 
        self.author.show()
590
 
        self.author.hide()
591
 
 
592
 
        align = gtk.Alignment(1.0, 0.5)
593
 
        label = gtk.Label()
594
 
        label.set_markup("<b>Committer:</b>")
595
 
        align.add(label)
596
 
        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
597
 
        align.show()
598
 
        label.show()
599
 
 
600
 
        align = gtk.Alignment(0.0, 0.5)
601
106
        self.committer = gtk.Label()
602
107
        self.committer.set_selectable(True)
603
108
        align.add(self.committer)
604
 
        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)
605
110
        align.show()
606
111
        self.committer.show()
607
112
 
608
 
        align = gtk.Alignment(0.0, 0.5)
609
 
        label = gtk.Label()
610
 
        label.set_markup("<b>Branch nick:</b>")
611
 
        align.add(label)
612
 
        self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
613
 
        label.show()
614
 
        align.show()
615
 
 
616
 
        align = gtk.Alignment(0.0, 0.5)
617
 
        self.branchnick_label = gtk.Label()
618
 
        self.branchnick_label.set_selectable(True)
619
 
        align.add(self.branchnick_label)
620
 
        self.table.attach(align, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
621
 
        self.branchnick_label.show()
622
 
        align.show()
623
 
 
624
113
        align = gtk.Alignment(1.0, 0.5)
625
114
        label = gtk.Label()
626
115
        label.set_markup("<b>Timestamp:</b>")
627
116
        align.add(label)
628
 
        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)
629
118
        align.show()
630
119
        label.show()
631
120
 
633
122
        self.timestamp = gtk.Label()
634
123
        self.timestamp.set_selectable(True)
635
124
        align.add(self.timestamp)
636
 
        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)
637
126
        align.show()
638
127
        self.timestamp.show()
639
128
 
640
129
        align = gtk.Alignment(1.0, 0.5)
641
 
        self.tags_label = gtk.Label()
642
 
        self.tags_label.set_markup("<b>Tags:</b>")
643
 
        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)
644
134
        align.show()
645
 
        self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
646
 
        self.tags_label.show()
 
135
        label.show()
647
136
 
648
137
        align = gtk.Alignment(0.0, 0.5)
649
 
        self.tags_list = gtk.Label()
650
 
        align.add(self.tags_list)
651
 
        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)
652
142
        align.show()
653
 
        self.tags_list.show()
654
 
 
655
 
        self.connect('notify::revision', self._add_tags)
 
143
        self.revision_id.show()
656
144
 
657
145
        return self.table
658
 
    
659
 
    def _create_parents(self):
660
 
        hbox = gtk.HBox(True, 3)
661
 
        
662
 
        self.parents_table = self._create_parents_or_children_table(
663
 
            "<b>Parents:</b>")
664
 
        self.parents_widgets = []
665
 
        hbox.pack_start(self.parents_table)
666
 
 
667
 
        hbox.show()
668
 
        return hbox
669
 
 
670
 
    def _create_children(self):
671
 
        hbox = gtk.HBox(True, 3)
672
 
        self.children_table = self._create_parents_or_children_table(
673
 
            "<b>Children:</b>")
674
 
        self.children_widgets = []
675
 
        hbox.pack_start(self.children_table)
676
 
        hbox.show()
677
 
        return hbox
678
 
        
679
 
    def _create_parents_or_children_table(self, text):
680
 
        table = gtk.Table(rows=1, columns=2)
681
 
        table.set_row_spacings(3)
682
 
        table.set_col_spacings(6)
683
 
        table.show()
684
 
 
685
 
        label = gtk.Label()
686
 
        label.set_markup(text)
687
 
        align = gtk.Alignment(0.0, 0.5)
688
 
        align.add(label)
689
 
        table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
690
 
        label.show()
691
 
        align.show()
692
 
 
693
 
        return table
694
146
 
695
147
    def _create_message_view(self):
696
 
        msg_buffer = gtk.TextBuffer()
697
 
        self.connect('notify::revision',
698
 
                lambda w, p: msg_buffer.set_text(self._revision.message))
699
 
        window = gtk.ScrolledWindow()
700
 
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
701
 
        window.set_shadow_type(gtk.SHADOW_IN)
702
 
        tv = gtk.TextView(msg_buffer)
703
 
        tv.set_editable(False)
704
 
        tv.set_wrap_mode(gtk.WRAP_WORD)
705
 
 
706
 
        tv.modify_font(pango.FontDescription("Monospace"))
707
 
        tv.show()
708
 
        window.add(tv)
709
 
        window.show()
710
 
        return window
711
 
 
712
 
    def _create_bugs(self):
713
 
        self.bugs_page = BugsTab()
714
 
        self.connect_after('notify::revision', self._update_bugs) 
715
 
        self.append_page(self.bugs_page, tab_label=gtk.Label('Bugs'))
716
 
 
717
 
    def _create_file_info_view(self):
718
 
        self.file_info_box = gtk.VBox(False, 6)
719
 
        self.file_info_box.set_border_width(6)
720
 
        self.file_info_buffer = gtk.TextBuffer()
721
 
        window = gtk.ScrolledWindow()
722
 
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
723
 
        window.set_shadow_type(gtk.SHADOW_IN)
724
 
        tv = gtk.TextView(self.file_info_buffer)
725
 
        tv.set_editable(False)
726
 
        tv.set_wrap_mode(gtk.WRAP_WORD)
727
 
        tv.modify_font(pango.FontDescription("Monospace"))
728
 
        tv.show()
729
 
        window.add(tv)
730
 
        window.show()
731
 
        self.file_info_box.pack_start(window)
732
 
        self.file_info_box.hide() # Only shown when there are per-file messages
733
 
        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
734
155