/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 revisionview.py

  • Committer: Jelmer Vernooij
  • Date: 2008-06-29 18:12:29 UTC
  • mto: This revision was merged to the branch mainline in revision 519.
  • Revision ID: jelmer@samba.org-20080629181229-1l2m4cf7vvbyh8qg
Simplify progress bar code, use embedded progress bar inside viz window.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
17
 
18
 
from gi.repository import Gtk
19
 
from gi.repository import Pango
20
 
from gi.repository import GObject
 
18
import pygtk
 
19
pygtk.require("2.0")
 
20
import gtk
 
21
import pango
 
22
import gobject
21
23
import webbrowser
22
24
 
23
 
from bzrlib import trace
 
25
from bzrlib.plugins.gtk import icon_path
24
26
from bzrlib.osutils import format_date
25
 
from bzrlib.bencode import bdecode
26
 
from bzrlib.testament import Testament
27
 
 
28
 
from bzrlib.plugins.gtk import icon_path
29
 
 
30
 
from bzrlib.plugins.gtk.avatarsbox import AvatarsBox
 
27
from bzrlib.util.bencode import bdecode
31
28
 
32
29
try:
33
30
    from bzrlib.plugins.gtk import seahorse
48
45
            webbrowser._tryorder.insert(0, '%s "%%s"' % cmd)
49
46
    webbrowser.open(uri)
50
47
 
 
48
gtk.link_button_set_uri_hook(_open_link)
51
49
 
52
 
class BugsTab(Gtk.VBox):
 
50
class BugsTab(gtk.VBox):
53
51
 
54
52
    def __init__(self):
55
 
        super(BugsTab, self).__init__(homogeneous=False, spacing=6)
56
 
 
57
 
        table = Gtk.Table(rows=2, columns=2)
 
53
        super(BugsTab, self).__init__(False, 6)
 
54
    
 
55
        table = gtk.Table(rows=2, columns=2)
58
56
 
59
57
        table.set_row_spacings(6)
60
58
        table.set_col_spacing(0, 16)
61
59
 
62
 
        image = Gtk.Image()
 
60
        image = gtk.Image()
63
61
        image.set_from_file(icon_path("bug.png"))
64
 
        table.attach(image, 0, 1, 0, 1, Gtk.AttachOptions.FILL)
 
62
        table.attach(image, 0, 1, 0, 1, gtk.FILL)
65
63
 
66
 
        align = Gtk.Alignment.new(0.0, 0.1, 0, 0)
67
 
        self.label = Gtk.Label()
 
64
        align = gtk.Alignment(0.0, 0.1)
 
65
        self.label = gtk.Label()
68
66
        align.add(self.label)
69
 
        table.attach(align, 1, 2, 0, 1, Gtk.AttachOptions.FILL)
 
67
        table.attach(align, 1, 2, 0, 1, gtk.FILL)
70
68
 
71
69
        treeview = self.construct_treeview()
72
 
        table.attach(treeview, 1, 2, 1, 2, Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND)
 
70
        table.attach(treeview, 1, 2, 1, 2, gtk.FILL | gtk.EXPAND)
73
71
 
74
72
        self.set_border_width(6)
75
 
        self.pack_start(table, False, True, 0)
 
73
        self.pack_start(table, expand=False)
76
74
 
77
75
        self.clear()
78
76
        self.show_all()
87
85
                (url, status) = bugline.split(" ")
88
86
                if status == "fixed":
89
87
                    self.add_bug(url, status)
90
 
 
 
88
        
91
89
        if self.num_bugs == 0:
92
90
            return
93
91
        elif self.num_bugs == 1:
100
98
                              "%d %s." % (self.num_bugs, label))
101
99
 
102
100
    def construct_treeview(self):
103
 
        self.bugs = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING)
104
 
        self.treeview = Gtk.TreeView(model=self.bugs)
 
101
        self.bugs = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
 
102
        self.treeview = gtk.TreeView(self.bugs)
105
103
        self.treeview.set_headers_visible(False)
106
104
 
107
 
        uri_column = Gtk.TreeViewColumn('Bug URI', Gtk.CellRendererText(), text=0)
 
105
        uri_column = gtk.TreeViewColumn('Bug URI', gtk.CellRendererText(), text=0)
108
106
        self.treeview.append_column(uri_column)
109
107
 
110
108
        self.treeview.connect('row-activated', self.on_row_activated)
111
109
 
