/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-07-15 15:22:29 UTC
  • Revision ID: jelmer@samba.org-20070715152229-clmlen0vpd8d2pzx
Add docstrings, remove unused code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import pango
24
24
import re
25
25
 
26
 
from bzrlib import patiencediff
 
26
from bzrlib import patiencediff, tsort
27
27
from bzrlib.errors import NoSuchRevision
28
28
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
29
29
 
30
 
from bzrlib.plugins.gtk.annotate.colormap import AnnotateColorSaturation
31
 
from bzrlib.plugins.gtk.revisionview import RevisionView
32
 
from bzrlib.plugins.gtk.window import Window
 
30
from colormap import AnnotateColorMap, AnnotateColorSaturation
 
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
 
 
53
 
        Window.__init__(self, parent)
54
 
 
 
50
        
 
51
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
 
52
        
55
53
        self.set_icon(self.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_BUTTON))
56
54
        self.annotate_colormap = AnnotateColorSaturation()
57
55
 
65
63
        self.branch = branch
66
64
        self.tree = tree
67
65
        self.file_id = file_id
68
 
        self.revisionview.set_file_id(file_id)
69
66
        self.revision_id = getattr(tree, 'get_revision_id', 
70
67
                                   lambda: CURRENT_REVISION)()
71
 
 
72
 
        # [revision id, line number, author, revno, highlight color, line]
 
68
        
 
69
        # [revision id, line number, committer, revno, highlight color, line]
73
70
        self.annomodel = gtk.ListStore(gobject.TYPE_STRING,
74
 
                                       gobject.TYPE_INT,
 
71
                                       gobject.TYPE_STRING,
75
72
                                       gobject.TYPE_STRING,
76
73
                                       gobject.TYPE_STRING,
77
74
                                       gobject.TYPE_STRING,
78
75
                                       gobject.TYPE_STRING)
79
 
 
 
76
        
80
77
        last_seen = None
81
78
        try:
82
79
            branch.lock_read()
83
80
            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
81
            for line_no, (revision, revno, line)\
89
 
                in enumerate(self._annotate(tree, file_id)):
 
82
                    in enumerate(self._annotate(tree, file_id)):
90
83
                if revision.revision_id == last_seen and not self.all:
91
 
                    revno = author = ""
 
84
                    revno = committer = ""
92
85
                else:
93
86
                    last_seen = revision.revision_id
94
 
                    author = ", ".join(revision.get_apparent_authors())
 
87
                    committer = revision.committer
95
88
 
96
89
                if revision.revision_id not in self.revisions:
97
90
                    self.revisions[revision.revision_id] = revision
98
91
 
99
92
                self.annomodel.append([revision.revision_id,
100
93
                                       line_no + 1,
101
 
                                       author,
 
94
                                       committer,
102
95
                                       revno,
103
96
                                       None,
104
97
                                       line.rstrip("\r\n")
105
 
                                       ])
 
98
                                      ])
106
99
                self.annotations.append(revision)
107
100
 
108
101
            if not self.plain:
114
107
 
115
108
        self.annoview.set_model(self.annomodel)
116
109
        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
110
 
121
111
    def jump_to_line(self, lineno):
122
112
        if lineno > len(self.annomodel) or lineno < 1:
125
115
            # bar?
126
116
            print("gannotate: Line number %d does't exist. Defaulting to "
127
117
                  "line 1." % lineno)
128
 
            return
 
118
            return
129
119
        else:
130
120
            row = lineno - 1
131
121
 
132
122
        self.annoview.set_cursor(row)
133
123
        self.annoview.scroll_to_cell(row, use_align=True)
134
124
 
 
125
    def _dotted_revnos(self, repository, revision_id):
 
126
        """Return a dict of revision_id -> dotted revno
 
127
        
 
128
        :param repository: The repository to get the graph from
 
129
        :param revision_id: The last revision for which this info is needed
 
130
        """
 
131
        graph = repository.get_revision_graph(revision_id)
 
132
        dotted = {}
 
133
        for n, revision_id, d, revno, e in tsort.merge_sort(graph, 
 
134
            revision_id, generate_revno=True):
 
135
            dotted[revision_id] = '.'.join(str(num) for num in revno)
 
136
        return dotted
135
137
 
136
138
    def _annotate(self, tree, file_id):
137
139
        current_revision = FakeRevision(CURRENT_REVISION)
