/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
22
23
from bzrlib.osutils import format_date
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
24
from bzrlib.util import bencode
0.1.1 by Dan Loda
First working version of xannotate.
25
26
27
class LogView(gtk.ScrolledWindow):
28
    """ Custom widget for commit log details.
29
30
    A variety of bzr tools may need to implement such a thing. This is a
31
    start.
32
    """
33
256.2.23 by Gary van der Merwe
Show Children
34
    def __init__(self, revision=None, scroll=True, tags=[],
35
                 show_children=False):
179 by Jelmer Vernooij
Don't use scrolling inside revisions in missing window.
36
        super(LogView, self).__init__()
37
        if scroll:
38
            self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
39
        else:
40
            self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)
0.1.1 by Dan Loda
First working version of xannotate.
41
        self.set_shadow_type(gtk.SHADOW_NONE)
256.2.23 by Gary van der Merwe
Show Children
42
        self.show_children = show_children
0.1.1 by Dan Loda
First working version of xannotate.
43
        self._create()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
44
        self._show_callback = None
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.
45
        self._go_callback = None
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
46
        self._clicked_callback = None
0.1.1 by Dan Loda
First working version of xannotate.
47
48
        if revision is not None:
241 by Jelmer Vernooij
Show tags in bzr viz.
49
            self.set_revision(revision, tags=tags)
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
50
        self.set_file_id(None)
0.1.1 by Dan Loda
First working version of xannotate.
51
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
52
    def set_show_callback(self, callback):
53
        self._show_callback = callback
54
55
    def set_go_callback(self, callback):
56
        self._go_callback = callback
57
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
58
    def set_file_id(self, file_id):
59
        """Set a specific file id that we want to track.
60
61
        This just effects the display of a per-file commit message.
62
        If it is set to None, then all commit messages will be shown.
63
        """
64
        self._file_id = file_id
65
256.2.23 by Gary van der Merwe
Show Children
66
    def set_revision(self, revision, tags=[], children=[]):
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
67
        self._revision = revision
0.1.1 by Dan Loda
First working version of xannotate.
68
        self.revision_id.set_text(revision.revision_id)
192 by Jelmer Vernooij
Allow committer to be None.
69
        if revision.committer is not None:
70
            self.committer.set_text(revision.committer)
71
        else:
72
            self.committer.set_text("")
259 by Aaron Bentley
Add author support to gannotate and log viewer
73
        author = revision.properties.get('author', '')
74
        if author != '':
75
            self.author.set_text(author)
76
            self.author.show()
77
            self.author_label.show()
78
        else:
79
            self.author.hide()
80
            self.author_label.hide()
81
197 by Jelmer Vernooij
Fix some warnings when displaying ghost revisions. Reported by John.
82
        if revision.timestamp is not None:
83
            self.timestamp.set_text(format_date(revision.timestamp,
84
                                                revision.timezone))
0.1.1 by Dan Loda
First working version of xannotate.
85
        self.message_buffer.set_text(revision.message)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
86
        try:
87
            self.branchnick_label.set_text(revision.properties['branch-nick'])
88
        except KeyError:
89
            self.branchnick_label.set_text("")
90
256.2.23 by Gary van der Merwe
Show Children
91
        self._add_parents_or_children(revision.parent_ids,
92
                                      self.parents_widgets,
93
                                      self.parents_table)
94
        
95
        if self.show_children:
96
            self._add_parents_or_children(children,
97
                                          self.children_widgets,
98
                                          self.children_table)
99
        
241 by Jelmer Vernooij
Show tags in bzr viz.
100
        self._add_tags(tags)
0.1.1 by Dan Loda
First working version of xannotate.
101
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
102
        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.
103
        if file_info is not None:
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
104
            file_info = bencode.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.
105
106
        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.
107
            if self._file_id is None:
108
                text = []
109
                for fi in file_info:
110
                    text.append('%(path)s\n%(message)s' % fi)
111
                self.file_info_buffer.set_text('\n'.join(text))
112
                self.file_info_label.set_markup("<b>File Messages:</b>")
113
                self.file_info_box.show()
114
            else:
115
                text = []
116
                for fi in file_info:
117
                    if fi['file_id'] == self._file_id:
118
                        text.append(fi['message'])
119
                if text:
120
                    self.file_info_buffer.set_text('\n'.join(text))
121
                    self.file_info_label.set_markup("<b>File Message:</b>")
122
                    self.file_info_box.show()
123
                else:
124
                    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.
125
        else:
126
            self.file_info_box.hide()
127
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
128
    def _show_clicked_cb(self, widget, revid, parentid):
129
        """Callback for when the show button for a parent is clicked."""
130
        self._show_callback(revid, parentid)
131
132
    def _go_clicked_cb(self, widget, revid):
133
        """Callback for when the go button for a parent is clicked."""
134
        self._go_callback(revid)
135
241 by Jelmer Vernooij
Show tags in bzr viz.
136
    def _add_tags(self, tags):
137
        if tags == []:
138
            self.tags_list.hide()
139
            self.tags_label.hide()
