/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
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
26
class RevisionView(gtk.Notebook):
0.1.1 by Dan Loda
First working version of xannotate.
27
    """ Custom widget for commit log details.
28
29
    A variety of bzr tools may need to implement such a thing. This is a
30
    start.
31
    """
32
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
33
    def __init__(self, revision=None, tags=[],
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
34
                 show_children=False, branch=None):
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
35
        gtk.Notebook.__init__(self)
256.2.23 by Gary van der Merwe
Show Children
36
        self.show_children = show_children
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
37
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
38
        self._create_general()
39
        self._create_relations()
278.1.45 by John Arbash Meinel
Switch to a new tab for per-file messages.
40
        self._create_file_info_view()
324.2.9 by Daniel Schierbeck
Made 'General' the default page of the logview.
41
42
        self.set_current_page(0)
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
43
        
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
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
48
        self._branch = branch
49
0.1.1 by Dan Loda
First working version of xannotate.
50
        if revision is not None:
241 by Jelmer Vernooij
Show tags in bzr viz.
51
            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.
52
        self.set_file_id(None)
0.1.1 by Dan Loda
First working version of xannotate.
53
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
54
    def set_show_callback(self, callback):
55
        self._show_callback = callback
56
57
    def set_go_callback(self, callback):
58
        self._go_callback = callback
59
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
60
    def set_file_id(self, file_id):
61
        """Set a specific file id that we want to track.
62
63
        This just effects the display of a per-file commit message.
64
        If it is set to None, then all commit messages will be shown.
65
        """
66
        self._file_id = file_id
67
256.2.23 by Gary van der Merwe
Show Children
68
    def set_revision(self, revision, tags=[], children=[]):
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
69
        self._revision = revision
0.1.1 by Dan Loda
First working version of xannotate.
70
        self.revision_id.set_text(revision.revision_id)
192 by Jelmer Vernooij
Allow committer to be None.
71
        if revision.committer is not None:
72
            self.committer.set_text(revision.committer)
73
        else:
74
            self.committer.set_text("")
259 by Aaron Bentley
Add author support to gannotate and log viewer
75
        author = revision.properties.get('author', '')
76
        if author != '':
77
            self.author.set_text(author)
78
            self.author.show()
79
            self.author_label.show()
80
        else:
81
            self.author.hide()
82
            self.author_label.hide()
83
197 by Jelmer Vernooij
Fix some warnings when displaying ghost revisions. Reported by John.
84
        if revision.timestamp is not None:
85
            self.timestamp.set_text(format_date(revision.timestamp,
86
                                                revision.timezone))
0.1.1 by Dan Loda
First working version of xannotate.
87
        self.message_buffer.set_text(revision.message)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
88
        try:
89
            self.branchnick_label.set_text(revision.properties['branch-nick'])
90
        except KeyError:
91
            self.branchnick_label.set_text("")
92
256.2.23 by Gary van der Merwe
Show Children
93
        self._add_parents_or_children(revision.parent_ids,
94
                                      self.parents_widgets,
95
                                      self.parents_table)
96
        
97
        if self.show_children:
98
            self._add_parents_or_children(children,
99
                                          self.children_widgets,
100
                                          self.children_table)
101
        
241 by Jelmer Vernooij
Show tags in bzr viz.
102
        self._add_tags(tags)
324.2.10 by Daniel Schierbeck
Reduced overhead by only calculating diff when 'Changes' page is selected.
103
278.1.3 by John Arbash Meinel
Have the ability to tell the log view that we only care about a specific file_id.
104
        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.
105
        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.
106
            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.
107
108
        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.
109
            if self._file_id is None:
110
                text = []
111
                for fi in file_info:
112
                    text.append('%(path)s\n%(message)s' % fi)
113
                self.file_info_buffer.set_text('\n'.join(text))
114
                self.file_info_box.show()
115
            else:
116
                text = []
117
                for fi in file_info:
118
                    if fi['file_id'] == self._file_id:
119
                        text.append(fi['message'])
120
                if text:
121
                    self.file_info_buffer.set_text('\n'.join(text))
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
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
195
    def _create_general(self):
0.1.1 by Dan Loda
First working version of xannotate.
196
        vbox = gtk.VBox(False, 6)
197
        vbox.set_border_width(6)
198
        vbox.pack_start(self._create_headers(), expand=False, fill=True)
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
199
        vbox.pack_start(self._create_message_view())
200
        self.append_page(vbox, tab_label=gtk.Label("General"))
