/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:
104
            file_info = bencode.bdecode(file_info)
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
        
155
256.2.23 by Gary van der Merwe
Show Children
156
    def _add_parents_or_children(self, revids, widgets, table):
157
        while len(widgets) > 0:
158
            widget = widgets.pop()
159
            table.remove(widget)
160
        
161
        table.resize(max(len(revids), 1), 2)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
162
256.2.23 by Gary van der Merwe
Show Children
163
        for idx, revid in enumerate(revids):
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
164
            align = gtk.Alignment(0.0, 0.0)
256.2.23 by Gary van der Merwe
Show Children
165
            widgets.append(align)
166
            table.attach(align, 1, 2, idx, idx + 1,
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
167
                                      gtk.EXPAND | gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
168
            align.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
169
170
            hbox = gtk.HBox(False, spacing=6)
171
            align.add(hbox)
172
            hbox.show()
173
174
            image = gtk.Image()
175
            image.set_from_stock(
176
                gtk.STOCK_FIND, gtk.ICON_SIZE_SMALL_TOOLBAR)
177
            image.show()
178
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.
179
            if self._show_callback is not None:
180
                button = gtk.Button()
181
                button.add(image)
182
                button.connect("clicked", self._show_clicked_cb,
256.2.23 by Gary van der Merwe
Show Children
183
                               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.
184
                hbox.pack_start(button, expand=False, fill=True)
185
                button.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
186
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.
187
            if self._go_callback is not None:
256.2.23 by Gary van der Merwe
Show Children
188
                button = gtk.Button(revid)
189
                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.
190
            else:
256.2.23 by Gary van der Merwe
Show Children
191
                button = gtk.Label(revid)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
192
            button.set_use_underline(False)
193
            hbox.pack_start(button, expand=False, fill=True)
194
            button.show()
0.1.1 by Dan Loda
First working version of xannotate.
195
196
    def _create(self):
197
        vbox = gtk.VBox(False, 6)
198
        vbox.set_border_width(6)
199
        vbox.pack_start(self._create_headers(), expand=False, fill=True)
256.2.23 by Gary van der Merwe
Show Children
200
        vbox.pack_start(self._create_parents_and_children(), expand=False, fill=True)
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
201
        vbox.pack_start(self._create_message_view(), expand=True, fill=True)
202
        vbox.pack_start(self._create_file_info_view(), expand=True, fill=True)
0.1.1 by Dan Loda
First working version of xannotate.
203
        self.add_with_viewport(vbox)
204
        vbox.show()
205
206
    def _create_headers(self):
241 by Jelmer Vernooij
Show tags in bzr viz.
207
        self.table = gtk.Table(rows=5, columns=2)
0.1.1 by Dan Loda
First working version of xannotate.
208
        self.table.set_row_spacings(6)
209
        self.table.set_col_spacings(6)
210
        self.table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
211
212
        align = gtk.Alignment(1.0, 0.5)
213
        label = gtk.Label()
214
        label.set_markup("<b>Revision Id:</b>")
215
        align.add(label)
216
        self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
217
        align.show()
218
        label.show()
219
220
        align = gtk.Alignment(0.0, 0.5)
221
        self.revision_id = gtk.Label()
222
        self.revision_id.set_selectable(True)
223
        align.add(self.revision_id)
224
        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
225
        align.show()
226
        self.revision_id.show()
227
0.1.1 by Dan Loda
First working version of xannotate.
228
        align = gtk.Alignment(1.0, 0.5)
259 by Aaron Bentley
Add author support to gannotate and log viewer
229
        self.author_label = gtk.Label()
230
        self.author_label.set_markup("<b>Author:</b>")
231
        align.add(self.author_label)
232
        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
233
        align.show()
234
        self.author_label.show()
235
236
        align = gtk.Alignment(0.0, 0.5)
237
        self.author = gtk.Label()
238
        self.author.set_selectable(True)
239
        align.add(self.author)
240
        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
241
        align.show()
242
        self.author.show()
243
        self.author.hide()
244
245
        align = gtk.Alignment(1.0, 0.5)
0.1.1 by Dan Loda
First working version of xannotate.
246
        label = gtk.Label()
247
        label.set_markup("<b>Committer:</b>")
248
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
249
        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
250
        align.show()
251
        label.show()
252
253
        align = gtk.Alignment(0.0, 0.5)
254
        self.committer = gtk.Label()
255
        self.committer.set_selectable(True)
256
        align.add(self.committer)
259 by Aaron Bentley
Add author support to gannotate and log viewer
257
        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.
258
        align.show()
259
        self.committer.show()
260
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
261
        align = gtk.Alignment(0.0, 0.5)
262
        label = gtk.Label()
263
        label.set_markup("<b>Branch nick:</b>")
264
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
265
        self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
266
        label.show()
267
        align.show()
268
269
        align = gtk.Alignment(0.0, 0.5)
270
        self.branchnick_label = gtk.Label()
271
        self.branchnick_label.set_selectable(True)
272
        align.add(self.branchnick_label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
273
        self.table.attach(align, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
274
        self.branchnick_label.show()
275
        align.show()
276
0.1.1 by Dan Loda
First working version of xannotate.
277
        align = gtk.Alignment(1.0, 0.5)
278
        label = gtk.Label()
279
        label.set_markup("<b>Timestamp:</b>")
280
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
281
        self.table.attach(align, 0, 1, 4, 5, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
282
        align.show()
283
        label.show()
284
285
        align = gtk.Alignment(0.0, 0.5)
286
        self.timestamp = gtk.Label()
287
        self.timestamp.set_selectable(True)
288
        align.add(self.timestamp)
259 by Aaron Bentley
Add author support to gannotate and log viewer
289
        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.
290
        align.show()
291
        self.timestamp.show()
292
241 by Jelmer Vernooij
Show tags in bzr viz.
293
        align = gtk.Alignment(1.0, 0.5)
294
        self.tags_label = gtk.Label()
295
        self.tags_label.set_markup("<b>Tags:</b>")
296
        align.add(self.tags_label)
297
        align.show()
261 by Aaron Bentley
Fix tags formatting
298
        self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
299
        self.tags_label.show()
300
301
        align = gtk.Alignment(0.0, 0.5)
302
        self.tags_list = gtk.VBox()
303
        align.add(self.tags_list)
261 by Aaron Bentley
Fix tags formatting
304
        self.table.attach(align, 1, 2, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
305
        align.show()
306
        self.tags_list.show()
307
        self.tags_widgets = []
308
0.1.1 by Dan Loda
First working version of xannotate.
309
        return self.table
310
256.2.23 by Gary van der Merwe
Show Children
311
    
312
    def _create_parents_and_children(self):
313
        hbox = gtk.HBox(True, 6)
314
        
315
        self.parents_table = self._create_parents_or_children_table(
316
            "<b>Parents:</b>")
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
317
        self.parents_widgets = []
256.2.23 by Gary van der Merwe
Show Children
318
        hbox.pack_start(self.parents_table)
319
        
320
        if self.show_children:
321
            self.children_table = self._create_parents_or_children_table(
322
                "<b>Children:</b>")
323
            self.children_widgets = []
324
            hbox.pack_start(self.children_table)
325
        
326
        hbox.show()
327
        return hbox
328
        
329
    def _create_parents_or_children_table(self, text):
330
        table = gtk.Table(rows=1, columns=2)
331
        table.set_row_spacings(3)
332
        table.set_col_spacings(6)
333
        table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
334
335
        label = gtk.Label()
256.2.23 by Gary van der Merwe
Show Children
336
        label.set_markup(text)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
337
        align = gtk.Alignment(0.0, 0.5)
338
        align.add(label)
256.2.23 by Gary van der Merwe
Show Children
339
        table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
340
        label.show()
341
        align.show()
342
256.2.23 by Gary van der Merwe
Show Children
343
        return table
344
    
345
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
346
0.1.1 by Dan Loda
First working version of xannotate.
347
    def _create_message_view(self):
348
        self.message_buffer = gtk.TextBuffer()
349
        tv = gtk.TextView(self.message_buffer)
350
        tv.set_editable(False)
351
        tv.set_wrap_mode(gtk.WRAP_WORD)
352
        tv.modify_font(pango.FontDescription("Monospace"))
353
        tv.show()
354
        return tv
355
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
356
    def _create_file_info_view(self):
357
        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.
358
        self.file_info_label = gtk.Label()
359
        self.file_info_label.set_markup("<b>File Messages:</b>")
360
        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.
361
        self.file_info_buffer = gtk.TextBuffer()
362
        tv = gtk.TextView(self.file_info_buffer)
363
        tv.set_editable(False)
364
        tv.set_wrap_mode(gtk.WRAP_WORD)
365
        tv.modify_font(pango.FontDescription("Monospace"))
366
        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.
367
        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.
368
        self.file_info_box.pack_start(tv)
369
        self.file_info_box.hide() # Only shown when there are per-file messages
370
        return self.file_info_box
371