/b-gtk/fix-viz

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