/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
0.1.1 by Dan Loda
First working version of xannotate.
1
# Copyright (C) 2005 Dan Loda <danloda@gmail.com>
175 by Jelmer Vernooij
Add very simple gmissing command.
2
# Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
0.1.1 by Dan Loda
First working version of xannotate.
3
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
import pygtk
19
pygtk.require("2.0")
20
import gtk
21
import pango
399.1.9 by Daniel Schierbeck
Merged with trunk.
22
import gobject
496.1.1 by Sabin Iacob (m0n5t3r)
use webbrowser.open instead of the debian-specific sensible-browser
23
import webbrowser
0.1.1 by Dan Loda
First working version of xannotate.
24
622.1.2 by John Arbash Meinel
Add tests of RevisionView that it can handle broken file-info properties.
25
from bzrlib import trace
0.1.1 by Dan Loda
First working version of xannotate.
26
from bzrlib.osutils import format_date
412.1.8 by Daniel Schierbeck
Only import the bdecode function from the bzrlib.util.bencode package.
27
from bzrlib.util.bencode import bdecode
511.1.3 by Jelmer Vernooij
Make sure signed testament matches repository data.
28
from bzrlib.testament import Testament
29
30
from bzrlib.plugins.gtk import icon_path
0.1.1 by Dan Loda
First working version of xannotate.
31
399.3.27 by Daniel Schierbeck
Only show Signature tab if DBus and Seahorse are installed.
32
try:
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
33
    from bzrlib.plugins.gtk import seahorse
498.1.2 by Elliot Murphy
Trying to fix bug 107169 so that visualize can be used even if there are DBus problems which prevent seahorse from being loaded
34
except ImportError:
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
35
    has_seahorse = False
399.3.27 by Daniel Schierbeck
Only show Signature tab if DBus and Seahorse are installed.
36
else:
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
37
    has_seahorse = True
399.3.27 by Daniel Schierbeck
Only show Signature tab if DBus and Seahorse are installed.
38
450.1.19 by Daniel Schierbeck
Made sure the Signature page only gets updated when it is selected.
39
PAGE_GENERAL = 0
40
PAGE_RELATIONS = 1
41
PAGE_SIGNATURE = 2
42
PAGE_BUGS = 3
43
496.1.2 by Sabin Iacob (m0n5t3r)
also try xdg-open and sensible-browser
44
423.14.2 by Jelmer Vernooij
Move bugs tab to separate widget.
45
def _open_link(widget, uri):
498.2.1 by Sabin Iacob (m0n5t3r)
fix the browser opening code to work with python 2.4
46
    for cmd in ['sensible-browser', 'xdg-open']:
47
        if webbrowser._iscommand(cmd):
498.2.3 by Sabin Iacob (m0n5t3r)
fix typo, it actually works now
48
            webbrowser._tryorder.insert(0, '%s "%%s"' % cmd)
496.1.1 by Sabin Iacob (m0n5t3r)
use webbrowser.open instead of the debian-specific sensible-browser
49
    webbrowser.open(uri)
423.14.2 by Jelmer Vernooij
Move bugs tab to separate widget.
50
51
gtk.link_button_set_uri_hook(_open_link)
52
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
53
class BugsTab(gtk.VBox):
399.3.1 by Daniel Schierbeck
Made the key id label disappear when the revision is not signed.
54
423.14.2 by Jelmer Vernooij
Move bugs tab to separate widget.
55
    def __init__(self):
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
56
        super(BugsTab, self).__init__(False, 6)
450.6.11 by Daniel Schierbeck
Made Bugs page always visible, but only sensitive when the revision has bug associations.
57
    
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
58
        table = gtk.Table(rows=2, columns=2)
59
60
        table.set_row_spacings(6)
450.6.7 by Daniel Schierbeck
Improved spacing in the bugs page.
61
        table.set_col_spacing(0, 16)
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
62
63
        image = gtk.Image()
64
        image.set_from_file(icon_path("bug.png"))
65
        table.attach(image, 0, 1, 0, 1, gtk.FILL)
66
450.6.2 by Daniel Schierbeck
Further improved the look of the bug tab.
67
        align = gtk.Alignment(0.0, 0.1)
450.6.12 by Daniel Schierbeck
Changed Bugs page labels.
68
        self.label = gtk.Label()
69
        align.add(self.label)
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
70
        table.attach(align, 1, 2, 0, 1, gtk.FILL)
71
72
        treeview = self.construct_treeview()
73
        table.attach(treeview, 1, 2, 1, 2, gtk.FILL | gtk.EXPAND)
74
75
        self.set_border_width(6)
76
        self.pack_start(table, expand=False)
77
450.6.12 by Daniel Schierbeck
Changed Bugs page labels.
78
        self.clear()
450.6.11 by Daniel Schierbeck
Made Bugs page always visible, but only sensitive when the revision has bug associations.
79
        self.show_all()
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
80
450.6.4 by Daniel Schierbeck
Moved bug parsing code into the bug page itself.
81
    def set_revision(self, revision):
82
        if revision is None:
83
            return
84
85
        self.clear()
450.6.5 by Daniel Schierbeck
Simplified bug parsing.
86
        bugs_text = revision.properties.get('bugs', '')
87
        for bugline in bugs_text.splitlines():
450.6.4 by Daniel Schierbeck
Moved bug parsing code into the bug page itself.
88
                (url, status) = bugline.split(" ")
450.6.10 by Daniel Schierbeck
Only show fixed bugs in Bugs page.
89
                if status == "fixed":
90
                    self.add_bug(url, status)
450.6.12 by Daniel Schierbeck
Changed Bugs page labels.
91
        
92
        if self.num_bugs == 0:
93
            return
94
        elif self.num_bugs == 1:
95
            label = "bug"