140
            return
141
142
        for widget in self.tags_widgets:
143
            self.tags_list.remove(widget)
144
242 by Jelmer Vernooij
Avoid cleanup warning.
145
        self.tags_widgets = []
146
241 by Jelmer Vernooij
Show tags in bzr viz.
147
        for tag in tags:
148
            widget = gtk.Label(tag)
149
            widget.set_selectable(True)
150
            self.tags_widgets.append(widget)
151
            self.tags_list.add(widget)
152
        self.tags_list.show_all()
153
        self.tags_label.show_all()
154
        
256.2.23 by Gary van der Merwe
Show Children
155
    def _add_parents_or_children(self, revids, widgets, table):
156
        while len(widgets) > 0:
157
            widget = widgets.pop()
158
            table.remove(widget)
159
        
160
        table.resize(max(len(revids), 1), 2)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
161
256.2.23 by Gary van der Merwe
Show Children
162
        for idx, revid in enumerate(revids):
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
163
            align = gtk.Alignment(0.0, 0.0)
256.2.23 by Gary van der Merwe
Show Children
164
            widgets.append(align)
165
            table.attach(align, 1, 2, idx, idx + 1,
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
166
                                      gtk.EXPAND | gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
167
            align.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
168
169
            hbox = gtk.HBox(False, spacing=6)
170
            align.add(hbox)
171
            hbox.show()
172
173
            image = gtk.Image()
174
            image.set_from_stock(
175
                gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)
176
            image.show()
177
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.
178
            if self._show_callback is not None:
179
                button = gtk.Button()
180
                button.add(image)
181
                button.connect("clicked", self._show_clicked_cb,
256.2.23 by Gary van der Merwe
Show Children
182
                               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.
183
                hbox.pack_start(button, expand=False, fill=True)
184
                button.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
185
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.
186
            if self._go_callback is not None:
256.2.23 by Gary van der Merwe
Show Children
187
                button = gtk.Button(revid)
188
                button.connect("clicked", self._go_clicked_cb, 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.
189
            else:
256.2.23 by Gary van der Merwe
Show Children
190
                button = gtk.Label(revid)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
191
            button.set_use_underline(False)
192
            hbox.pack_start(button, expand=False, fill=True)
193
            button.show()
0.1.1 by Dan Loda
First working version of xannotate.
194
195
    def _create(self):
196
        vbox = gtk.VBox(False, 6)
197
        vbox.set_border_width(6)
198
        vbox.pack_start(self._create_headers(), expand=False, fill=True)
291 by Jelmer Vernooij
Put children widget on a new line.
199
        vbox.pack_start(self._create_parents(), expand=False, fill=True)
200
        if self.show_children:
201
            vbox.pack_start(self._create_children(), expand=False, fill=True)
0.1.1 by Dan Loda
First working version of xannotate.
202
        vbox.pack_start(self._create_message_view())
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
203
        vbox.pack_start(self._create_file_info_view(), expand=True, fill=True)
0.1.1 by Dan Loda
First working version of xannotate.
204
        self.add_with_viewport(vbox)
205
        vbox.show()
206
207
    def _create_headers(self):
241 by Jelmer Vernooij
Show tags in bzr viz.
208
        self.table = gtk.Table(rows=5, columns=2)
0.1.1 by Dan Loda
First working version of xannotate.
209
        self.table.set_row_spacings(6)
210
        self.table.set_col_spacings(6)
211
        self.table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
212
213
        align = gtk.Alignment(1.0, 0.5)
214
        label = gtk.Label()
215
        label.set_markup("<b>Revision Id:</b>")
216
        align.add(label)
217
        self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
218
        align.show()
219
        label.show()
220
221
        align = gtk.Alignment(0.0, 0.5)
222
        self.revision_id = gtk.Label()
223
        self.revision_id.set_selectable(True)
224
        align.add(self.revision_id)
225
        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
226
        align.show()
227
        self.revision_id.show()
228
0.1.1 by Dan Loda
First working version of xannotate.
229
        align = gtk.Alignment(1.0, 0.5)
259 by Aaron Bentley
Add author support to gannotate and log viewer
230
        self.author_label = gtk.Label()
231
        self.author_label.set_markup("<b>Author:</b>")
232
        align.add(self.author_label)
233
        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
234
        align.show()
235
        self.author_label.show()
236
237
        align = gtk.Alignment(0.0, 0.5)
238
        self.author = gtk.Label()
239
        self.author.set_selectable(True)
240
        align.add(self.author)
241
        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
242
        align.show()
243
        self.author.show()
244
        self.author.hide()
245
246
        align = gtk.Alignment(1.0, 0.5)
0.1.1 by Dan Loda
First working version of xannotate.
247
        label = gtk.Label()
248
        label.set_markup("<b>Committer:</b>")
249
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
250
        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
251
        align.show()
252
        label.show()
253
254
        align = gtk.Alignment(0.0, 0.5)
255
        self.committer = gtk.Label()
256
        self.committer.set_selectable(True)
257
        align.add(self.committer)
259 by Aaron Bentley
Add author support to gannotate and log viewer
258
        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.
259
        align.show()
260
        self.committer.show()
261
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
262
        align = gtk.Alignment(0.0, 0.5)
263
        label = gtk.Label()
264
        label.set_markup("<b>Branch nick:</b>")
265
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
266
        self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
267
        label.show()
268
        align.show()
269
270
        align = gtk.Alignment(0.0, 0.5)
271
        self.branchnick_label = gtk.Label()
272
        self.branchnick_label.set_selectable(True)
273
        align.add(self.branchnick_label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
274
        self.table.attach(align, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
275
        self.branchnick_label.show()
276
        align.show()
277
0.1.1 by Dan Loda
First working version of xannotate.
278
        align = gtk.Alignment(1.0, 0.5)
279
        label = gtk.Label()
280
        label.set_markup("<b>Timestamp:</b>")
281
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
282
        self.table.attach(align, 0, 1, 4, 5, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
283
        align.show()
284
        label.show()
285
286
        align = gtk.Alignment(0.0, 0.5)
287
        self.timestamp = gtk.Label()
288
        self.timestamp.set_selectable(True)
289
        align.add(self.timestamp)
259 by Aaron Bentley
Add author support to gannotate and log viewer
290
        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.
291
        align.show()
292
        self.timestamp.show()
293
241 by Jelmer Vernooij
Show tags in bzr viz.
294
        align = gtk.Alignment(1.0, 0.5)
295
        self.tags_label = gtk.Label()
296
        self.tags_label.set_markup("<b>Tags:</b>")
297
        align.add(self.tags_label)
298
        align.show()
261 by Aaron Bentley
Fix tags formatting
299
        self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
300
        self.tags_label.show()
301
302
        align = gtk.Alignment(0.0, 0.5)
303
        self.tags_list = gtk.VBox()
304
        align.add(self.tags_list)
261 by Aaron Bentley
Fix tags formatting
305
        self.table.attach(align, 1, 2, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
306
        align.show()
307
        self.tags_list.show()
308
        self.tags_widgets = []
309
0.1.1 by Dan Loda
First working version of xannotate.
310
        return self.table
311
256.2.23 by Gary van der Merwe
Show Children
312
    
291 by Jelmer Vernooij
Put children widget on a new line.
313
    def _create_parents(self):
314
        hbox = gtk.HBox(True, 3)
256.2.23 by Gary van der Merwe
Show Children
315
        
316
        self.parents_table = self._create_parents_or_children_table(
317
            "<b>Parents:</b>")
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
318
        self.parents_widgets = []
256.2.23 by Gary van der Merwe
Show Children
319
        hbox.pack_start(self.parents_table)
291 by Jelmer Vernooij
Put children widget on a new line.
320
321
        hbox.show()
322
        return hbox
323
324
    def _create_children(self):
325
        hbox = gtk.HBox(True, 3)
326
        self.children_table = self._create_parents_or_children_table(
327
            "<b>Children:</b>")
328
        self.children_widgets = []
329
        hbox.pack_start(self.children_table)
256.2.23 by Gary van der Merwe
Show Children
330
        hbox.show()
331
        return hbox
332
        
333
    def _create_parents_or_children_table(self, text):
334
        table = gtk.Table(rows=1, columns=2)
335
        table.set_row_spacings(3)
336
        table.set_col_spacings(6)
337
        table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
338
339
        label = gtk.Label()
256.2.23 by Gary van der Merwe
Show Children
340
        label.set_markup(text)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
341
        align = gtk.Alignment(0.0, 0.5)
342
        align.add(label)
256.2.23 by Gary van der Merwe
Show Children
343
        table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
344
        label.show()
345
        align.show()
346
256.2.23 by Gary van der Merwe
Show Children
347
        return table
348
    
349
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
350
0.1.1 by Dan Loda
First working version of xannotate.
351
    def _create_message_view(self):
352
        self.message_buffer = gtk.TextBuffer()
353
        tv = gtk.TextView(self.message_buffer)
354
        tv.set_editable(False)
355
        tv.set_wrap_mode(gtk.WRAP_WORD)
356
        tv.modify_font(pango.FontDescription("Monospace"))
357
        tv.show()
358
        return tv
359
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
360
    def _create_file_info_view(self):
361
        self.file_info_box = gtk.VBox()
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
362
        self.file_info_label = gtk.Label()
363
        self.file_info_label.set_markup("<b>File Messages:</b>")
364
        self.file_info_label.show()
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
365
        self.file_info_buffer = gtk.TextBuffer()
366
        tv = gtk.TextView(self.file_info_buffer)
367
        tv.set_editable(False)
368
        tv.set_wrap_mode(gtk.WRAP_WORD)
369
        tv.modify_font(pango.FontDescription("Monospace"))
370
        tv.show()
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
371
        self.file_info_box.pack_start(self.file_info_label)
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
372
        self.file_info_box.pack_start(tv)
373
        self.file_info_box.hide() # Only shown when there are per-file messages
374
        return self.file_info_box
375