/b-gtk/fix-viz

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