96
        else:
97
            label = "bugs"
98
99
        self.label.set_markup("<b>Bugs fixed</b>\n" +
100
                              "This revision claims to fix " +
101
                              "%d %s." % (self.num_bugs, label))
450.6.4 by Daniel Schierbeck
Moved bug parsing code into the bug page itself.
102
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
103
    def construct_treeview(self):
104
        self.bugs = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
105
        self.treeview = gtk.TreeView(self.bugs)
450.6.8 by Daniel Schierbeck
Removed status column from bug table.
106
        self.treeview.set_headers_visible(False)
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
107
108
        uri_column = gtk.TreeViewColumn('Bug URI', gtk.CellRendererText(), text=0)
109
        self.treeview.append_column(uri_column)
110
450.6.9 by Daniel Schierbeck
Made it possible to open bugs in the browser.
111
        self.treeview.connect('row-activated', self.on_row_activated)
112
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
113
        win = gtk.ScrolledWindow()
114
        win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
115
        win.set_shadow_type(gtk.SHADOW_IN)
116
        win.add(self.treeview)
117
118
        return win
423.14.2 by Jelmer Vernooij
Move bugs tab to separate widget.
119
120
    def clear(self):
450.6.11 by Daniel Schierbeck
Made Bugs page always visible, but only sensitive when the revision has bug associations.
121
        self.num_bugs = 0
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
122
        self.bugs.clear()
450.6.11 by Daniel Schierbeck
Made Bugs page always visible, but only sensitive when the revision has bug associations.
123
        self.set_sensitive(False)
450.6.12 by Daniel Schierbeck
Changed Bugs page labels.
124
        self.label.set_markup("<b>No bugs fixed</b>\n" +
125
                              "This revision does not claim to fix any bugs.")
423.14.2 by Jelmer Vernooij
Move bugs tab to separate widget.
126
127
    def add_bug(self, url, status):
450.6.11 by Daniel Schierbeck
Made Bugs page always visible, but only sensitive when the revision has bug associations.
128
        self.num_bugs += 1
450.6.1 by Daniel Schierbeck
Made bug tab prettier.
129
        self.bugs.append([url, status])
450.6.11 by Daniel Schierbeck
Made Bugs page always visible, but only sensitive when the revision has bug associations.
130
        self.set_sensitive(True)
131
132
    def get_num_bugs(self):
133
        return self.num_bugs
423.14.2 by Jelmer Vernooij
Move bugs tab to separate widget.
134
450.6.9 by Daniel Schierbeck
Made it possible to open bugs in the browser.
135
    def on_row_activated(self, treeview, path, column):
136
        uri = self.bugs.get_value(self.bugs.get_iter(path), 0)
137
        _open_link(self, uri)
138
423.14.2 by Jelmer Vernooij
Move bugs tab to separate widget.
139
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
140
class SignatureTab(gtk.VBox):
399.3.1 by Daniel Schierbeck
Made the key id label disappear when the revision is not signed.
141
399.3.17 by Daniel Schierbeck
Moved signature handling into signature widget.
142
    def __init__(self, repository):
399.3.8 by Daniel Schierbeck
Moved crypt code into a Key class.
143
        self.key = None
399.3.23 by Daniel Schierbeck
Added comparison with revision committer.
144
        self.revision = None
399.3.17 by Daniel Schierbeck
Moved signature handling into signature widget.
145
        self.repository = repository
399.3.8 by Daniel Schierbeck
Moved crypt code into a Key class.
146
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
147
        super(SignatureTab, self).__init__(False, 6)
399.3.5 by Daniel Schierbeck
Added support for key fingerprints.
148
        signature_box = gtk.Table(rows=3, columns=3)
399.3.21 by Daniel Schierbeck
Played a bit with the spacings.
149
        signature_box.set_col_spacing(0, 16)
150
        signature_box.set_col_spacing(1, 12)
399.3.19 by Daniel Schierbeck
Increased row spacing in signature tab.
151
        signature_box.set_row_spacings(6)
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
152
153
        self.signature_image = gtk.Image()
154
        signature_box.attach(self.signature_image, 0, 1, 0, 1, gtk.FILL)
155
399.3.21 by Daniel Schierbeck
Played a bit with the spacings.
156
        align = gtk.Alignment(0.0, 0.1)
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
157
        self.signature_label = gtk.Label()
399.3.2 by Daniel Schierbeck
Moved key id label to the right.
158
        align.add(self.signature_label)
159
        signature_box.attach(align, 1, 3, 0, 1, gtk.FILL)
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
160
399.3.21 by Daniel Schierbeck
Played a bit with the spacings.
161
        align = gtk.Alignment(0.0, 0.5)
399.3.1 by Daniel Schierbeck
Made the key id label disappear when the revision is not signed.
162
        self.signature_key_id_label = gtk.Label()
163
        self.signature_key_id_label.set_markup("<b>Key Id:</b>")
164
        align.add(self.signature_key_id_label)
399.3.2 by Daniel Schierbeck
Moved key id label to the right.
165
        signature_box.attach(align, 1, 2, 1, 2, gtk.FILL, gtk.FILL)
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
166
167
        align = gtk.Alignment(0.0, 0.5)
168
        self.signature_key_id = gtk.Label()
169
        self.signature_key_id.set_selectable(True)
170
        align.add(self.signature_key_id)
