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