201
        vbox.show()
202
203
    def _create_relations(self):
204
        vbox = gtk.VBox(False, 6)
205
        vbox.set_border_width(6)
291 by Jelmer Vernooij
Put children widget on a new line.
206
        vbox.pack_start(self._create_parents(), expand=False, fill=True)
207
        if self.show_children:
208
            vbox.pack_start(self._create_children(), expand=False, fill=True)
324.2.1 by Daniel Schierbeck
Turned the logview into a notebook.
209
        self.append_page(vbox, tab_label=gtk.Label("Relations"))
0.1.1 by Dan Loda
First working version of xannotate.
210
        vbox.show()
324.2.4 by Daniel Schierbeck
Added 'Changes' page to logview.
211
0.1.1 by Dan Loda
First working version of xannotate.
212
    def _create_headers(self):
241 by Jelmer Vernooij
Show tags in bzr viz.
213
        self.table = gtk.Table(rows=5, columns=2)
0.1.1 by Dan Loda
First working version of xannotate.
214
        self.table.set_row_spacings(6)
215
        self.table.set_col_spacings(6)
216
        self.table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
217
218
        align = gtk.Alignment(1.0, 0.5)
219
        label = gtk.Label()
220
        label.set_markup("<b>Revision Id:</b>")
221
        align.add(label)
222
        self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
223
        align.show()
224
        label.show()
225
226
        align = gtk.Alignment(0.0, 0.5)
227
        self.revision_id = gtk.Label()
228
        self.revision_id.set_selectable(True)
229
        align.add(self.revision_id)
230
        self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
231
        align.show()
232
        self.revision_id.show()
233
0.1.1 by Dan Loda
First working version of xannotate.
234
        align = gtk.Alignment(1.0, 0.5)
259 by Aaron Bentley
Add author support to gannotate and log viewer
235
        self.author_label = gtk.Label()
236
        self.author_label.set_markup("<b>Author:</b>")
237
        align.add(self.author_label)
238
        self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
239
        align.show()
240
        self.author_label.show()
241
242
        align = gtk.Alignment(0.0, 0.5)
243
        self.author = gtk.Label()
244
        self.author.set_selectable(True)
245
        align.add(self.author)
246
        self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
247
        align.show()
248
        self.author.show()
249
        self.author.hide()
250
251
        align = gtk.Alignment(1.0, 0.5)
0.1.1 by Dan Loda
First working version of xannotate.
252
        label = gtk.Label()
253
        label.set_markup("<b>Committer:</b>")
254
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
255
        self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
256
        align.show()
257
        label.show()
258
259
        align = gtk.Alignment(0.0, 0.5)
260
        self.committer = gtk.Label()
261
        self.committer.set_selectable(True)
262
        align.add(self.committer)
259 by Aaron Bentley
Add author support to gannotate and log viewer
263
        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.
264
        align.show()
265
        self.committer.show()
266
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
267
        align = gtk.Alignment(0.0, 0.5)
268
        label = gtk.Label()
269
        label.set_markup("<b>Branch nick:</b>")
270
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
271
        self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
272
        label.show()
273
        align.show()
274
275
        align = gtk.Alignment(0.0, 0.5)
276
        self.branchnick_label = gtk.Label()
277
        self.branchnick_label.set_selectable(True)
