/b-gtk/fix-viz

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