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