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
18
from gi.repository import Gtk
19
from gi.repository import Pango
20
from gi.repository import GObject
23
from gpg import GPGSubprocess
23
from bzrlib import trace
24
25
from bzrlib.osutils import format_date
25
from bzrlib.bencode import bdecode
26
from bzrlib.testament import Testament
28
from bzrlib.plugins.gtk import icon_path
30
from bzrlib.plugins.gtk.avatarsbox import AvatarsBox
33
from bzrlib.plugins.gtk import seahorse
45
def _open_link(widget, uri):
46
for cmd in ['sensible-browser', 'xdg-open']:
47
if webbrowser._iscommand(cmd):
48
webbrowser._tryorder.insert(0, '%s "%%s"' % cmd)
52
class BugsTab(Gtk.VBox):
55
super(BugsTab, self).__init__(homogeneous=False, spacing=6)
57
table = Gtk.Table(rows=2, columns=2)
59
table.set_row_spacings(6)
60
table.set_col_spacing(0, 16)
63
image.set_from_file(icon_path("bug.png"))
64
table.attach(image, 0, 1, 0, 1, Gtk.AttachOptions.FILL)
66
align = Gtk.Alignment.new(0.0, 0.1, 0, 0)
67
self.label = Gtk.Label()
69
table.attach(align, 1, 2, 0, 1, Gtk.AttachOptions.FILL)
71
treeview = self.construct_treeview()
72
table.attach(treeview, 1, 2, 1, 2, Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND)
74
self.set_border_width(6)
75
self.pack_start(table, False, True, 0)
80
def set_revision(self, revision):
85
bugs_text = revision.properties.get('bugs', '')
86
for bugline in bugs_text.splitlines():
87
(url, status) = bugline.split(" ")
89
self.add_bug(url, status)
91
if self.num_bugs == 0:
93
elif self.num_bugs == 1:
98
self.label.set_markup("<b>Bugs fixed</b>\n" +
99
"This revision claims to fix " +
100
"%d %s." % (self.num_bugs, label))
102
def construct_treeview(self):
103
self.bugs = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING)
104
self.treeview = Gtk.TreeView(model=self.bugs)
105
self.treeview.set_headers_visible(False)
107
uri_column = Gtk.TreeViewColumn('Bug URI', Gtk.CellRendererText(), text=0)
108
self.treeview.append_column(uri_column)
110
self.treeview.connect('row-activated', self.on_row_activated)
112
win = Gtk.ScrolledWindow()
113
win.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
114
win.set_shadow_type(Gtk.ShadowType.IN)
115
win.add(self.treeview)
122
self.set_sensitive(False)
123
self.label.set_markup("<b>No bugs fixed</b>\n" +
124
"This revision does not claim to fix any bugs.")
126
def add_bug(self, url, status):
128
self.bugs.append([url, status])
129
self.set_sensitive(True)
131
def get_num_bugs(self):
134
def on_row_activated(self, treeview, path, column):
135
uri = self.bugs.get_value(self.bugs.get_iter(path), 0)
136
_open_link(self, uri)
139
class SignatureTab(Gtk.VBox):
141
def __init__(self, repository):
144
self.repository = repository
146
super(SignatureTab, self).__init__(homogeneous=False, spacing=6)
147
signature_box = Gtk.Table(rows=3, columns=3)
148
signature_box.set_col_spacing(0, 16)
149
signature_box.set_col_spacing(1, 12)
150
signature_box.set_row_spacings(6)
152
self.signature_image = Gtk.Image()
153
signature_box.attach(self.signature_image, 0, 1, 0, 1, Gtk.AttachOptions.FILL)
155
align = Gtk.Alignment.new(0.0, 0.1, 0.0, 0.0)
156
self.signature_label = Gtk.Label()
157
align.add(self.signature_label)
158
signature_box.attach(align, 1, 3, 0, 1, Gtk.AttachOptions.FILL)
160
align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
161
self.signature_key_id_label = Gtk.Label()
162
self.signature_key_id_label.set_markup("<b>Key Id:</b>")
163
align.add(self.signature_key_id_label)
164
signature_box.attach(align, 1, 2, 1, 2, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
166
align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
167
self.signature_key_id = Gtk.Label()
168
self.signature_key_id.set_selectable(True)
169
align.add(self.signature_key_id)
170
signature_box.attach(align, 2, 3, 1, 2, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
172
align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
173
self.signature_fingerprint_label = Gtk.Label()
174
self.signature_fingerprint_label.set_markup("<b>Fingerprint:</b>")
175
align.add(self.signature_fingerprint_label)
176
signature_box.attach(align, 1, 2, 2, 3, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
178
align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
179
self.signature_fingerprint = Gtk.Label()
180
self.signature_fingerprint.set_selectable(True)
181
align.add(self.signature_fingerprint)
182
signature_box.attach(align, 2, 3, 2, 3, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
184
align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
185
self.signature_trust_label = Gtk.Label()
186
self.signature_trust_label.set_markup("<b>Trust:</b>")
187
align.add(self.signature_trust_label)
188
signature_box.attach(align, 1, 2, 3, 4, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
190
align = Gtk.Alignment.new(0.0, 0.5, 0.0, 0.0)
191
self.signature_trust = Gtk.Label()
192
self.signature_trust.set_selectable(True)
193
align.add(self.signature_trust)
194
signature_box.attach(align, 2, 3, 3, 4, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
196
self.set_border_width(6)
197
self.pack_start(signature_box, False, True, 0)
200
def set_revision(self, revision):
201
self.revision = revision
202
revid = revision.revision_id
204
if self.repository.has_signature_for_revision_id(revid):
205
crypttext = self.repository.get_signature_text(revid)
206
self.show_signature(crypttext)
208
self.show_no_signature()
210
def show_no_signature(self):
211
self.signature_key_id_label.hide()
212
self.signature_key_id.set_text("")
214
self.signature_fingerprint_label.hide()
215
self.signature_fingerprint.set_text("")
217
self.signature_trust_label.hide()
218
self.signature_trust.set_text("")
220
self.signature_image.set_from_file(icon_path("sign-unknown.png"))
221
self.signature_label.set_markup("<b>Authenticity unknown</b>\n" +
222
"This revision has not been signed.")
224
def show_signature(self, crypttext):
225
(cleartext, key) = seahorse.verify(crypttext)
227
assert cleartext is not None
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.")
237
if key and key.is_available():
239
if key.get_display_name() == self.revision.committer:
240
self.signature_image.set_from_file(icon_path("sign-ok.png"))
241
self.signature_label.set_markup("<b>Authenticity confirmed</b>\n" +
242
"This revision has been signed with " +
245
self.signature_image.set_from_file(icon_path("sign-bad.png"))
246
self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
247
"Revision committer is not the same as signer.")
249
self.signature_image.set_from_file(icon_path("sign-bad.png"))
250
self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
251
"This revision has been signed, but the " +
252
"key is not trusted.")
254
self.show_no_signature()
255
self.signature_image.set_from_file(icon_path("sign-bad.png"))
256
self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
257
"Signature key not available.")
260
trust = key.get_trust()
262
if trust <= seahorse.TRUST_NEVER:
263
trust_text = 'never trusted'
264
elif trust == seahorse.TRUST_UNKNOWN:
265
trust_text = 'not trusted'
266
elif trust == seahorse.TRUST_MARGINAL:
267
trust_text = 'marginally trusted'
268
elif trust == seahorse.TRUST_FULL:
269
trust_text = 'fully trusted'
270
elif trust == seahorse.TRUST_ULTIMATE:
271
trust_text = 'ultimately trusted'
273
self.signature_key_id_label.show()
274
self.signature_key_id.set_text(key.get_id())
276
fingerprint = key.get_fingerprint()
277
if fingerprint == "":
278
fingerprint = '<span foreground="dim grey">N/A</span>'
280
self.signature_fingerprint_label.show()
281
self.signature_fingerprint.set_markup(fingerprint)
283
self.signature_trust_label.show()
284
self.signature_trust.set_text('This key is ' + trust_text)
287
class RevisionView(Gtk.Notebook):
26
from bzrlib.util.bencode import bdecode
30
class RevisionView(gtk.Notebook):
288
31
""" Custom widget for commit log details.
290
33
A variety of bzr tools may need to implement such a thing. This is a
527
220
table.resize(max(len(revids), 1), 2)
529
222
for idx, revid in enumerate(revids):
530
align = Gtk.Alignment.new(0.0, 0.0, 1, 1)
223
align = gtk.Alignment(0.0, 0.0)
531
224
widgets.append(align)
532
225
table.attach(align, 1, 2, idx, idx + 1,
533
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
226
gtk.EXPAND | gtk.FILL, gtk.FILL)
536
hbox = Gtk.HBox(homogeneous=False, spacing=6)
229
hbox = gtk.HBox(False, spacing=6)
541
234
image.set_from_stock(
542
Gtk.STOCK_FIND, Gtk.IconSize.SMALL_TOOLBAR)
235
gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)
545
238
if self._show_callback is not None:
546
button = Gtk.Button()
239
button = gtk.Button()
547
240
button.add(image)
548
241
button.connect("clicked", self._show_clicked_cb,
549
242
self._revision.revision_id, revid)
550
hbox.pack_start(button, False, True, 0)
243
hbox.pack_start(button, expand=False, fill=True)
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)
246
button = gtk.Button(revid)
558
247
button.connect("clicked",
559
lambda w, r: self.set_revision(
560
self._repository.get_revision(r)), revid)
248
lambda w, r: self.set_revision(self._branch.repository.get_revision(r)), revid)
561
249
button.set_use_underline(False)
562
hbox.pack_start(button, True, True, 0)
250
hbox.pack_start(button, expand=False, fill=True)
565
253
def _create_general(self):
566
vbox = Gtk.VBox(homogeneous=False, spacing=6)
254
vbox = gtk.VBox(False, 6)
567
255
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"))
256
vbox.pack_start(self._create_headers(), expand=False, fill=True)
257
vbox.pack_start(self._create_message_view())
258
self.append_page(vbox, tab_label=gtk.Label("General"))
573
261
def _create_relations(self):
574
vbox = Gtk.VBox(homogeneous=False, spacing=6)
262
vbox = gtk.VBox(False, 6)
575
263
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"))
264
vbox.pack_start(self._create_parents(), expand=False, fill=True)
265
vbox.pack_start(self._create_children(), expand=False, fill=True)
266
self.append_page(vbox, tab_label=gtk.Label("Relations"))
581
269
def _create_signature(self):
582
self.signature_table = SignatureTab(self._repository)
584
self.signature_table, Gtk.Label(label='Signature'))
270
signature_box = gtk.Table(rows=1, columns=2)
271
signature_box.set_col_spacing(0, 12)
273
self.signature_image = gtk.Image()
274
signature_box.attach(self.signature_image, 0, 1, 0, 1, gtk.FILL)
276
self.signature_label = gtk.Label()
277
signature_box.attach(self.signature_label, 1, 2, 0, 1, gtk.FILL)
279
signature_info = gtk.Table(rows=1, columns=2)
280
signature_info.set_row_spacings(6)
281
signature_info.set_col_spacings(6)
283
align = gtk.Alignment(1.0, 0.5)
285
label.set_markup("<b>Key Id:</b>")
287
signature_info.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
289
align = gtk.Alignment(0.0, 0.5)
290
self.signature_key_id = gtk.Label()
291
self.signature_key_id.set_selectable(True)
292
align.add(self.signature_key_id)
293
signature_info.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
295
box = gtk.VBox(False, 6)
296
box.set_border_width(6)
297
box.pack_start(signature_box, expand=False)
298
box.pack_start(signature_info, expand=False)
300
self.append_page(box, tab_label=gtk.Label("Signature"))
585
302
self.connect_after('notify::revision', self._update_signature)
587
304
def _create_headers(self):
588
self.avatarsbox = AvatarsBox()
590
self.table = Gtk.Table(rows=5, columns=2)
305
self.table = gtk.Table(rows=5, columns=2)
591
306
self.table.set_row_spacings(6)
592
307
self.table.set_col_spacings(6)
593
308
self.table.show()
595
self.avatarsbox.pack_start(self.table, True, True, 0)
596
self.avatarsbox.show()
601
label.set_alignment(1.0, 0.5)
310
align = gtk.Alignment(1.0, 0.5)
602
312
label.set_markup("<b>Revision Id:</b>")
603
self.table.attach(label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
314
self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
606
revision_id = Gtk.Label()
607
revision_id.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
608
revision_id.set_alignment(0.0, 0.5)
318
align = gtk.Alignment(0.0, 0.5)
319
revision_id = gtk.Label()
609
320
revision_id.set_selectable(True)
610
321
self.connect('notify::revision',
611
322
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)
323
align.add(revision_id)
324
self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
613
326
revision_id.show()
616
self.author_label = Gtk.Label()
617
self.author_label.set_alignment(1.0, 0.5)
328
align = gtk.Alignment(1.0, 0.5)
329
self.author_label = gtk.Label()
618
330
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)
331
align.add(self.author_label)
332
self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
620
334
self.author_label.show()
622
self.author = Gtk.Label()
623
self.author.set_ellipsize(Pango.EllipsizeMode.END)
624
self.author.set_alignment(0.0, 0.5)
336
align = gtk.Alignment(0.0, 0.5)
337
self.author = gtk.Label()
625
338
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)
339
align.add(self.author)
340
self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
627
342
self.author.show()
628
343
self.author.hide()
632
label.set_alignment(1.0, 0.5)
345
align = gtk.Alignment(1.0, 0.5)
633
347
label.set_markup("<b>Committer:</b>")
634
self.table.attach(label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
349
self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
637
self.committer = Gtk.Label()
638
self.committer.set_ellipsize(Pango.EllipsizeMode.END)
639
self.committer.set_alignment(0.0, 0.5)
353
align = gtk.Alignment(0.0, 0.5)
354
self.committer = gtk.Label()
640
355
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)
356
align.add(self.committer)
357
self.table.attach(align, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
642
359
self.committer.show()
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)
361
align = gtk.Alignment(0.0, 0.5)
363
label.set_markup("<b>Branch nick:</b>")
365
self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
369
align = gtk.Alignment(0.0, 0.5)
370
self.branchnick_label = gtk.Label()
371
self.branchnick_label.set_selectable(True)
372
align.add(self.branchnick_label)
373
self.table.attach(align, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
649
374
self.branchnick_label.show()
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()
660
label.set_alignment(1.0, 0.5)
377
align = gtk.Alignment(1.0, 0.5)
661
379
label.set_markup("<b>Timestamp:</b>")
662
self.table.attach(label, 0, 1, row, row+1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
381
self.table.attach(align, 0, 1, 4, 5, gtk.FILL, gtk.FILL)
665
self.timestamp = Gtk.Label()
666
self.timestamp.set_ellipsize(Pango.EllipsizeMode.END)
667
self.timestamp.set_alignment(0.0, 0.5)
385
align = gtk.Alignment(0.0, 0.5)
386
self.timestamp = gtk.Label()
668
387
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)
388
align.add(self.timestamp)
389
self.table.attach(align, 1, 2, 4, 5, gtk.EXPAND | gtk.FILL, gtk.FILL)
670
391
self.timestamp.show()
673
self.tags_label = Gtk.Label()
674
self.tags_label.set_alignment(1.0, 0.5)
393
align = gtk.Alignment(1.0, 0.5)
394
self.tags_label = gtk.Label()
675
395
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)
396
align.add(self.tags_label)
398
self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
677
399
self.tags_label.show()
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)
401
align = gtk.Alignment(0.0, 0.5)
402
self.tags_list = gtk.Label()
403
align.add(self.tags_list)
404
self.table.attach(align, 1, 2, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL)
683
406
self.tags_list.show()
685
408
self.connect('notify::revision', self._add_tags)
687
return self.avatarsbox
689
412
def _create_parents(self):
690
hbox = Gtk.HBox(homogeneous=True, spacing=3)
413
hbox = gtk.HBox(True, 3)
692
415
self.parents_table = self._create_parents_or_children_table(
693
416
"<b>Parents:</b>")
694
417
self.parents_widgets = []
695
hbox.pack_start(self.parents_table, True, True, 0)
418
hbox.pack_start(self.parents_table)
700
423
def _create_children(self):
701
hbox = Gtk.HBox(homogeneous=True, spacing=3)
424
hbox = gtk.HBox(True, 3)
702
425
self.children_table = self._create_parents_or_children_table(
703
426
"<b>Children:</b>")
704
427
self.children_widgets = []
705
hbox.pack_start(self.children_table, True, True, 0)
428
hbox.pack_start(self.children_table)
709
432
def _create_parents_or_children_table(self, text):
710
table = Gtk.Table(rows=1, columns=2)
433
table = gtk.Table(rows=1, columns=2)
711
434
table.set_row_spacings(3)
712
435
table.set_col_spacings(6)
716
439
label.set_markup(text)
717
align = Gtk.Alignment.new(0.0, 0.5, 0, 0)
440
align = gtk.Alignment(0.0, 0.5)
719
table.attach(align, 0, 1, 0, 1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)
442
table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
725
448
def _create_message_view(self):
726
msg_buffer = Gtk.TextBuffer()
449
msg_buffer = gtk.TextBuffer()
727
450
self.connect('notify::revision',
728
451
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)
452
window = gtk.ScrolledWindow()
453
window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
454
window.set_shadow_type(gtk.SHADOW_IN)
455
tv = gtk.TextView(msg_buffer)
733
456
tv.set_editable(False)
734
tv.set_wrap_mode(Gtk.WrapMode.WORD)
736
tv.modify_font(Pango.FontDescription("Monospace"))
457
tv.set_wrap_mode(gtk.WRAP_WORD)
458
tv.modify_font(pango.FontDescription("Monospace"))
742
def _create_bugs(self):
743
self.bugs_page = BugsTab()
744
self.connect_after('notify::revision', self._update_bugs)
745
self.append_page(self.bugs_page, Gtk.Label(label='Bugs'))
747
464
def _create_file_info_view(self):
748
self.file_info_box = Gtk.VBox(homogeneous=False, spacing=6)
465
self.file_info_box = gtk.VBox(False, 6)
749
466
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)
467
self.file_info_buffer = gtk.TextBuffer()
468
window = gtk.ScrolledWindow()
469
window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
470
window.set_shadow_type(gtk.SHADOW_IN)
471
tv = gtk.TextView(self.file_info_buffer)
755
472
tv.set_editable(False)
756
tv.set_wrap_mode(Gtk.WrapMode.WORD)
757
tv.modify_font(Pango.FontDescription("Monospace"))
473
tv.set_wrap_mode(gtk.WRAP_WORD)
474
tv.modify_font(pango.FontDescription("Monospace"))
761
self.file_info_box.pack_start(window, True, True, 0)
478
self.file_info_box.pack_start(window)
762
479
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'))
480
self.append_page(self.file_info_box, tab_label=gtk.Label('Per-file'))
482
def _update_signature(self, widget, param):
483
revid = self._revision.revision_id
485
if self._repository.has_signature_for_revision_id(revid):
486
signature_text = self._repository.get_signature_text(revid)
487
signature = gpg.verify(signature_text)
489
if signature.key_id is not None:
490
self.signature_key_id.set_text(signature.key_id)
492
if signature.is_valid():
493
self.signature_image.set_from_file("icons/sign-ok.png")
494
self.signature_label.set_text("This revision has been signed.")
496
self.signature_image.set_from_file("icons/sign-bad.png")
497
self.signature_label.set_text("This revision has been signed, " +
498
"but the authenticity of the signature cannot be verified.")
500
self.signature_key_id.set_text("")
501
self.signature_image.set_from_file("icons/sign-unknown.png")
502
self.signature_label.set_text("This revision has not been signed.")