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