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