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