139
141
        current_revision.timestamp = time.time()
140
142
        current_revision.message = '[Not yet committed]'
141
143
        current_revision.parent_ids = tree.get_parent_ids()
142
 
        current_revision.properties['branch-nick'] = self.branch._get_nick(local=True)
 
144
        current_revision.properties['branch-nick'] = self.branch.nick
143
145
        current_revno = '%d?' % (self.branch.revno() + 1)
144
146
        repository = self.branch.repository
145
147
        if self.revision_id == CURRENT_REVISION:
146
148
            revision_id = self.branch.last_revision()
147
149
        else:
148
150
            revision_id = self.revision_id
 
151
        dotted = self._dotted_revnos(repository, revision_id)
149
152
        revision_cache = RevisionCache(repository, self.revisions)
150
153
        for origin, text in tree.annotate_iter(file_id):
151
154
            rev_id = origin
155
158
            else:
156
159
                try:
157
160
                    revision = revision_cache.get_revision(rev_id)
158
 
                    revno = self.dotted.get(rev_id, 'merge')
 
161
                    revno = dotted.get(rev_id, 'merge')
159
162
                    if len(revno) > 15:
160
163
                        revno = 'merge'
161
164
                except NoSuchRevision:
178
181
 
179
182
    def _activate_selected_revision(self, w):
180
183
        rev_id = self._selected_revision()
181
 
        if not rev_id or rev_id == NULL_REVISION:
 
184
        if rev_id is None:
182
185
            return
183
186
        selected = self.revisions[rev_id]
184
 
        self.revisionview.set_revision(selected)
 
187
        self.logview.set_revision(selected)
185
188
        if (len(selected.parent_ids) != 0 and selected.parent_ids[0] not in
186
189
            self._no_back):
187
190
            enable_back = True
190
193
        self.back_button.set_sensitive(enable_back)
191
194
 
192
195
    def _create(self):
193
 
        self.revisionview = self._create_log_view()
 
196
        self.logview = self._create_log_view()
194
197
        self.annoview = self._create_annotate_view()
195
198
 
196
199
        vbox = gtk.VBox(False)
212
215
        hbox.pack_start(self.back_button, expand=False, fill=True)
213
216
        self.forward_button = self._create_forward_button()
214
217
        hbox.pack_start(self.forward_button, expand=False, fill=True)
215
 
        self.find_button = self._create_find_button()
216
 
        hbox.pack_start(self.find_button, expand=False, fill=True)
217
 
        self.goto_button = self._create_goto_button()
218
 
        hbox.pack_start(self.goto_button, expand=False, fill=True)
219
218
        hbox.show()
220
219
        vbox.pack_start(hbox, expand=False, fill=True)
221
 
 
 
220
        
222
221
        self.pane = pane = gtk.VPaned()
223
222
        pane.add1(swbox)
224
 
        pane.add2(self.revisionview)
 
223
        pane.add2(self.logview)
225
224
        pane.show()
226
225
        vbox.pack_start(pane, expand=True, fill=True)
227
226
 
238
237
 
239
238
        self.add(vbox)
240
239
 
241
 
    def _search_by_text(self, *ignored): # (accel_group, window, key, modifiers):
 
240
    def _search_by_text(self, accel_group, window, key, modifiers):
242
241
        self._search.show_for('text')
243
242
        self._search.set_target(self.annoview, TEXT_LINE_COL)
244
243
 
245
 
    def _search_by_line(self, *ignored): # accel_group, window, key, modifiers):
 
244
    def _search_by_line(self, accel_group, window, key, modifiers):
246
245
        self._search.show_for('line')
247
246
        self._search.set_target(self.annoview, LINE_NUM_COL)
248
247
 
249
 
    def line_diff(self, tv, path, tvc):
 
248
    def row_diff(self, tv, path, tvc):
250
249
        row = path[0]
251
250
        revision = self.annotations[row]
252
251
        repository = self.branch.repository
260
259
            else:
261
260
                tree2 = repository.revision_tree(NULL_REVISION)
262
261
        from bzrlib.plugins.gtk.diff import DiffWindow
263
 
        window = DiffWindow(self)
264
 
        window.set_diff("Diff for line %d" % (row+1), tree1, tree2)
 
262
        window = DiffWindow()
 
263
        window.set_diff("Diff for row %d" % (row+1), tree1, tree2)
