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