278
        align.add(self.branchnick_label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
279
        self.table.attach(align, 1, 2, 3, 4, gtk.EXPAND | gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
280
        self.branchnick_label.show()
281
        align.show()
282
0.1.1 by Dan Loda
First working version of xannotate.
283
        align = gtk.Alignment(1.0, 0.5)
284
        label = gtk.Label()
285
        label.set_markup("<b>Timestamp:</b>")
286
        align.add(label)
259 by Aaron Bentley
Add author support to gannotate and log viewer
287
        self.table.attach(align, 0, 1, 4, 5, gtk.FILL, gtk.FILL)
0.1.1 by Dan Loda
First working version of xannotate.
288
        align.show()
289
        label.show()
290
291
        align = gtk.Alignment(0.0, 0.5)
292
        self.timestamp = gtk.Label()
293
        self.timestamp.set_selectable(True)
294
        align.add(self.timestamp)
259 by Aaron Bentley
Add author support to gannotate and log viewer
295
        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.
296
        align.show()
297
        self.timestamp.show()
298
241 by Jelmer Vernooij
Show tags in bzr viz.
299
        align = gtk.Alignment(1.0, 0.5)
300
        self.tags_label = gtk.Label()
301
        self.tags_label.set_markup("<b>Tags:</b>")
302
        align.add(self.tags_label)
303
        align.show()
261 by Aaron Bentley
Fix tags formatting
304
        self.table.attach(align, 0, 1, 5, 6, gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
305
        self.tags_label.show()
306
307
        align = gtk.Alignment(0.0, 0.5)
308
        self.tags_list = gtk.VBox()
309
        align.add(self.tags_list)
261 by Aaron Bentley
Fix tags formatting
310
        self.table.attach(align, 1, 2, 5, 6, gtk.EXPAND | gtk.FILL, gtk.FILL)
241 by Jelmer Vernooij
Show tags in bzr viz.
311
        align.show()
312
        self.tags_list.show()
313
        self.tags_widgets = []
314
0.1.1 by Dan Loda
First working version of xannotate.
315
        return self.table
316
256.2.23 by Gary van der Merwe
Show Children
317
    
291 by Jelmer Vernooij
Put children widget on a new line.
318
    def _create_parents(self):
319
        hbox = gtk.HBox(True, 3)
256.2.23 by Gary van der Merwe
Show Children
320
        
321
        self.parents_table = self._create_parents_or_children_table(
322
            "<b>Parents:</b>")
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
323
        self.parents_widgets = []
256.2.23 by Gary van der Merwe
Show Children
324
        hbox.pack_start(self.parents_table)
291 by Jelmer Vernooij
Put children widget on a new line.
325
326
        hbox.show()
327
        return hbox
328
329
    def _create_children(self):
330
        hbox = gtk.HBox(True, 3)
331
        self.children_table = self._create_parents_or_children_table(
332
            "<b>Children:</b>")
333
        self.children_widgets = []
334
        hbox.pack_start(self.children_table)
256.2.23 by Gary van der Merwe
Show Children
335
        hbox.show()
336
        return hbox
337
        
338
    def _create_parents_or_children_table(self, text):
339
        table = gtk.Table(rows=1, columns=2)
340
        table.set_row_spacings(3)
341
        table.set_col_spacings(6)
342
        table.show()
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
343
344
        label = gtk.Label()
256.2.23 by Gary van der Merwe
Show Children
345
        label.set_markup(text)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
346
        align = gtk.Alignment(0.0, 0.5)
347
        align.add(label)
256.2.23 by Gary van der Merwe
Show Children
348
        table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
349
        label.show()
350
        align.show()
351
256.2.23 by Gary van der Merwe
Show Children
352
        return table
353
    
354
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
355
0.1.1 by Dan Loda
First working version of xannotate.
356
    def _create_message_view(self):
357
        self.message_buffer = gtk.TextBuffer()
324.2.2 by Daniel Schierbeck
Surrounded the commit message textview with a scrolled window and added a shadow.
358
        window = gtk.ScrolledWindow()
359
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
360
        window.set_shadow_type(gtk.SHADOW_IN)
0.1.1 by Dan Loda
First working version of xannotate.
361
        tv = gtk.TextView(self.message_buffer)
362
        tv.set_editable(False)
363
        tv.set_wrap_mode(gtk.WRAP_WORD)
364
        tv.modify_font(pango.FontDescription("Monospace"))
365
        tv.show()
324.2.2 by Daniel Schierbeck
Surrounded the commit message textview with a scrolled window and added a shadow.
366
        window.add(tv)
367
        window.show()
368
        return window
0.1.1 by Dan Loda
First working version of xannotate.
369
278.1.2 by John Arbash Meinel
Add an extra box that pops up when we have per-file information.
370
    def _create_file_info_view(self):
278.1.45 by John Arbash Meinel
Switch to a new tab for per-file messages.
371
        self.file_info_box = gtk.VBox(False, 6)
372
        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.
373
        self.file_info_buffer = gtk.TextBuffer()
278.1.44 by John Arbash Meinel
Merge in trunk, and update logview per-file commit messages.
374
        window = gtk.ScrolledWindow()
375
        window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
376
        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.
377
        tv = gtk.TextView(self.file_info_buffer)
378
        tv.set_editable(False)
379
        tv.set_wrap_mode(gtk.WRAP_WORD)
380
        tv.modify_font(pango.FontDescription("Monospace"))
381
        tv.show()
278.1.44 by John Arbash Meinel
Merge in trunk, and update logview per-file commit messages.
382
        window.add(tv)
383
        window.show()
384
        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.
385
        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.
386
        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.
387