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