265
264
        window.set_file(tree1.id2path(self.file_id))
266
265
        window.show()
267
266
 
271
270
        tv.set_rules_hint(False)
272
271
        tv.connect("cursor-changed", self._activate_selected_revision)
273
272
        tv.show()
274
 
        tv.connect("row-activated", self.line_diff)
 
273
        tv.connect("row-activated", self.row_diff)
275
274
 
276
275
        cell = gtk.CellRendererText()
277
276
        cell.set_property("xalign", 1.0)
318
317
        col.add_attribute(cell, "text", TEXT_LINE_COL)
319
318
        tv.append_column(col)
320
319
 
321
 
        # interactive substring search
322
 
        def search_equal_func(model, column, key, iter):
323
 
            return model.get_value(iter, TEXT_LINE_COL).lower().find(key.lower()) == -1
324
 
 
325
 
        tv.set_enable_search(True)
326
 
        tv.set_search_equal_func(search_equal_func)
 
320
        # FIXME: Now that C-f is now used for search by text we
 
321
        # may as well disable the auto search.
 
322
        tv.set_search_column(LINE_NUM_COL)
327
323
 
328
324
        return tv
329
325
 
330
326
    def _create_log_view(self):
331
 
        lv = RevisionView(self._branch)
 
327
        lv = LogView()
332
328
        lv.show()
333
329
        return lv
334
330
 
351
347
        button.set_sensitive(False)
352
348
        return button
353
349
 
354
 
    def _create_find_button(self):
355
 
        button = gtk.Button()
356
 
        button.set_use_stock(True)
357
 
        button.set_label("gtk-find")
358
 
        button.set_tooltip_text("Search for text (Ctrl+F)")
359
 
        button.connect("clicked", self._search_by_text)
360
 
        button.set_relief(gtk.RELIEF_NONE)
361
 
        button.show()
362
 
        button.set_sensitive(True)
363
 
        return button
364
 
 
365
 
    def _create_goto_button(self):
366
 
        button = gtk.Button()
367
 
        button.set_label("Goto Line")
368
 
        button.set_tooltip_text("Scroll to a line by entering its number (Ctrl+G)")
369
 
        button.connect("clicked", self._search_by_line)
370
 
        button.set_relief(gtk.RELIEF_NONE)
371
 
        button.show()
372
 
        button.set_sensitive(True)
373
 
        return button
374
 
 
375
350
    def go_back(self):
376
351
        last_tree = self.tree
377
352
        rev_id = self._selected_revision()
417
392
                return j - i
418
393
 
419
394
 
420
 
class FakeRevision(object):
 
395
 
 
396
class FakeRevision:
421
397
    """ A fake revision.
422
398
 
423
399
    For when a revision is referenced but not present.
432
408
        self.timezone = 0
433
409
        self.properties = {}
434
410
 
435
 
    def get_apparent_authors(self):
436
 
        return [self.committer]
437
 
 
438
411
 
439
412
class RevisionCache(object):
440
413
    """A caching revision source"""
441
 
 
442
414
    def __init__(self, real_source, seed_cache=None):
443
415
        self.__real_source = real_source
444
416
        if seed_cache is None:
535
507
 
536
508
    def _match(self, model, iterator, column):
537
509
        matching_case = self._match_case.get_active()
538
 
        cell_value, = model.get(iterator, column)
 
510
        string, = model.get(iterator, column)
539
511
        key = self._entry.get_text()
540
 
        if column == LINE_NUM_COL:
541
 
            # FIXME: For goto-line there are faster algorithms than searching 
542
 
            # every line til we find the right one! -- mbp 2011-01-27
543
 
            return key.strip() == str(cell_value)
544
 
        elif self._regexp.get_active():
 
512
        if self._regexp.get_active():
545
513
            if matching_case:
546
 
                match = re.compile(key).search(cell_value, 1)
 
514
                match = re.compile(key).search(string, 1)
547
515
            else:
548
 
                match = re.compile(key, re.I).search(cell_value, 1)
 
516
                match = re.compile(key, re.I).search(string, 1)
549
517
        else:
550
518
            if not matching_case:
551
 
                cell_value = cell_value.lower()
 
519
                string = string.lower()
552
520
                key = key.lower()
553
 
            match = cell_value.find(key) != -1
 
521
            match = string.find(key) != -1
554
522
 
555
523
        return match
556
524