112
 
        win = Gtk.ScrolledWindow()
113
 
        win.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
114
 
        win.set_shadow_type(Gtk.ShadowType.IN)
 
110
        win = gtk.ScrolledWindow()
 
111
        win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
112
        win.set_shadow_type(gtk.SHADOW_IN)
115
113
        win.add(self.treeview)
116
114
 
117
115
        return win
136
134
        _open_link(self, uri)
137
135
 
138
136
 
139
 
class SignatureTab(Gtk.VBox):
 
137
class SignatureTab(gtk.VBox):
140
138
 
141
139
    def __init__(self, repository):
142
140
        self.key = None
143
141
        self.revision = None
144
142
        self.repository = repository
145
143
 
146
 
        super(SignatureTab, self).__init__(homogeneous=False, spacing=6)
147
 
        signature_box = Gtk.Table(rows=3, columns=3)
 
144
        super(SignatureTab, self).__init__(False, 6)
 
145
        signature_box = gtk.Table(rows=3, columns=3)
148
146
        signature_box.set_col_spacing(0, 16)
149
147
        signature_box.set_col_spacing(1, 12)
150
148
        signature_box.set_row_spacings(6)
151
149
 
152
 
        self.signature_image = Gtk.Image()
153
 
        signature_box.attach(self.signature_image, 0, 1, 0, 1, Gtk.AttachOptions.FILL)
 
150
        self.signature_image = gtk.Image()
 
151
        signature_box.attach(self.signature_image, 0, 1, 0, 1, gtk.FILL)
154
152
 
155
 
        align = Gtk.Alignment.new(0.0, 0.1, 0.0, 0.0)
156
 
        self.signature_label = Gtk.Label()
 
153
        align = gtk.Alignment(0.0, 0.1)
 
154
        self.signature_label = gtk.Label()
157
155
        align.add(self.signature_label)
158
 
        signature_box.attach(align, 1, 3, 0, 1, Gtk.AttachOptions.FILL)
 
156
        signature_box.attach(align, 1, 3, 0, 1, gtk.FILL)
159
157
 
160
 
        align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
161
 
        self.signature_key_id_label = Gtk.Label()
 
158
        align = gtk.Alignment(0.0, 0.5)
 
159
        self.signature_key_id_label = gtk.Label()
162
160
        self.signature_key_id_label.set_markup("<b>Key Id:</b>")
163
161
        align.add(self.signature_key_id_label)
