/b-gtk/fix-viz

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