/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to annotate/gannotate.py

  • Committer: Jelmer Vernooij
  • Date: 2008-06-29 19:04:44 UTC
  • mto: This revision was merged to the branch mainline in revision 515.
  • Revision ID: jelmer@samba.org-20080629190444-3hhmoc5fsoknrvet
Re-enable signature showing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
29
29
 
30
30
from colormap import AnnotateColorMap, AnnotateColorSaturation
31
 
from bzrlib.plugins.gtk.logview import LogView
 
31
from bzrlib.plugins.gtk.revisionview import RevisionView
 
32
from bzrlib.plugins.gtk.window import Window
32
33
 
33
34
 
34
35
(
41
42
) = range(6)
42
43
 
43
44
 
44
 
class GAnnotateWindow(gtk.Window):
 
45
class GAnnotateWindow(Window):
45
46
    """Annotate window."""
46
47
 
47
 
    def __init__(self, all=False, plain=False):
 
48
    def __init__(self, all=False, plain=False, parent=None, branch=None):
48
49
        self.all = all
49
50
        self.plain = plain
 
51
        self._branch = branch
50
52
        
51
 
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
 
53
        Window.__init__(self, parent)
52
54
        
53
55
        self.set_icon(self.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_BUTTON))
54
56
        self.annotate_colormap = AnnotateColorSaturation()
56
58
        self._create()
57
59
        self.revisions = {}
58
60
        self.history = []
 
61
        self._no_back = set()
59
62
 
60
63
    def annotate(self, tree, branch, file_id):
61
64
        self.annotations = []
62
65
        self.branch = branch
63
66
        self.tree = tree
64
67
        self.file_id = file_id
 
68
        self.revisionview.set_file_id(file_id)
65
69
        self.revision_id = getattr(tree, 'get_revision_id', 
66
70
                                   lambda: CURRENT_REVISION)()
67
71
        
68
 
        # [revision id, line number, committer, revno, highlight color, line]
 
72
        # [revision id, line number, author, revno, highlight color, line]