164
 
        signature_box.attach(align, 1, 2, 1, 2, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
162
        signature_box.attach(align, 1, 2, 1, 2, gtk.FILL, gtk.FILL)
165
163
 
166
 
        align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
167
 
        self.signature_key_id = Gtk.Label()
 
164
        align = gtk.Alignment(0.0, 0.5)
 
165
        self.signature_key_id = gtk.Label()
168
166
        self.signature_key_id.set_selectable(True)
169
167
        align.add(self.signature_key_id)
170
 
        signature_box.attach(align, 2, 3, 1, 2, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
168
        signature_box.attach(align, 2, 3, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
171
169
 
172
 
        align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
173
 
        self.signature_fingerprint_label = Gtk.Label()
 
170
        align = gtk.Alignment(0.0, 0.5)
 
171
        self.signature_fingerprint_label = gtk.Label()
174
172
        self.signature_fingerprint_label.set_markup("<b>Fingerprint:</b>")
175
173
        align.add(self.signature_fingerprint_label)
176
 
        signature_box.attach(align, 1, 2, 2, 3, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
174
        signature_box.attach(align, 1, 2, 2, 3, gtk.FILL, gtk.FILL)
177
175
 
178
 
        align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
179
 
        self.signature_fingerprint = Gtk.Label()
 
176
        align = gtk.Alignment(0.0, 0.5)
 
177
        self.signature_fingerprint = gtk.Label()
180
178
        self.signature_fingerprint.set_selectable(True)
181
179
        align.add(self.signature_fingerprint)
182
 
        signature_box.attach(align, 2, 3, 2, 3, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
180
        signature_box.attach(align, 2, 3, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
183
181
 
184
 
        align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
185
 
        self.signature_trust_label = Gtk.Label()
 
182
        align = gtk.Alignment(0.0, 0.5)
 
183
        self.signature_trust_label = gtk.Label()
186
184
        self.signature_trust_label.set_markup("<b>Trust:</b>")
187
185
        align.add(self.signature_trust_label)
188
 
        signature_box.attach(align, 1, 2, 3, 4, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
186
        signature_box.attach(align, 1, 2, 3, 4, gtk.FILL, gtk.FILL)
189
187
 
190
 
        align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
191
 
        self.signature_trust = Gtk.Label()
 
188
        align = gtk.Alignment(0.0, 0.5)
 
189
        self.signature_trust = gtk.Label()
192
190
        self.signature_trust.set_selectable(True)
193
191
        align.add(self.signature_trust)
194
 
        signature_box.attach(align, 2, 3, 3, 4, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
192
        signature_box.attach(align, 2, 3, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
195
193
 
196
194
        self.set_border_width(6)
197
 
        self.pack_start(signature_box, False, True, 0)
 
195
        self.pack_start(signature_box, expand=False)
198
196
        self.show_all()
199
197
 
200
198
    def set_revision(self, revision):
222
220
                                        "This revision has not been signed.")
223
221
 
224
222
    def show_signature(self, crypttext):
225
 
        (cleartext, key) = seahorse.verify(crypttext)
226
 
 
227
 
        assert cleartext is not None
228
 
 
229
 
        inv = self.repository.get_inventory(self.revision.revision_id)
230
 
        expected_testament = Testament(self.revision, inv).as_short_text()
231
 
        if expected_testament != cleartext:
232
 
            self.signature_image.set_from_file(icon_path("sign-bad.png"))
233
 
            self.signature_label.set_markup("<b>Signature does not match repository data</b>\n" +
234
 
                        "The signature plaintext is different from the expected testament plaintext.")
235
 
            return
 
223
        key = seahorse.verify(crypttext)
236
224
 
237
225
        if key and key.is_available():
238
226
            if key.is_trusted():
284
272
        self.signature_trust.set_text('This key is ' + trust_text)
285
273
 
286
274
 
287
 
class RevisionView(Gtk.Notebook):
 
275
class RevisionView(gtk.Notebook):
288
276
    """ Custom widget for commit log details.
289
277
 
290
278
    A variety of bzr tools may need to implement such a thing. This is a
293
281
 
294
282
    __gproperties__ = {
295
283
        'branch': (
296
 
            GObject.TYPE_PYOBJECT,
 
284
            gobject.TYPE_PYOBJECT,
297
285
            'Branch',
298
286
            'The branch holding the revision being displayed',
299
 
            GObject.PARAM_CONSTRUCT_ONLY | GObject.PARAM_WRITABLE
 
287
            gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE
300
288
        ),
301
289
 
302
290
        'revision': (
303
 
            GObject.TYPE_PYOBJECT,
 
291
            gobject.TYPE_PYOBJECT,
304
292
            'Revision',
305
293
            'The revision being displayed',
306
 
            GObject.PARAM_READWRITE
 
294
            gobject.PARAM_READWRITE
307
295
        ),
308
296
 
309
297
        'children': (
310
 
            GObject.TYPE_PYOBJECT,
 
298
            gobject.TYPE_PYOBJECT,
311
299
            'Children',
312
300
            'Child revisions',
313
 
            GObject.PARAM_READWRITE
 
301
            gobject.PARAM_READWRITE
314
302
        ),
315
303
 
316
304
        'file-id': (
317
 
            GObject.TYPE_PYOBJECT,
 
305
            gobject.TYPE_PYOBJECT,
318
306
            'File Id',
319
307
            'The file id',
320
 
            GObject.PARAM_READWRITE
 
308
            gobject.PARAM_READWRITE
321
309
        )
322
310
    }
323
311
 
324
312
    def __init__(self, branch=None, repository=None):
325
 
        super(RevisionView, self).__init__()
 
313
        gtk.Notebook.__init__(self)
326
314
 
327
315
        self._revision = None
328
316
        self._branch = branch
330
318
            self._repository = branch.repository
331
319
        else:
332
320
            self._repository = repository
333
 
        self.signature_table = None
334
321
 
335
322
        self._create_general()
336
323
        self._create_relations()
337
324
        # Disabled because testaments aren't verified yet:
338
 
        if has_seahorse:
339
 
            self._create_signature()
 
325
        # if has_seahorse:
 
326
        #    self._create_signature()
340
327
        self._create_file_info_view()
341
328
        self._create_bugs()
342
329
 
397
384
 
398
385
    def _set_revision(self, revision):
399
386
        if revision is None: return
400
 
        
401
 
        self.avatarsbox.reset()
402
 
        
 
387
 
403
388
        self._revision = revision
404
389
        if revision.committer is not None:
405
390
            self.committer.set_text(revision.committer)
406
 
            self.avatarsbox.add(revision.committer, "committer")
407
391
        else:
408
392
            self.committer.set_text("")
409
 
            self.avatarsbox.hide()
410
393
        author = revision.properties.get('author', '')
411
 
        self.avatarsbox.merge(revision.get_apparent_authors(), "author")
412
394
        if author != '':
413
395
            self.author.set_text(author)
414
396
            self.author.show()
421
403
            self.timestamp.set_text(format_date(revision.timestamp,
422
404
                                                revision.timezone))
423
405
        try:
424
 
            self.branchnick.show()
425
 
            self.branchnick_label.show()
426
 
            self.branchnick.set_text(revision.properties['branch-nick'])
 
406
            self.branchnick_label.set_text(revision.properties['branch-nick'])
427
407
        except KeyError:
428
 
            self.branchnick.hide()
429
 
            self.branchnick_label.hide()
 
408
            self.branchnick_label.set_text("")
430
409
 
431
410
        self._add_parents_or_children(revision.parent_ids,
432
411
                                      self.parents_widgets,
433
412
                                      self.parents_table)
434
 
 
 
413
        
435
414
        file_info = revision.properties.get('file-info', None)
436
415
        if file_info is not None:
437
 
            try:
438
 
                file_info = bdecode(file_info.encode('UTF-8'))
439
 
            except ValueError:
440
 
                trace.note('Invalid per-file info for revision:%s, value: %r',
441
 
                           revision.revision_id, file_info)
442
 
                file_info = None
 
416
            file_info = bdecode(file_info.encode('UTF-8'))
443
417
 
444
418
        if file_info:
445
419
            if self._file_id is None:
470
444
        self._add_tags()
471
445
 
472
446
    def _update_signature(self, widget, param):
473
 
        if not has_seahorse:
474
 
            return
475
447
        if self.get_current_page() == PAGE_SIGNATURE:
476
448
            self.signature_table.set_revision(self._revision)
477
449
 
486
458
                                      self.children_table)
487
459
 
488
460
    def _switch_page_cb(self, notebook, page, page_num):
489
 
        if not has_seahorse:
490
 
            return
491
461
        if page_num == PAGE_SIGNATURE:
492
462
            self.signature_table.set_revision(self._revision)
493
463
 
527
497
        table.resize(max(len(revids), 1), 2)
528
498
 
529
499
        for idx, revid in enumerate(revids):
530
 
            align = Gtk.Alignment.new(0.0, 0.0, 1, 1)
 
500
            align = gtk.Alignment(0.0, 0.0)
531
501
            widgets.append(align)
532
502
            table.attach(align, 1, 2, idx, idx + 1,
533
 
                                      Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
503
                                      gtk.EXPAND | gtk.FILL, gtk.FILL)
534
504
            align.show()
535
505
 
536
 
            hbox = Gtk.HBox(homogeneous=False, spacing=6)
 
506
            hbox = gtk.HBox(False, spacing=6)
537
507
            align.add(hbox)
538
508
            hbox.show()
539
509
 
540
 
            image = Gtk.Image()
 
510
            image = gtk.Image()
541
511
            image.set_from_stock(
542
 
                Gtk.STOCK_FIND, Gtk.IconSize.SMALL_TOOLBAR)
 
512
                gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)
543
513
            image.show()
544
514
 
545
515
            if self._show_callback is not None:
546
 
                button = Gtk.Button()
 
516
                button = gtk.Button()
547
517
                button.add(image)
548
518
                button.connect("clicked", self._show_clicked_cb,
549
519
                               self._revision.revision_id, revid)
550
 
                hbox.pack_start(button, False, True, 0)
 
520
                hbox.pack_start(button, expand=False, fill=True)
551
521
                button.show()
552
522
 
553
 
            button = Gtk.Button()
554
 
            revid_label = Gtk.Label(label=str(revid))
555
 
            revid_label.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
556
 
            revid_label.set_alignment(0.0, 0.5)
557
 
            button.add(revid_label)
 
523
            button = gtk.Button(revid)
558
524
            button.connect("clicked",
559
 
                    lambda w, r: self.set_revision(
560
 
                        self._repository.get_revision(r)), revid)
 
525
                    lambda w, r: self.set_revision(self._repository.get_revision(r)), revid)
561
526
            button.set_use_underline(False)
562
 
            hbox.pack_start(button, True, True, 0)
563
 
            button.show_all()
 
527
            hbox.pack_start(button, expand=False, fill=True)
 
528
            button.show()
564
529
 
565
530
    def _create_general(self):
566
 
        vbox = Gtk.VBox(homogeneous=False, spacing=6)
 
531
        vbox = gtk.VBox(False, 6)
567
532
        vbox.set_border_width(6)
568
 
        vbox.pack_start(self._create_headers(), False, True, 0)
569
 
        vbox.pack_start(self._create_message_view(), True, True, 0)
570
 
        self.append_page(vbox, Gtk.Label(label="General"))
 
533
        vbox.pack_start(self._create_headers(), expand=False, fill=True)
 
534
        vbox.pack_start(self._create_message_view())
 
535
        self.append_page(vbox, tab_label=gtk.Label("General"))
571
536
        vbox.show()
572
537
 
573
538
    def _create_relations(self):
574
 
        vbox = Gtk.VBox(homogeneous=False, spacing=6)
 
539
        vbox = gtk.VBox(False, 6)
575
540
        vbox.set_border_width(6)
576
 
        vbox.pack_start(self._create_parents(), False, True, 0)
577
 
        vbox.pack_start(self._create_children(), False, True, 0)
578
 
        self.append_page(vbox, Gtk.Label(label="Relations"))
 
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"))
579
544
        vbox.show()
580
545
 
581
546
    def _create_signature(self):
582
547
        self.signature_table = SignatureTab(self._repository)
583
 
        self.append_page(
584
 
            self.signature_table, Gtk.Label(label='Signature'))
 
548
        self.append_page(self.signature_table, tab_label=gtk.Label('Signature'))
585
549
        self.connect_after('notify::revision', self._update_signature)
586
550
 
587
551
    def _create_headers(self):
588
 
        self.avatarsbox = AvatarsBox()
589
 
        
590
 
        self.table = Gtk.Table(rows=5, columns=2)
 
552
        self.table = gtk.Table(rows=5, columns=2)
591
553
        self.table.set_row_spacings(6)
592
554
        self.table.set_col_spacings(6)
593
555
        self.table.show()
594
 
        
595
 
        self.avatarsbox.pack_start(self.table, True, True, 0)
596
 
        self.avatarsbox.show()
597
 
 
598
 
        row = 0
599
 
 
600
 
        label = Gtk.Label()
601
 
        label.set_alignment(1.0, 0.5)
 
556
 
 
557
        align = gtk.Alignment(1.0, 0.5)
 
558
        label = gtk.Label()
602
559
        label.set_markup("<b>Revision Id:</b>")
603
 
        self.table.attach(label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
560
        align.add(label)
 
561
        self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
 
562
        align.show()
604
563
        label.show()
605
564
 
606
 
        revision_id = Gtk.Label()
607
 
        revision_id.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
608
 
        revision_id.set_alignment(0.0, 0.5)
 
565
        align = gtk.Alignment(0.0, 0.5)
 
566
        revision_id = gtk.Label()
609
567
        revision_id.set_selectable(True)
610
568
        self.connect('notify::revision', 
611
569
                lambda w, p: revision_id.set_text(self._revision.revision_id))
612
 
        self.table.attach(revision_id, 1, 2, row, row+1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
570
        align.add(revision_id)
 
571
        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
 
572
        align.show()
613
573
        revision_id.show()
614
574
 
615
 
        row += 1
616
 
        self.author_label = Gtk.Label()
617
 
        self.author_label.set_alignment(1.0, 0.5)
 
575
        align = gtk.Alignment(1.0, 0.5)
 
576
        self.author_label = gtk.Label()
618
577
        self.author_label.set_markup("<b>Author:</b>")
619
 
        self.table.attach(self.author_label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
578
        align.add(self.author_label)
 
579
        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
 
580
        align.show()
620
581
        self.author_label.show()
621
582
 
622
 
        self.author = Gtk.Label()
623
 
        self.author.set_ellipsize(Pango.EllipsizeMode.END)
624
 
        self.author.set_alignment(0.0, 0.5)
 
583
        align = gtk.Alignment(0.0, 0.5)
 
584
        self.author = gtk.Label()
625
585
        self.author.set_selectable(True)
626
 
        self.table.attach(self.author, 1, 2, row, row+1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
586
        align.add(self.author)
 
587
        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
 
588
        align.show()
627
589
        self.author.show()
628
590
        self.author.hide()
629
591
 
630
 
        row += 1
631
 
        label = Gtk.Label()
632
 
        label.set_alignment(1.0, 0.5)
 
592
        align = gtk.Alignment(1.0, 0.5)
 
593
        label = gtk.Label()
633
594
        label.set_markup("<b>Committer:</b>")
634
 
        self.table.attach(label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
595
        align.add(label)
 
596
        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
 
597
        align.show()
635
598
        label.show()
636
599
 
637
 
        self.committer = Gtk.Label()
638
 
        self.committer.set_ellipsize(Pango.EllipsizeMode.END)
639
 
        self.committer.set_alignment(0.0, 0.5)
 
600
        align = gtk.Alignment(0.0, 0.5)
 
601
        self.committer = gtk.Label()
640
602
        self.committer.set_selectable(True)
641
 
        self.table.attach(self.committer, 1, 2, row, row+1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
603
        align.add(self.committer)
 
604
        self.table.attach(align, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
 
605
        align.show()
642
606
        self.committer.show()
643
607
 
644
 
        row += 1
645
 
        self.branchnick_label = Gtk.Label()
646
 
        self.branchnick_label.set_alignment(1.0, 0.5)
647
 
        self.branchnick_label.set_markup("<b>Branch nick:</b>")
648
 
        self.table.attach(self.branchnick_label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
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)
649
621
        self.branchnick_label.show()
650
 
 
651
 
        self.branchnick = Gtk.Label()
652
 
        self.branchnick.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
653
 
        self.branchnick.set_alignment(0.0, 0.5)
654
 
        self.branchnick.set_selectable(True)
655
 
        self.table.attach(self.branchnick, 1, 2, row, row+1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
656
 
        self.branchnick.show()
657
 
 
658
 
        row += 1
659
 
        label = Gtk.Label()
660
 
        label.set_alignment(1.0, 0.5)
 
622
        align.show()
 
623
 
 
624
        align = gtk.Alignment(1.0, 0.5)
 
625
        label = gtk.Label()
661
626
        label.set_markup("<b>Timestamp:</b>")
662
 
        self.table.attach(label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
627
        align.add(label)
 
628
        self.table.attach(align, 0, 1, 4, 5, gtk.FILL, gtk.FILL)
 
629
        align.show()
663
630
        label.show()
664
631
 
665
 
        self.timestamp = Gtk.Label()
666
 
        self.timestamp.set_ellipsize(Pango.EllipsizeMode.END)
667
 
        self.timestamp.set_alignment(0.0, 0.5)
 
632
        align = gtk.Alignment(0.0, 0.5)
 
633
        self.timestamp = gtk.Label()
668
634
        self.timestamp.set_selectable(True)
669
 
        self.table.attach(self.timestamp, 1, 2, row, row+1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
635
        align.add(self.timestamp)
 
636
        self.table.attach(align, 1, 2, 4, 5, gtk.EXPAND | gtk.FILL, gtk.FILL)
 
637
        align.show()
670
638
        self.timestamp.show()
671
639
 
672
 
        row += 1
673
 
        self.tags_label = Gtk.Label()
674
 
        self.tags_label.set_alignment(1.0, 0.5)
 
640
        align = gtk.Alignment(1.0, 0.5)
 
641
        self.tags_label = gtk.Label()
675
642
        self.tags_label.set_markup("<b>Tags:</b>")
676
 
        self.table.attach(self.tags_label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
643
        align.add(self.tags_label)
 
644
        align.show()
 
645
        self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
677
646
        self.tags_label.show()
678
647
 
679
 
        self.tags_list = Gtk.Label()
680
 
        self.tags_list.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
681
 
        self.tags_list.set_alignment(0.0, 0.5)
682
 
        self.table.attach(self.tags_list, 1, 2, row, row+1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
648
        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)
 
652
        align.show()
683
653
        self.tags_list.show()
684
654
 
685
655
        self.connect('notify::revision', self._add_tags)
686
656
 
687
 
        return self.avatarsbox
 
657
        return self.table
688
658
    
689
659
    def _create_parents(self):
690
 
        hbox = Gtk.HBox(homogeneous=True, spacing=3)
 
660
        hbox = gtk.HBox(True, 3)
691
661
        
692
662
        self.parents_table = self._create_parents_or_children_table(
693
663
            "<b>Parents:</b>")
694
664
        self.parents_widgets = []
695
 
        hbox.pack_start(self.parents_table, True, True, 0)
 
665
        hbox.pack_start(self.parents_table)
696
666
 
697
667
        hbox.show()
698
668
        return hbox
699
669
 
700
670
    def _create_children(self):
701
 
        hbox = Gtk.HBox(homogeneous=True, spacing=3)
 
671
        hbox = gtk.HBox(True, 3)
702
672
        self.children_table = self._create_parents_or_children_table(
703
673
            "<b>Children:</b>")
704
674
        self.children_widgets = []
705
 
        hbox.pack_start(self.children_table, True, True, 0)
 
675
        hbox.pack_start(self.children_table)
706
676
        hbox.show()
707
677
        return hbox
708
678
        
709
679
    def _create_parents_or_children_table(self, text):
710
 
        table = Gtk.Table(rows=1, columns=2)
 
680
        table = gtk.Table(rows=1, columns=2)
711
681
        table.set_row_spacings(3)
712
682
        table.set_col_spacings(6)
713
683
        table.show()
714
684
 
715
 
        label = Gtk.Label()
 
685
        label = gtk.Label()
716
686
        label.set_markup(text)
717
 
        align = Gtk.Alignment.new(0.0, 0.5, 0, 0)
 
687
        align = gtk.Alignment(0.0, 0.5)
718
688
        align.add(label)
719
 
        table.attach(align, 0, 1, 0, 1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
 
689
        table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
720
690
        label.show()
721
691
        align.show()
722
692
 
723
693
        return table
724
694
 
725
695
    def _create_message_view(self):
726
 
        msg_buffer = Gtk.TextBuffer()
 
696
        msg_buffer = gtk.TextBuffer()
727
697
        self.connect('notify::revision',
728
698
                lambda w, p: msg_buffer.set_text(self._revision.message))
729
 
        window = Gtk.ScrolledWindow()
730
 
        window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
731
 
        window.set_shadow_type(Gtk.ShadowType.IN)
732
 
        tv = Gtk.TextView(buffer=msg_buffer)
 
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)
733
703
        tv.set_editable(False)
734
 
        tv.set_wrap_mode(Gtk.WrapMode.WORD)
 
704
        tv.set_wrap_mode(gtk.WRAP_WORD)
735
705
 
736
 
        tv.modify_font(Pango.FontDescription("Monospace"))
 
706
        tv.modify_font(pango.FontDescription("Monospace"))
737
707
        tv.show()
738
708
        window.add(tv)
739
709
        window.show()
742
712
    def _create_bugs(self):
743
713
        self.bugs_page = BugsTab()
744
714
        self.connect_after('notify::revision', self._update_bugs) 
745
 
        self.append_page(self.bugs_page, Gtk.Label(label='Bugs'))
 
715
        self.append_page(self.bugs_page, tab_label=gtk.Label('Bugs'))
746
716
 
747
717
    def _create_file_info_view(self):
748
 
        self.file_info_box = Gtk.VBox(homogeneous=False, spacing=6)
 
718
        self.file_info_box = gtk.VBox(False, 6)
749
719
        self.file_info_box.set_border_width(6)
750
 
        self.file_info_buffer = Gtk.TextBuffer()
751
 
        window = Gtk.ScrolledWindow()
752
 
        window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
753
 
        window.set_shadow_type(Gtk.ShadowType.IN)
754
 
        tv = Gtk.TextView(buffer=self.file_info_buffer)
 
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)
755
725
        tv.set_editable(False)
756
 
        tv.set_wrap_mode(Gtk.WrapMode.WORD)
757
 
        tv.modify_font(Pango.FontDescription("Monospace"))
 
726
        tv.set_wrap_mode(gtk.WRAP_WORD)
 
727
        tv.modify_font(pango.FontDescription("Monospace"))
758
728
        tv.show()
759
729
        window.add(tv)
760
730
        window.show()
761
 
        self.file_info_box.pack_start(window, True, True, 0)
 
731
        self.file_info_box.pack_start(window)
762
732
        self.file_info_box.hide() # Only shown when there are per-file messages
763
 
        self.append_page(self.file_info_box, Gtk.Label(label='Per-file'))
 
733
        self.append_page(self.file_info_box, tab_label=gtk.Label('Per-file'))
764
734