/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: 2007-03-17 23:58:03 UTC
  • mfrom: (170.1.5 bzr-gtk-meld)
  • Revision ID: jelmer@samba.org-20070317235803-fyaw65t8ika939s1
MergeĀ upstream

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