69
73
        self.annomodel = gtk.ListStore(gobject.TYPE_STRING,
70
74
                                       gobject.TYPE_STRING,
71
75
                                       gobject.TYPE_STRING,
77
81
        try:
78
82
            branch.lock_read()
79
83
            branch.repository.lock_read()
 
84
            self.dotted = {}
 
85
            revno_map = self.branch.get_revision_id_to_revno_map()
 
86
            for revision_id, revno in revno_map.iteritems():
 
87
                self.dotted[revision_id] = '.'.join(str(num) for num in revno)
80
88
            for line_no, (revision, revno, line)\
81
89
                    in enumerate(self._annotate(tree, file_id)):
82
90
                if revision.revision_id == last_seen and not self.all:
83
 
                    revno = committer = ""
 
91
                    revno = author = ""
84
92
                else:
85
93
                    last_seen = revision.revision_id
86
 
                    committer = revision.committer
 
94
                    author = revision.get_apparent_author()
87
95
 
88
96
                if revision.revision_id not in self.revisions:
89
97
                    self.revisions[revision.revision_id] = revision
90
98
 
91
99
                self.annomodel.append([revision.revision_id,
92
100
                                       line_no + 1,
93
 
                                       committer,
 
101
                                       author,
94
102
                                       revno,
95
103
                                       None,
96
104
                                       line.rstrip("\r\n")
106
114
 
107
115
        self.annoview.set_model(self.annomodel)
108
116
        self.annoview.grab_focus()
 
117
        my_revno = self.dotted.get(self.revision_id, 'current')
 
118
        title = '%s (%s) - gannotate' % (self.tree.id2path(file_id), my_revno)
 
119
        self.set_title(title)
109
120
 
110
121
    def jump_to_line(self, lineno):
111
122
        if lineno > len(self.annomodel) or lineno < 1:
121
132
        self.annoview.set_cursor(row)
122
133
        self.annoview.scroll_to_cell(row, use_align=True)
123
134
 
124
 
    def _dotted_revnos(self, repository, revision_id):
125
 
        """Return a dict of revision_id -> dotted revno
126
 
        
127
 
        :param repository: The repository to get the graph from
128
 
        :param revision_id: The last revision for which this info is needed
129
 
        """
130
 
        graph = repository.get_revision_graph(revision_id)
131
 
        dotted = {}
132
 
        for n, revision_id, d, revno, e in tsort.merge_sort(graph, 
133
 
            revision_id, generate_revno=True):
134
 
            dotted[revision_id] = '.'.join(str(num) for num in revno)
135
 
        return dotted
136
135
 
137
136
    def _annotate(self, tree, file_id):
138
137
        current_revision = FakeRevision(CURRENT_REVISION)
147
146
            revision_id = self.branch.last_revision()
148
147
        else:
149
148
            revision_id = self.revision_id
150
 
        dotted = self._dotted_revnos(repository, revision_id)
151
149
        revision_cache = RevisionCache(repository, self.revisions)
152
150
        for origin, text in tree.annotate_iter(file_id):
153
151
            rev_id = origin
157
155
            else:
158
156
                try:
159
157
                    revision = revision_cache.get_revision(rev_id)
160
 
                    revno = dotted.get(rev_id, 'merge')
 
158
                    revno = self.dotted.get(rev_id, 'merge')
161
159
                    if len(revno) > 15:
162
160
                        revno = 'merge'
163
161
                except NoSuchRevision:
180
178
 
181
179
    def _activate_selected_revision(self, w):
182
180
        rev_id = self._selected_revision()
183
 
        if rev_id is None:
 
181
        if not rev_id or rev_id == NULL_REVISION:
184
182
            return
185
183
        selected = self.revisions[rev_id]
186
 
        self.logview.set_revision(selected)
187
 
        self.back_button.set_sensitive(len(selected.parent_ids) != 0)
 
184
        self.revisionview.set_revision(selected)
 
185
        if (len(selected.parent_ids) != 0 and selected.parent_ids[0] not in
 
186
            self._no_back):
 
187
            enable_back = True
 
188
        else:
 
189
            enable_back = False
 
190
        self.back_button.set_sensitive(enable_back)
188
191
 
189
192
    def _create(self):
190
 
        self.logview = self._create_log_view()
 
193
        self.revisionview = self._create_log_view()
191
194
        self.annoview = self._create_annotate_view()
192
195
 
193
 
        vbox = gtk.VBox(False, 12)
194
 
        vbox.set_border_width(12)
 
196
        vbox = gtk.VBox(False)
195
197
        vbox.show()
196
198
 
197
199
        sw = gtk.ScrolledWindow()
204
206
        swbox = gtk.VBox()
205
207
        swbox.pack_start(sw)
206
208
        swbox.show()
 
209
 
 
210
        hbox = gtk.HBox(False, 6)
 
211
        self.back_button = self._create_back_button()
 
212
        hbox.pack_start(self.back_button, expand=False, fill=True)
 
213
        self.forward_button = self._create_forward_button()
 
214
        hbox.pack_start(self.forward_button, expand=False, fill=True)
 
215
        hbox.show()
 
216
        vbox.pack_start(hbox, expand=False, fill=True)
207
217
        
208
218
        self.pane = pane = gtk.VPaned()
209
219
        pane.add1(swbox)
210
 
        pane.add2(self.logview)
 
220
        pane.add2(self.revisionview)
211
221
        pane.show()
212
222
        vbox.pack_start(pane, expand=True, fill=True)
213
223
 
222
232
                             self._search_by_line)
223
233
        self.add_accel_group(accels)
224
234
 
225
 
        hbox = gtk.HBox(False, 6)
226
 
        self.back_button = self._create_back_button()
227
 
        hbox.pack_start(self.back_button, expand=False, fill=True)
228
 
        self.forward_button = self._create_forward_button()
229
 
        hbox.pack_start(self.forward_button, expand=False, fill=True)
230
 
        hbox.pack_end(self._create_button_box(), expand=False, fill=True)
231
 
        hbox.show()
232
 
        vbox.pack_start(hbox, expand=False, fill=True)
233
 
 
234
235
        self.add(vbox)
235
236
 
236
237
    def _search_by_text(self, accel_group, window, key, modifiers):
241
242
        self._search.show_for('line')
242
243
        self._search.set_target(self.annoview, LINE_NUM_COL)
243
244
 
244
 
    def row_diff(self, tv, path, tvc):
 
245
    def line_diff(self, tv, path, tvc):
245
246
        row = path[0]
246
247
        revision = self.annotations[row]
247
248
        repository = self.branch.repository
256
257
                tree2 = repository.revision_tree(NULL_REVISION)
257
258
        from bzrlib.plugins.gtk.diff import DiffWindow
258
259
        window = DiffWindow()
259
 
        window.set_diff("Diff for row %d" % (row+1), tree1, tree2)
 
260
        window.set_diff("Diff for line %d" % (row+1), tree1, tree2)
260
261
        window.set_file(tree1.id2path(self.file_id))
261
262
        window.show()
262
263
 
266
267
        tv.set_rules_hint(False)
267
268
        tv.connect("cursor-changed", self._activate_selected_revision)
268
269
        tv.show()
269
 
        tv.connect("row-activated", self.row_diff)
 
270
        tv.connect("row-activated", self.line_diff)
270
271
 
271
272
        cell = gtk.CellRendererText()
272
273
        cell.set_property("xalign", 1.0)
320
321
        return tv
321
322
 
322
323
    def _create_log_view(self):
323
 
        lv = LogView()
 
324
        lv = RevisionView(self._branch)
324
325
        lv.show()
325
326
        return lv
326
327
 
327
 
    def _create_button_box(self):
328
 
        button = gtk.Button()
329
 
        button.set_use_stock(True)
330
 
        button.set_label("gtk-close")
331
 
        button.connect("clicked", lambda w: self.destroy())
332
 
        button.show()
333
 
        return button
334
 
 
335
328
    def _create_back_button(self):
336
329
        button = gtk.Button()
337
330
        button.set_use_stock(True)
338
331
        button.set_label("gtk-go-back")
339
332
        button.connect("clicked", lambda w: self.go_back())
 
333
        button.set_relief(gtk.RELIEF_NONE)
340
334
        button.show()
341
335
        return button
342
336
 
345
339
        button.set_use_stock(True)
346
340
        button.set_label("gtk-go-forward")
347
341
        button.connect("clicked", lambda w: self.go_forward())
 
342
        button.set_relief(gtk.RELIEF_NONE)
348
343
        button.show()
349
344
        button.set_sensitive(False)
350
345
        return button
351
346
 
352
347
    def go_back(self):
353
 
        self.history.append(self.tree)
354
 
        self.forward_button.set_sensitive(True)
 
348
        last_tree = self.tree
355
349
        rev_id = self._selected_revision()
356
350
        parent_id = self.revisions[rev_id].parent_ids[0]
357
351
        target_tree = self.branch.repository.revision_tree(parent_id)
358
 
        self._go(target_tree)
 
352
        if self._go(target_tree):
 
353
            self.history.append(last_tree)
 
354
            self.forward_button.set_sensitive(True)
 
355
        else:
 
356
            self._no_back.add(parent_id)
 
357
            self.back_button.set_sensitive(False)
359
358
 
360
359
    def go_forward(self):
361
360
        if len(self.history) == 0:
375
374
            if new_row < 0:
376
375
                new_row = 0
377
376
            self.annoview.set_cursor(new_row)
 
377
            return True
 
378
        else:
 
379
            return False
378
380
 
379
381
    def get_scroll_offset(self, tree):
380
382
        old = self.tree.get_file(self.file_id)
387
389
                return j - i
388
390
 
389
391
 
390
 
 
391
392
class FakeRevision:
392
393
    """ A fake revision.
393
394
 
403
404
        self.timezone = 0
404
405
        self.properties = {}
405
406
 
 
407
    def get_apparent_author(self):
 
408
        return self.committer
 
409
 
406
410
 
407
411
class RevisionCache(object):
408
412
    """A caching revision source"""