399.3.2 by Daniel Schierbeck
Moved key id label to the right.
171
        signature_box.attach(align, 2, 3, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
172
399.3.21 by Daniel Schierbeck
Played a bit with the spacings.
173
        align = gtk.Alignment(0.0, 0.5)
399.3.5 by Daniel Schierbeck
Added support for key fingerprints.
174
        self.signature_fingerprint_label = gtk.Label()
175
        self.signature_fingerprint_label.set_markup("<b>Fingerprint:</b>")
176
        align.add(self.signature_fingerprint_label)
177
        signature_box.attach(align, 1, 2, 2, 3, gtk.FILL, gtk.FILL)
178
179
        align = gtk.Alignment(0.0, 0.5)
180
        self.signature_fingerprint = gtk.Label()
181
        self.signature_fingerprint.set_selectable(True)
182
        align.add(self.signature_fingerprint)
183
        signature_box.attach(align, 2, 3, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
184
399.3.6 by Daniel Schierbeck
Added support for key trust.
185
        align = gtk.Alignment(0.0, 0.5)
399.3.21 by Daniel Schierbeck
Played a bit with the spacings.
186
        self.signature_trust_label = gtk.Label()
187
        self.signature_trust_label.set_markup("<b>Trust:</b>")
188
        align.add(self.signature_trust_label)
189
        signature_box.attach(align, 1, 2, 3, 4, gtk.FILL, gtk.FILL)
190
191
        align = gtk.Alignment(0.0, 0.5)
399.3.6 by Daniel Schierbeck
Added support for key trust.
192
        self.signature_trust = gtk.Label()
193
        self.signature_trust.set_selectable(True)
194
        align.add(self.signature_trust)
195
        signature_box.attach(align, 2, 3, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
196
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
197
        self.set_border_width(6)
198
        self.pack_start(signature_box, expand=False)
199
        self.show_all()
200
399.3.17 by Daniel Schierbeck
Moved signature handling into signature widget.
201
    def set_revision(self, revision):
202
        self.revision = revision
203
        revid = revision.revision_id
204
205
        if self.repository.has_signature_for_revision_id(revid):
399.3.30 by Daniel Schierbeck
Fixed some naming issues.
206
            crypttext = self.repository.get_signature_text(revid)
207
            self.show_signature(crypttext)
399.3.17 by Daniel Schierbeck
Moved signature handling into signature widget.
208
        else:
209
            self.show_no_signature()
210
399.1.16 by Jelmer Vernooij
Move logic showing images to the SignatureTab widget.
211
    def show_no_signature(self):
399.3.1 by Daniel Schierbeck
Made the key id label disappear when the revision is not signed.
212
        self.signature_key_id_label.hide()
399.1.16 by Jelmer Vernooij
Move logic showing images to the SignatureTab widget.
213
        self.signature_key_id.set_text("")
399.3.6 by Daniel Schierbeck
Added support for key trust.
214
399.3.5 by Daniel Schierbeck
Added support for key fingerprints.
215
        self.signature_fingerprint_label.hide()
216
        self.signature_fingerprint.set_text("")
399.3.6 by Daniel Schierbeck
Added support for key trust.
217
218
        self.signature_trust_label.hide()
219
        self.signature_trust.set_text("")
220
399.1.19 by Jelmer Vernooij
Add utility function for finding icon paths.
221
        self.signature_image.set_from_file(icon_path("sign-unknown.png"))
399.3.9 by Daniel Schierbeck
Added headings.
222
        self.signature_label.set_markup("<b>Authenticity unknown</b>\n" +
223
                                        "This revision has not been signed.")
399.1.16 by Jelmer Vernooij
Move logic showing images to the SignatureTab widget.
224
399.3.30 by Daniel Schierbeck
Fixed some naming issues.
225
    def show_signature(self, crypttext):
511.1.2 by Jelmer Vernooij
Return cleartext from seahorse module
226
        (cleartext, key) = seahorse.verify(crypttext)
399.3.3 by Daniel Schierbeck
Made the signature code use the Seahorse D-Bus service.
227
511.1.3 by Jelmer Vernooij
Make sure signed testament matches repository data.
228
        assert cleartext is not None
229
230
        inv = self.repository.get_inventory(self.revision.revision_id)
231
        expected_testament = Testament(self.revision, inv).as_short_text()
232
        if expected_testament != cleartext:
233
            self.signature_image.set_from_file(icon_path("sign-bad.png"))
234
            self.signature_label.set_markup("<b>Signature does not match repository data</b>\n" +
235
                        "The signature plaintext is different from the expected testament plaintext.")
236
            return
237
450.5.3 by Daniel Schierbeck
Made the signature checking code not try to discover the signature key.
238
        if key and key.is_available():
399.3.23 by Daniel Schierbeck
Added comparison with revision committer.
239
            if key.is_trusted():
240
                if key.get_display_name() == self.revision.committer:
241
                    self.signature_image.set_from_file(icon_path("sign-ok.png"))
242
                    self.signature_label.set_markup("<b>Authenticity confirmed</b>\n" +
243
                                                    "This revision has been signed with " +
244
                                                    "a trusted key.")
245
                else:
246
                    self.signature_image.set_from_file(icon_path("sign-bad.png"))
247
                    self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
248
                                                    "Revision committer is not the same as signer.")
249
            else:
250
                self.signature_image.set_from_file(icon_path("sign-bad.png"))
251
                self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
252
                                                "This revision has been signed, but the " +
253
                                                "key is not trusted.")
254
        else:
399.3.11 by Daniel Schierbeck
Fixed error with unavailable keys.
255
            self.show_no_signature()
256
            self.signature_image.set_from_file(icon_path("sign-bad.png"))
399.3.13 by Daniel Schierbeck
Changed wording of authenticity heading.
257
            self.signature_label.set_markup("<b>Authenticity cannot be confirmed</b>\n" +
399.3.12 by Daniel Schierbeck
Fixed typo.
258
                                            "Signature key not available.")
399.3.11 by Daniel Schierbeck
Fixed error with unavailable keys.
259
            return
260
399.3.8 by Daniel Schierbeck
Moved crypt code into a Key class.
261
        trust = key.get_trust()
399.3.6 by Daniel Schierbeck
Added support for key trust.
262
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
263
        if trust <= seahorse.TRUST_NEVER:
399.3.6 by Daniel Schierbeck
Added support for key trust.
264
            trust_text = 'never trusted'
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
265
        elif trust == seahorse.TRUST_UNKNOWN:
399.3.6 by Daniel Schierbeck
Added support for key trust.
266
            trust_text = 'not trusted'
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
267
        elif trust == seahorse.TRUST_MARGINAL:
399.3.6 by Daniel Schierbeck
Added support for key trust.
268
            trust_text = 'marginally trusted'
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
269
        elif trust == seahorse.TRUST_FULL:
399.3.6 by Daniel Schierbeck
Added support for key trust.
270
            trust_text = 'fully trusted'
399.3.29 by Daniel Schierbeck
Renamed the crypt module to seahorse.
271
        elif trust == seahorse.TRUST_ULTIMATE:
399.3.6 by Daniel Schierbeck
Added support for key trust.
272
            trust_text = 'ultimately trusted'
399.3.5 by Daniel Schierbeck
Added support for key fingerprints.
273
399.3.1 by Daniel Schierbeck
Made the key id label disappear when the revision is not signed.
274
        self.signature_key_id_label.show()
399.3.8 by Daniel Schierbeck
Moved crypt code into a Key class.
275
        self.signature_key_id.set_text(key.get_id())
399.3.5 by Daniel Schierbeck
Added support for key fingerprints.
276
399.3.15 by Daniel Schierbeck
Made the fingerprint label read N/A when no fingerprint is available.
277
        fingerprint = key.get_fingerprint()
278
        if fingerprint == "":
399.3.18 by Daniel Schierbeck
Made empty fingerprint text grey.
279
            fingerprint = '<span foreground="dim grey">N/A</span>'
399.3.15 by Daniel Schierbeck
Made the fingerprint label read N/A when no fingerprint is available.
280
399.3.5 by Daniel Schierbeck
Added support for key fingerprints.
281
        self.signature_fingerprint_label.show()
399.3.18 by Daniel Schierbeck
Made empty fingerprint text grey.
282
        self.signature_fingerprint.set_markup(fingerprint)
399.3.3 by Daniel Schierbeck
Made the signature code use the Seahorse D-Bus service.
283
399.3.6 by Daniel Schierbeck
Added support for key trust.
284
        self.signature_trust_label.show()
285
        self.signature_trust.set_text('This key is ' + trust_text)
399.3.17 by Daniel Schierbeck
Moved signature handling into signature widget.
286
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
287
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
288
class RevisionView(gtk.Notebook):
0.1.1 by Dan Loda
First working version of xannotate.
289
    """ Custom widget for commit log details.
290
291
    A variety of bzr tools may need to implement such a thing. This is a
292
    start.
293
    """
294
412.1.1 by Daniel Schierbeck
Added branch and revision properties to the revisionview widget.
295
    __gproperties__ = {
296
        'branch': (
297
            gobject.TYPE_PYOBJECT,
298
            'Branch',
299
            'The branch holding the revision being displayed',
300
            gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE
301
        ),
302
303
        'revision': (
304
            gobject.TYPE_PYOBJECT,
305
            'Revision',
306
            'The revision being displayed',
412.1.2 by Daniel Schierbeck
Moved retrieval of tags into the revisionview itself.
307
            gobject.PARAM_READWRITE
412.1.7 by Daniel Schierbeck
Added file-id property to the revisionview.
308
        ),
309
412.1.13 by Daniel Schierbeck
Re-added support for displaying the children of a revision.
310
        'children': (
311
            gobject.TYPE_PYOBJECT,
312
            'Children',
313
            'Child revisions',
314
            gobject.PARAM_READWRITE
315
        ),
316
412.1.7 by Daniel Schierbeck
Added file-id property to the revisionview.
317
        'file-id': (
318
            gobject.TYPE_PYOBJECT,
319
            'File Id',
320
            'The file id',
321
            gobject.PARAM_READWRITE
412.1.1 by Daniel Schierbeck
Added branch and revision properties to the revisionview widget.
322
        )
323
    }
324
471.2.1 by Jelmer Vernooij
Fix gannotate.
325
    def __init__(self, branch=None, repository=None):
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
326
        gtk.Notebook.__init__(self)
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
327
399.3.17 by Daniel Schierbeck
Moved signature handling into signature widget.
328
        self._revision = None
329
        self._branch = branch
471.2.1 by Jelmer Vernooij
Fix gannotate.
330
        if branch is not None:
331
            self._repository = branch.repository
332
        else:
333
            self._repository = repository
399.3.17 by Daniel Schierbeck
Moved signature handling into signature widget.
334
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
335
        self._create_general()
336
        self._create_relations()
485 by Jelmer Vernooij
Disable signature tab until we actually start verifying the testament.
337
        # Disabled because testaments aren't verified yet:
511.1.1 by Jelmer Vernooij
Re-enable signature showing.
338
        if has_seahorse:
339
            self._create_signature()
278.1.45 by John Arbash Meinel
Switch to a new tab for per-file messages.
340
        self._create_file_info_view()
423.14.1 by Jelmer Vernooij
Add bugs tab to display bug status change metadata.
341
        self._create_bugs()
324.2.9 by Daniel Schierbeck
Made 'General' the default page of the logview.
342
450.1.19 by Daniel Schierbeck
Made sure the Signature page only gets updated when it is selected.
343
        self.set_current_page(PAGE_GENERAL)
450.1.20 by Daniel Schierbeck
Removed usage of lambda expressions as callbacks.
344
        self.connect_after('switch-page', self._switch_page_cb)
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
345
        
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
346
        self._show_callback = None
347
        self._clicked_callback = None
0.1.1 by Dan Loda
First working version of xannotate.
348
412.1.9 by Daniel Schierbeck
Removed the use of RevisionView.set_go_callback().
349
        self._revision = None
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
350
        self._branch = branch
351
423.7.4 by Daniel Schierbeck
Made revisionview and branchview update when a tag is added.
352
        self.update_tags()
412.1.2 by Daniel Schierbeck
Moved retrieval of tags into the revisionview itself.
353
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
354
        self.set_file_id(None)
0.1.1 by Dan Loda
First working version of xannotate.
355
412.1.1 by Daniel Schierbeck
Added branch and revision properties to the revisionview widget.
356
    def do_get_property(self, property):
357
        if property.name == 'branch':
358
            return self._branch
359
        elif property.name == 'revision':
360
            return self._revision
412.1.13 by Daniel Schierbeck
Re-added support for displaying the children of a revision.
361
        elif property.name == 'children':
362
            return self._children
412.1.7 by Daniel Schierbeck
Added file-id property to the revisionview.
363
        elif property.name == 'file-id':
364
            return self._file_id
412.1.1 by Daniel Schierbeck
Added branch and revision properties to the revisionview widget.
365
        else:
366
            raise AttributeError, 'unknown property %s' % property.name
367
368
    def do_set_property(self, property, value):
369
        if property.name == 'branch':
370
            self._branch = value
371
        elif property.name == 'revision':
372
            self._set_revision(value)
412.1.13 by Daniel Schierbeck
Re-added support for displaying the children of a revision.
373
        elif property.name == 'children':
374
            self.set_children(value)
412.1.7 by Daniel Schierbeck
Added file-id property to the revisionview.
375
        elif property.name == 'file-id':
376
            self._file_id = value
412.1.1 by Daniel Schierbeck
Added branch and revision properties to the revisionview widget.
377
        else:
378
            raise AttributeError, 'unknown property %s' % property.name
379
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
380
    def set_show_callback(self, callback):
381
        self._show_callback = callback
382
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
383
    def set_file_id(self, file_id):
384
        """Set a specific file id that we want to track.
385
386
        This just effects the display of a per-file commit message.
387
        If it is set to None, then all commit messages will be shown.
388
        """
412.1.7 by Daniel Schierbeck
Added file-id property to the revisionview.
389
        self.set_property('file-id', file_id)
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
390
412.1.13 by Daniel Schierbeck
Re-added support for displaying the children of a revision.
391
    def set_revision(self, revision):
412.1.9 by Daniel Schierbeck
Removed the use of RevisionView.set_go_callback().
392
        if revision != self._revision:
393
            self.set_property('revision', revision)
394
395
    def get_revision(self):
396
        return self.get_property('revision')
412.1.1 by Daniel Schierbeck
Added branch and revision properties to the revisionview widget.
397
412.1.15 by Daniel Schierbeck
Removed redundant method argument.
398
    def _set_revision(self, revision):
412.1.1 by Daniel Schierbeck
Added branch and revision properties to the revisionview widget.
399
        if revision is None: return
400
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
401
        self._revision = revision
192 by Jelmer Vernooij
Allow committer to be None.
402
        if revision.committer is not None:
403
            self.committer.set_text(revision.committer)
404
        else:
405
            self.committer.set_text("")
259 by Aaron Bentley
Add author support to gannotate and log viewer
406
        author = revision.properties.get('author', '')
407
        if author != '':
408
            self.author.set_text(author)
409
            self.author.show()
410
            self.author_label.show()
411
        else:
412
            self.author.hide()
413
            self.author_label.hide()
414
197 by Jelmer Vernooij
Fix some warnings when displaying ghost revisions. Reported by John.
415
        if revision.timestamp is not None:
416
            self.timestamp.set_text(format_date(revision.timestamp,
417
                                                revision.timezone))
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
418
        try:
626 by Jelmer Vernooij
Hide branch nick field rather if there is no branch nick property
419
            self.branchnick.show()
420
            self.branchnick_label.show()
421
            self.branchnick.set_text(revision.properties['branch-nick'])
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
422
        except KeyError:
626 by Jelmer Vernooij
Hide branch nick field rather if there is no branch nick property
423
            self.branchnick.hide()
424
            self.branchnick_label.hide()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
425
256.2.23 by Gary van der Merwe
Show Children
426
        self._add_parents_or_children(revision.parent_ids,
427
                                      self.parents_widgets,
428
                                      self.parents_table)
622.1.2 by John Arbash Meinel
Add tests of RevisionView that it can handle broken file-info properties.
429
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
430
        file_info = revision.properties.get('file-info', None)
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
431
        if file_info is not None:
622.1.2 by John Arbash Meinel
Add tests of RevisionView that it can handle broken file-info properties.
432
            try:
433
                file_info = bdecode(file_info.encode('UTF-8'))
434
            except ValueError:
435
                trace.note('Invalid per-file info for revision:%s, value: %r',
436
                           revision.revision_id, file_info)
437
                file_info = None
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
438
439
        if file_info:
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
440
            if self._file_id is None:
441
                text = []
442
                for fi in file_info:
443
                    text.append('%(path)s\n%(message)s' % fi)
444
                self.file_info_buffer.set_text('\n'.join(text))
445
                self.file_info_box.show()
446
            else:
447
                text = []
448
                for fi in file_info:
449
                    if fi['file_id'] == self._file_id:
450
                        text.append(fi['message'])
451
                if text:
452
                    self.file_info_buffer.set_text('\n'.join(text))
453
                    self.file_info_box.show()
454
                else:
455
                    self.file_info_box.hide()
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
456
        else:
457
            self.file_info_box.hide()
458
423.7.4 by Daniel Schierbeck
Made revisionview and branchview update when a tag is added.
459
    def update_tags(self):
460
        if self._branch is not None and self._branch.supports_tags():
461
            self._tagdict = self._branch.tags.get_reverse_tag_dict()
462
        else:
463
            self._tagdict = {}
464
465
        self._add_tags()
466
450.1.20 by Daniel Schierbeck
Removed usage of lambda expressions as callbacks.
467
    def _update_signature(self, widget, param):
450.1.19 by Daniel Schierbeck
Made sure the Signature page only gets updated when it is selected.
468
        if self.get_current_page() == PAGE_SIGNATURE:
469
            self.signature_table.set_revision(self._revision)
399.1.13 by Daniel Schierbeck
Merged with mainline.
470
450.6.4 by Daniel Schierbeck
Moved bug parsing code into the bug page itself.
471
    def _update_bugs(self, widget, param):
472
        self.bugs_page.set_revision(self._revision)
450.6.11 by Daniel Schierbeck
Made Bugs page always visible, but only sensitive when the revision has bug associations.
473
        label = self.get_tab_label(self.bugs_page)
461.1.1 by Daniel Schierbeck
Merged bug page improvements.
474
        label.set_sensitive(self.bugs_page.get_num_bugs() != 0)
450.6.4 by Daniel Schierbeck
Moved bug parsing code into the bug page itself.
475
412.1.13 by Daniel Schierbeck
Re-added support for displaying the children of a revision.
476
    def set_children(self, children):
477
        self._add_parents_or_children(children,
478
                                      self.children_widgets,
479
                                      self.children_table)
480
450.1.20 by Daniel Schierbeck
Removed usage of lambda expressions as callbacks.
481
    def _switch_page_cb(self, notebook, page, page_num):
482
        if page_num == PAGE_SIGNATURE:
483
            self.signature_table.set_revision(self._revision)
484
485
486
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
487
    def _show_clicked_cb(self, widget, revid, parentid):
488
        """Callback for when the show button for a parent is clicked."""
489
        self._show_callback(revid, parentid)
490
491
    def _go_clicked_cb(self, widget, revid):
492
        """Callback for when the go button for a parent is clicked."""
493
412.1.4 by Daniel Schierbeck
Made tag list smarter.
494
    def _add_tags(self, *args):
399.1.13 by Daniel Schierbeck
Merged with mainline.
495
        if self._revision is None:
496
            return
423.7.4 by Daniel Schierbeck
Made revisionview and branchview update when a tag is added.
497
412.1.4 by Daniel Schierbeck
Made tag list smarter.
498
        if self._tagdict.has_key(self._revision.revision_id):
499
            tags = self._tagdict[self._revision.revision_id]
500
        else:
501
            tags = []
502
            
241 by Jelmer Vernooij
Show tags in bzr viz.
503
        if tags == []:
504
            self.tags_list.hide()
505
            self.tags_label.hide()
506
            return
507
423.3.1 by Daniel Schierbeck
Made the tag list be a comma-separated line instead of a vertically stacked box.
508
        self.tags_list.set_text(", ".join(tags))
509
241 by Jelmer Vernooij
Show tags in bzr viz.
510
        self.tags_list.show_all()
511
        self.tags_label.show_all()
512
        
256.2.23 by Gary van der Merwe
Show Children
513
    def _add_parents_or_children(self, revids, widgets, table):
514
        while len(widgets) > 0:
515
            widget = widgets.pop()
516
            table.remove(widget)
517
        
518
        table.resize(max(len(revids), 1), 2)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
519
256.2.23 by Gary van der Merwe
Show Children
520
        for idx, revid in enumerate(revids):
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
521
            align = gtk.Alignment(0.0, 0.0, 1, 1)
256.2.23 by Gary van der Merwe
Show Children
522
            widgets.append(align)
523
            table.attach(align, 1, 2, idx, idx + 1,
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
524
                                      gtk.EXPAND | gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
525
            align.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
526
527
            hbox = gtk.HBox(False, spacing=6)
528
            align.add(hbox)
529
            hbox.show()
530
531
            image = gtk.Image()
532
            image.set_from_stock(
533
                gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)
534
            image.show()
535
148 by Jelmer Vernooij
Clean up interface a bit: don't show diff button when no diff can be accessed, use label instead of button when there is no callback set.
536
            if self._show_callback is not None:
537
                button = gtk.Button()
538
                button.add(image)
539
                button.connect("clicked", self._show_clicked_cb,
256.2.23 by Gary van der Merwe
Show Children
540
                               self._revision.revision_id, revid)
148 by Jelmer Vernooij
Clean up interface a bit: don't show diff button when no diff can be accessed, use label instead of button when there is no callback set.
541
                hbox.pack_start(button, expand=False, fill=True)
542
                button.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
543
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
544
            button = gtk.Button()
545
            revid_label = gtk.Label(str(revid))
546
            revid_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
547
            revid_label.set_alignment(0.0, 0.5)
548
            button.add(revid_label)
412.1.9 by Daniel Schierbeck
Removed the use of RevisionView.set_go_callback().
549
            button.connect("clicked",
471.2.1 by Jelmer Vernooij
Fix gannotate.
550
                    lambda w, r: self.set_revision(self._repository.get_revision(r)), revid)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
551
            button.set_use_underline(False)
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
552
            hbox.pack_start(button, expand=True, fill=True)
553
            button.show_all()
0.1.1 by Dan Loda
First working version of xannotate.
554
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
555
    def _create_general(self):
0.1.1 by Dan Loda
First working version of xannotate.
556
        vbox = gtk.VBox(False, 6)
557
        vbox.set_border_width(6)
558
        vbox.pack_start(self._create_headers(), expand=False, fill=True)
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
559
        vbox.pack_start(self._create_message_view())
560
        self.append_page(vbox, tab_label=gtk.Label("General"))
561
        vbox.show()
562
563
    def _create_relations(self):
564
        vbox = gtk.VBox(False, 6)
565
        vbox.set_border_width(6)
291 by Jelmer Vernooij
Put children widget on a new line.
566
        vbox.pack_start(self._create_parents(), expand=False, fill=True)
412.1.13 by Daniel Schierbeck
Re-added support for displaying the children of a revision.
567
        vbox.pack_start(self._create_children(), expand=False, fill=True)
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
568
        self.append_page(vbox, tab_label=gtk.Label("Relations"))
0.1.1 by Dan Loda
First working version of xannotate.
569
        vbox.show()
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
570
399.1.10 by Daniel Schierbeck
Improved implementation of the Signature page.
571
    def _create_signature(self):
471.2.1 by Jelmer Vernooij
Fix gannotate.
572
        self.signature_table = SignatureTab(self._repository)
399.1.15 by Jelmer Vernooij
Move signature tab to a separate class.
573
        self.append_page(self.signature_table, tab_label=gtk.Label('Signature'))
450.1.20 by Daniel Schierbeck
Removed usage of lambda expressions as callbacks.
574
        self.connect_after('notify::revision', self._update_signature)
399.1.10 by Daniel Schierbeck
Improved implementation of the Signature page.
575
0.1.1 by Dan Loda
First working version of xannotate.
576
    def _create_headers(self):
241 by Jelmer Vernooij
Show tags in bzr viz.
577
        self.table = gtk.Table(rows=5, columns=2)
0.1.1 by Dan Loda
First working version of xannotate.
578
        self.table.set_row_spacings(6)
579
        self.table.set_col_spacings(6)
580
        self.table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
581
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
582
        row = 0
583
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
584
        label = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
585
        label.set_alignment(1.0, 0.5)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
586
        label.set_markup("<b>Revision Id:</b>")
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
587
        self.table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
588
        label.show()
589
412.1.5 by Daniel Schierbeck
Made the revision id label use signals when updating.
590
        revision_id = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
591
        revision_id.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
592
        revision_id.set_alignment(0.0, 0.5)
412.1.5 by Daniel Schierbeck
Made the revision id label use signals when updating.
593
        revision_id.set_selectable(True)
594
        self.connect('notify::revision', 
595
                lambda w, p: revision_id.set_text(self._revision.revision_id))
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
596
        self.table.attach(revision_id, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
412.1.5 by Daniel Schierbeck
Made the revision id label use signals when updating.
597
        revision_id.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
598
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
599
        row += 1
259 by Aaron Bentley
Add author support to gannotate and log viewer
600
        self.author_label = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
601
        self.author_label.set_alignment(1.0, 0.5)
259 by Aaron Bentley
Add author support to gannotate and log viewer
602
        self.author_label.set_markup("<b>Author:</b>")
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
603
        self.table.attach(self.author_label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
259 by Aaron Bentley
Add author support to gannotate and log viewer
604
        self.author_label.show()
605
606
        self.author = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
607
        self.author.set_ellipsize(pango.ELLIPSIZE_END)
608
        self.author.set_alignment(0.0, 0.5)
259 by Aaron Bentley
Add author support to gannotate and log viewer
609
        self.author.set_selectable(True)
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
610
        self.table.attach(self.author, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
259 by Aaron Bentley
Add author support to gannotate and log viewer
611
        self.author.show()
612
        self.author.hide()
613
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
614
        row += 1
0.1.1 by Dan Loda
First working version of xannotate.
615
        label = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
616
        label.set_alignment(1.0, 0.5)
0.1.1 by Dan Loda
First working version of xannotate.
617
        label.set_markup("<b>Committer:</b>")
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
618
        self.table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
619
        label.show()
620
621
        self.committer = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
622
        self.committer.set_ellipsize(pango.ELLIPSIZE_END)
623
        self.committer.set_alignment(0.0, 0.5)
0.1.1 by Dan Loda
First working version of xannotate.
624
        self.committer.set_selectable(True)
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
625
        self.table.attach(self.committer, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
626
        self.committer.show()
627
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
628
        row += 1
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
629
        self.branchnick_label = gtk.Label()
626 by Jelmer Vernooij
Hide branch nick field rather if there is no branch nick property
630
        self.branchnick_label.set_alignment(1.0, 0.5)
631
        self.branchnick_label.set_markup("<b>Branch nick:</b>")
632
        self.table.attach(self.branchnick_label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
633
        self.branchnick_label.show()
634
626 by Jelmer Vernooij
Hide branch nick field rather if there is no branch nick property
635
        self.branchnick = gtk.Label()
636
        self.branchnick.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
637
        self.branchnick.set_alignment(0.0, 0.5)
638
        self.branchnick.set_selectable(True)
639
        self.table.attach(self.branchnick, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
640
        self.branchnick.show()
641
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
642
        row += 1
0.1.1 by Dan Loda
First working version of xannotate.
643
        label = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
644
        label.set_alignment(1.0, 0.5)
0.1.1 by Dan Loda
First working version of xannotate.
645
        label.set_markup("<b>Timestamp:</b>")
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
646
        self.table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
647
        label.show()
648
649
        self.timestamp = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
650
        self.timestamp.set_ellipsize(pango.ELLIPSIZE_END)
651
        self.timestamp.set_alignment(0.0, 0.5)
0.1.1 by Dan Loda
First working version of xannotate.
652
        self.timestamp.set_selectable(True)
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
653
        self.table.attach(self.timestamp, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
654
        self.timestamp.show()
655
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
656
        row += 1
241 by Jelmer Vernooij
Show tags in bzr viz.
657
        self.tags_label = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
658
        self.tags_label.set_alignment(1.0, 0.5)
241 by Jelmer Vernooij
Show tags in bzr viz.
659
        self.tags_label.set_markup("<b>Tags:</b>")
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
660
        self.table.attach(self.tags_label, 0, 1, row, row+1, gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
661
        self.tags_label.show()
662
423.3.1 by Daniel Schierbeck
Made the tag list be a comma-separated line instead of a vertically stacked box.
663
        self.tags_list = gtk.Label()
531.7.7 by Scott Scriven
Fixed labels/buttons overflowing their parent widgets.
664
        self.tags_list.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
665
        self.tags_list.set_alignment(0.0, 0.5)
666
        self.table.attach(self.tags_list, 1, 2, row, row+1, gtk.EXPAND | gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
667
        self.tags_list.show()
668
412.1.4 by Daniel Schierbeck
Made tag list smarter.
669
        self.connect('notify::revision', self._add_tags)
670
0.1.1 by Dan Loda
First working version of xannotate.
671
        return self.table
256.2.23 by Gary van der Merwe
Show Children
672
    
291 by Jelmer Vernooij
Put children widget on a new line.
673
    def _create_parents(self):
674
        hbox = gtk.HBox(True, 3)
256.2.23 by Gary van der Merwe
Show Children
675
        
676
        self.parents_table = self._create_parents_or_children_table(
677
            "<b>Parents:</b>")
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
678
        self.parents_widgets = []
256.2.23 by Gary van der Merwe
Show Children
679
        hbox.pack_start(self.parents_table)
291 by Jelmer Vernooij
Put children widget on a new line.
680
681
        hbox.show()
682
        return hbox
683
684
    def _create_children(self):
685
        hbox = gtk.HBox(True, 3)
686
        self.children_table = self._create_parents_or_children_table(
687
            "<b>Children:</b>")
688
        self.children_widgets = []
689
        hbox.pack_start(self.children_table)
256.2.23 by Gary van der Merwe
Show Children
690
        hbox.show()
691
        return hbox
692
        
693
    def _create_parents_or_children_table(self, text):
694
        table = gtk.Table(rows=1, columns=2)
695
        table.set_row_spacings(3)
696
        table.set_col_spacings(6)
697
        table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
698
699
        label = gtk.Label()
256.2.23 by Gary van der Merwe
Show Children
700
        label.set_markup(text)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
701
        align = gtk.Alignment(0.0, 0.5)
702
        align.add(label)
256.2.23 by Gary van der Merwe
Show Children
703
        table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
704
        label.show()
705
        align.show()
706
256.2.23 by Gary van der Merwe
Show Children
707
        return table
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
708
0.1.1 by Dan Loda
First working version of xannotate.
709
    def _create_message_view(self):
412.1.6 by Daniel Schierbeck
Made the message buffer use signals when updating.
710
        msg_buffer = gtk.TextBuffer()
711
        self.connect('notify::revision',
712
                lambda w, p: msg_buffer.set_text(self._revision.message))
324.2.2 by Daniel Schierbeck
Surrounded the commit message textview with a scrolled window and added a shadow.
713
        window = gtk.ScrolledWindow()
714
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
715
        window.set_shadow_type(gtk.SHADOW_IN)
412.1.6 by Daniel Schierbeck
Made the message buffer use signals when updating.
716
        tv = gtk.TextView(msg_buffer)
0.1.1 by Dan Loda
First working version of xannotate.
717
        tv.set_editable(False)
718
        tv.set_wrap_mode(gtk.WRAP_WORD)
399.1.13 by Daniel Schierbeck
Merged with mainline.
719
0.1.1 by Dan Loda
First working version of xannotate.
720
        tv.modify_font(pango.FontDescription("Monospace"))
721
        tv.show()
324.2.2 by Daniel Schierbeck
Surrounded the commit message textview with a scrolled window and added a shadow.
722
        window.add(tv)
723
        window.show()
724
        return window
0.1.1 by Dan Loda
First working version of xannotate.
725
423.14.1 by Jelmer Vernooij
Add bugs tab to display bug status change metadata.
726
    def _create_bugs(self):
450.6.4 by Daniel Schierbeck
Moved bug parsing code into the bug page itself.
727
        self.bugs_page = BugsTab()
728
        self.connect_after('notify::revision', self._update_bugs) 
729
        self.append_page(self.bugs_page, tab_label=gtk.Label('Bugs'))
423.14.1 by Jelmer Vernooij
Add bugs tab to display bug status change metadata.
730
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
731
    def _create_file_info_view(self):
278.1.45 by John Arbash Meinel
Switch to a new tab for per-file messages.
732
        self.file_info_box = gtk.VBox(False, 6)
733
        self.file_info_box.set_border_width(6)
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
734
        self.file_info_buffer = gtk.TextBuffer()
278.1.44 by John Arbash Meinel
Merge in trunk, and update logview per-file commit messages.
735
        window = gtk.ScrolledWindow()
736
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
737
        window.set_shadow_type(gtk.SHADOW_IN)
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
738
        tv = gtk.TextView(self.file_info_buffer)
739
        tv.set_editable(False)
740
        tv.set_wrap_mode(gtk.WRAP_WORD)
741
        tv.modify_font(pango.FontDescription("Monospace"))
742
        tv.show()
278.1.44 by John Arbash Meinel
Merge in trunk, and update logview per-file commit messages.
743
        window.add(tv)
744
        window.show()
745
        self.file_info_box.pack_start(window)
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
746
        self.file_info_box.hide() # Only shown when there are per-file messages
278.1.45 by John Arbash Meinel
Switch to a new tab for per-file messages.
747
        self.append_page(self.file_info_box, tab_label=gtk.Label('Per-file'))
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
748