/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: 2012-07-09 15:23:26 UTC
  • mto: This revision was merged to the branch mainline in revision 794.
  • Revision ID: jelmer@samba.org-20120709152326-dzxb8zoz0btull7n
Remove bzr-notify.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
import time
18
18
 
19
 
import pygtk
20
 
pygtk.require("2.0")
21
 
import gobject
22
 
import gtk
23
 
import pango
 
19
from gi.repository import GObject
 
20
from gi.repository import Gdk
 
21
from gi.repository import Gtk
 
22
from gi.repository import Pango
24
23
import re
25
24
 
26
 
from bzrlib import patiencediff, tsort
 
25
from bzrlib import patiencediff
27
26
from bzrlib.errors import NoSuchRevision
28
27
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
29
28
 
30
 
from colormap import AnnotateColorMap, AnnotateColorSaturation
 
29
from bzrlib.plugins.gtk.annotate.colormap import AnnotateColorSaturation
 
30
from bzrlib.plugins.gtk.i18n import _i18n
31
31
from bzrlib.plugins.gtk.revisionview import RevisionView
32
32
from bzrlib.plugins.gtk.window import Window
33
33
 
45
45
class GAnnotateWindow(Window):
46
46
    """Annotate window."""
47
47
 
48
 
    def __init__(self, all=False, plain=False, parent=None):
 
48
    def __init__(self, all=False, plain=False, parent=None, branch=None):
49
49
        self.all = all
50
50
        self.plain = plain
51
 
        
52
 
        Window.__init__(self, parent)
53
 
        
54
 
        self.set_icon(self.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_BUTTON))
 
51
        self._branch = branch
 
52
 
 
53
        super(GAnnotateWindow, self).__init__(parent=parent)
 
54
 
 
55
        self.set_icon(
 
56
            self.render_icon_pixbuf(Gtk.STOCK_FIND, Gtk.IconSize.BUTTON))
55
57
        self.annotate_colormap = AnnotateColorSaturation()
56
58
 
57
59
        self._create()
67
69
        self.revisionview.set_file_id(file_id)
68
70
        self.revision_id = getattr(tree, 'get_revision_id', 
69
71
                                   lambda: CURRENT_REVISION)()
70
 
        
 
72
 
71
73
        # [revision id, line number, author, revno, highlight color, line]
72
 
        self.annomodel = gtk.ListStore(gobject.TYPE_STRING,
73
 
                                       gobject.TYPE_STRING,
74
 
                                       gobject.TYPE_STRING,
75
 
                                       gobject.TYPE_STRING,
76
 
                                       gobject.TYPE_STRING,
77
 
                                       gobject.TYPE_STRING)
78
 
        
 
74
        self.annomodel = Gtk.ListStore(GObject.TYPE_STRING,
 
75
                                       GObject.TYPE_INT,
 
76
                                       GObject.TYPE_STRING,
 
77
                                       GObject.TYPE_STRING,
 
78
                                       GObject.TYPE_STRING,
 
79
                                       GObject.TYPE_STRING)
 
80
 
79
81
        last_seen = None
80
82
        try:
81
83
            branch.lock_read()
85
87
            for revision_id, revno in revno_map.iteritems():
86
88
                self.dotted[revision_id] = '.'.join(str(num) for num in revno)
87
89
            for line_no, (revision, revno, line)\
88
 
                    in enumerate(self._annotate(tree, file_id)):
 
90
                in enumerate(self._annotate(tree, file_id)):
89
91
                if revision.revision_id == last_seen and not self.all:
90
92
                    revno = author = ""
91
93
                else:
92
94
                    last_seen = revision.revision_id
93
 
                    author = revision.get_apparent_author()
 
95
                    author = ", ".join(revision.get_apparent_authors())
94
96
 
95
97
                if revision.revision_id not in self.revisions:
96
98
                    self.revisions[revision.revision_id] = revision
101
103
                                       revno,
102
104
                                       None,
103
105
                                       line.rstrip("\r\n")
104
 
                                      ])
 
106
                                       ])
105
107
                self.annotations.append(revision)
106
108
 
107
109
            if not self.plain:
124
126
            # bar?
125
127
            print("gannotate: Line number %d does't exist. Defaulting to "
126
128
                  "line 1." % lineno)
127
 
            return
 
129
            return
128
130
        else:
129
131
            row = lineno - 1
130
132
 
131
 
        self.annoview.set_cursor(row)
132
 
        self.annoview.scroll_to_cell(row, use_align=True)
133
 
 
 
133
        tree_path = Gtk.TreePath(path=row)
 
134
        self.annoview.set_cursor(tree_path, None, False)
 
135
        self.annoview.scroll_to_cell(tree_path, use_align=True)
134
136
 
135
137
    def _annotate(self, tree, file_id):
136
138
        current_revision = FakeRevision(CURRENT_REVISION)
138
140
        current_revision.timestamp = time.time()
139
141
        current_revision.message = '[Not yet committed]'
140
142
        current_revision.parent_ids = tree.get_parent_ids()
141
 
        current_revision.properties['branch-nick'] = self.branch.nick
 
143
        current_revision.properties['branch-nick'] = self.branch._get_nick(local=True)
142
144
        current_revno = '%d?' % (self.branch.revno() + 1)
143
145
        repository = self.branch.repository
144
146
        if self.revision_id == CURRENT_REVISION:
166
168
    def _highlight_annotation(self, model, path, iter, now):
167
169
        revision_id, = model.get(iter, REVISION_ID_COL)
168
170
        revision = self.revisions[revision_id]
169
 
        model.set(iter, HIGHLIGHT_COLOR_COL,
170
 
                  self.annotate_colormap.get_color(revision, now))
 
171
        # XXX sinzui 2011-08-12: What does get_color return?
 
172
        color = self.annotate_colormap.get_color(revision, now)
 
173
        model.set_value(iter, HIGHLIGHT_COLOR_COL, color)
171
174
 
172
175
    def _selected_revision(self):
173
176
        (path, col) = self.annoview.get_cursor()
177
180
 
178
181
    def _activate_selected_revision(self, w):
179
182
        rev_id = self._selected_revision()
180
 
        if rev_id is None:
 
183
        if not rev_id or rev_id == NULL_REVISION:
181
184
            return
182
185
        selected = self.revisions[rev_id]
183
186
        self.revisionview.set_revision(selected)
192
195
        self.revisionview = self._create_log_view()
193
196
        self.annoview = self._create_annotate_view()
194
197
 
195
 
        vbox = gtk.VBox(False)
 
198
        vbox = Gtk.VBox(homogeneous=False, spacing=0)
196
199
        vbox.show()
197
200
 
198
 
        sw = gtk.ScrolledWindow()
199
 
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
200
 
        sw.set_shadow_type(gtk.SHADOW_IN)
 
201
        sw = Gtk.ScrolledWindow()
 
202
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
 
203
        sw.set_shadow_type(Gtk.ShadowType.IN)
201
204
        sw.add(self.annoview)
202
205
        self.annoview.gwindow = self
203
206
        sw.show()
204
207
 
205
 
        swbox = gtk.VBox()
206
 
        swbox.pack_start(sw)
 
208
        swbox = Gtk.VBox()
 
209
        swbox.pack_start(sw, True, True, 0)
207
210
        swbox.show()
208
211
 
209
 
        hbox = gtk.HBox(False, 6)
 
212
        hbox = Gtk.HBox(homogeneous=False, spacing=6)
210
213
        self.back_button = self._create_back_button()
211
 
        hbox.pack_start(self.back_button, expand=False, fill=True)
 
214
        hbox.pack_start(self.back_button, False, True, 0)
212
215
        self.forward_button = self._create_forward_button()
213
 
        hbox.pack_start(self.forward_button, expand=False, fill=True)
 
216
        hbox.pack_start(self.forward_button, False, True, 0)
 
217
        self.find_button = self._create_find_button()
 
218
        hbox.pack_start(self.find_button, False, True, 0)
 
219
        self.goto_button = self._create_goto_button()
 
220
        hbox.pack_start(self.goto_button, False, True, 0)
214
221
        hbox.show()
215
 
        vbox.pack_start(hbox, expand=False, fill=True)
216
 
        
217
 
        self.pane = pane = gtk.VPaned()
 
222
        vbox.pack_start(hbox, False, True, 0)
 
223
 
 
224
        self.pane = pane = Gtk.Paned.new(Gtk.Orientation.VERTICAL)
218
225
        pane.add1(swbox)
219
226
        pane.add2(self.revisionview)
220
227
        pane.show()
221
 
        vbox.pack_start(pane, expand=True, fill=True)
 
228
        vbox.pack_start(pane, True, True, 0)
222
229
 
223
230
        self._search = SearchBox()
224
 
        swbox.pack_start(self._search, expand=False, fill=True)
225
 
        accels = gtk.AccelGroup()
226
 
        accels.connect_group(gtk.keysyms.f, gtk.gdk.CONTROL_MASK,
227
 
                             gtk.ACCEL_LOCKED,
 
231
        swbox.pack_start(self._search, False, True, 0)
 
232
        accels = Gtk.AccelGroup()
 
233
        accels.connect(Gdk.KEY_f, Gdk.ModifierType.CONTROL_MASK,
 
234
                             Gtk.AccelFlags.LOCKED,
228
235
                             self._search_by_text)
229
 
        accels.connect_group(gtk.keysyms.g, gtk.gdk.CONTROL_MASK,
230
 
                             gtk.ACCEL_LOCKED,
 
236
        accels.connect(Gdk.KEY_g, Gdk.ModifierType.CONTROL_MASK,
 
237
                             Gtk.AccelFlags.LOCKED,
231
238
                             self._search_by_line)
232
239
        self.add_accel_group(accels)
233
240
 
234
241
        self.add(vbox)
235
242
 
236
 
    def _search_by_text(self, accel_group, window, key, modifiers):
 
243
    def _search_by_text(self, *ignored): # (accel_group, window, key, modifiers):
237
244
        self._search.show_for('text')
238
245
        self._search.set_target(self.annoview, TEXT_LINE_COL)
239
246
 
240
 
    def _search_by_line(self, accel_group, window, key, modifiers):
 
247
    def _search_by_line(self, *ignored): # accel_group, window, key, modifiers):
241
248
        self._search.show_for('line')
242
249
        self._search.set_target(self.annoview, LINE_NUM_COL)
243
250
 
244
251
    def line_diff(self, tv, path, tvc):
245
 
        row = path[0]
 
252
        row = path.get_indices()[0]
246
253
        revision = self.annotations[row]
247
254
        repository = self.branch.repository
248
255
        if revision.revision_id == CURRENT_REVISION:
255
262
            else:
256
263
                tree2 = repository.revision_tree(NULL_REVISION)
257
264
        from bzrlib.plugins.gtk.diff import DiffWindow
258
 
        window = DiffWindow()
 
265
        window = DiffWindow(self)
259
266
        window.set_diff("Diff for line %d" % (row+1), tree1, tree2)
260
267
        window.set_file(tree1.id2path(self.file_id))
261
268
        window.show()
262
269
 
263
270
 
264
271
    def _create_annotate_view(self):
265
 
        tv = gtk.TreeView()
 
272
        tv = Gtk.TreeView()
266
273
        tv.set_rules_hint(False)
267
274
        tv.connect("cursor-changed", self._activate_selected_revision)
268
275
        tv.show()
269
276
        tv.connect("row-activated", self.line_diff)
270
277
 
271
 
        cell = gtk.CellRendererText()
 
278
        cell = Gtk.CellRendererText()
272
279
        cell.set_property("xalign", 1.0)
273
280
        cell.set_property("ypad", 0)
274
281
        cell.set_property("family", "Monospace")
275
282
        cell.set_property("cell-background-gdk",
276
 
                          tv.get_style().bg[gtk.STATE_NORMAL])
277
 
        col = gtk.TreeViewColumn()
 
283
                          tv.get_style().bg[Gtk.StateType.NORMAL])
 
284
        col = Gtk.TreeViewColumn()
278
285
        col.set_resizable(False)
279
 
        col.pack_start(cell, expand=True)
 
286
        col.pack_start(cell, True)
280
287
        col.add_attribute(cell, "text", LINE_NUM_COL)
281
288
        tv.append_column(col)
282
289
 
283
 
        cell = gtk.CellRendererText()
 
290
        cell = Gtk.CellRendererText()
284
291
        cell.set_property("ypad", 0)
285
 
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
292
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
286
293
        cell.set_property("cell-background-gdk",
287
 
                          self.get_style().bg[gtk.STATE_NORMAL])
288
 
        col = gtk.TreeViewColumn("Committer")
 
294
                          self.get_style().bg[Gtk.StateType.NORMAL])
 
295
        col = Gtk.TreeViewColumn("Committer")
289
296
        col.set_resizable(True)
290
 
        col.pack_start(cell, expand=True)
 
297
        col.pack_start(cell, True)
291
298
        col.add_attribute(cell, "text", COMMITTER_COL)
292
299
        tv.append_column(col)
293
300
 
294
 
        cell = gtk.CellRendererText()
 
301
        cell = Gtk.CellRendererText()
295
302
        cell.set_property("xalign", 1.0)
296
303
        cell.set_property("ypad", 0)
297
304
        cell.set_property("cell-background-gdk",
298
 
                          self.get_style().bg[gtk.STATE_NORMAL])
299
 
        col = gtk.TreeViewColumn("Revno")
 
305
                          self.get_style().bg[Gtk.StateType.NORMAL])
 
306
        col = Gtk.TreeViewColumn("Revno")
300
307
        col.set_resizable(False)
301
 
        col.pack_start(cell, expand=True)
 
308
        col.pack_start(cell, True)
302
309
        col.add_attribute(cell, "markup", REVNO_COL)
303
310
        tv.append_column(col)
304
311
 
305
 
        cell = gtk.CellRendererText()
 
312
        cell = Gtk.CellRendererText()
306
313
        cell.set_property("ypad", 0)
307
314
        cell.set_property("family", "Monospace")
308
 
        col = gtk.TreeViewColumn()
 
315
        col = Gtk.TreeViewColumn()
309
316
        col.set_resizable(False)
310
 
        col.pack_start(cell, expand=True)
 
317
        col.pack_start(cell, True)
311
318
#        col.add_attribute(cell, "foreground", HIGHLIGHT_COLOR_COL)
312
319
        col.add_attribute(cell, "background", HIGHLIGHT_COLOR_COL)
313
320
        col.add_attribute(cell, "text", TEXT_LINE_COL)
314
321
        tv.append_column(col)
315
322
 
316
 
        # FIXME: Now that C-f is now used for search by text we
317
 
        # may as well disable the auto search.
318
 
        tv.set_search_column(LINE_NUM_COL)
 
323
        # interactive substring search
 
324
        def search_equal_func(model, column, key, iter):
 
325
            return model.get_value(iter, TEXT_LINE_COL).lower().find(key.lower()) == -1
 
326
 
 
327
        tv.set_enable_search(True)
 
328
        tv.set_search_equal_func(search_equal_func, None)
319
329
 
320
330
        return tv
321
331
 
322
332
    def _create_log_view(self):
323
 
        lv = RevisionView()
 
333
        lv = RevisionView(self._branch)
324
334
        lv.show()
325
335
        return lv
326
336
 
327
337
    def _create_back_button(self):
328
 
        button = gtk.Button()
 
338
        button = Gtk.Button()
329
339
        button.set_use_stock(True)
330
340
        button.set_label("gtk-go-back")
331
341
        button.connect("clicked", lambda w: self.go_back())
332
 
        button.set_relief(gtk.RELIEF_NONE)
 
342
        button.set_relief(Gtk.ReliefStyle.NONE)
333
343
        button.show()
334
344
        return button
335
345
 
336
346
    def _create_forward_button(self):
337
 
        button = gtk.Button()
 
347
        button = Gtk.Button()
338
348
        button.set_use_stock(True)
339
349
        button.set_label("gtk-go-forward")
340
350
        button.connect("clicked", lambda w: self.go_forward())
341
 
        button.set_relief(gtk.RELIEF_NONE)
 
351
        button.set_relief(Gtk.ReliefStyle.NONE)
342
352
        button.show()
343
353
        button.set_sensitive(False)
344
354
        return button
345
355
 
 
356
    def _create_find_button(self):
 
357
        button = Gtk.Button()
 
358
        button.set_use_stock(True)
 
359
        button.set_label("gtk-find")
 
360
        button.set_tooltip_text("Search for text (Ctrl+F)")
 
361
        button.connect("clicked", self._search_by_text)
 
362
        button.set_relief(Gtk.ReliefStyle.NONE)
 
363
        button.show()
 
364
        button.set_sensitive(True)
 
365
        return button
 
366
 
 
367
    def _create_goto_button(self):
 
368
        button = Gtk.Button()
 
369
        button.set_label("Goto Line")
 
370
        button.set_tooltip_text("Scroll to a line by entering its number (Ctrl+G)")
 
371
        button.connect("clicked", self._search_by_line)
 
372
        button.set_relief(Gtk.ReliefStyle.NONE)
 
373
        button.show()
 
374
        button.set_sensitive(True)
 
375
        return button
 
376
 
346
377
    def go_back(self):
347
378
        last_tree = self.tree
348
379
        rev_id = self._selected_revision()
367
398
        rev_id = self._selected_revision()
368
399
        if self.file_id in target_tree:
369
400
            offset = self.get_scroll_offset(target_tree)
370
 
            (row,), col = self.annoview.get_cursor()
 
401
            path, col = self.annoview.get_cursor()
 
402
            (row,) = path.get_indices()
371
403
            self.annotate(target_tree, self.branch, self.file_id)
372
404
            new_row = row+offset
373
405
            if new_row < 0:
374
406
                new_row = 0
375
 
            self.annoview.set_cursor(new_row)
 
407
            new_path = Gtk.TreePath(path=new_row)
 
408
            self.annoview.set_cursor(new_path, None, False)
376
409
            return True
377
410
        else:
378
411
            return False
380
413
    def get_scroll_offset(self, tree):
381
414
        old = self.tree.get_file(self.file_id)
382
415
        new = tree.get_file(self.file_id)
383
 
        (row,), col = self.annoview.get_cursor()
 
416
        path, col = self.annoview.get_cursor()
 
417
        (row,) = path.get_indices()
384
418
        matcher = patiencediff.PatienceSequenceMatcher(None, old.readlines(),
385
419
                                                       new.readlines())
386
420
        for i, j, n in matcher.get_matching_blocks():
388
422
                return j - i
389
423
 
390
424
 
391
 
class FakeRevision:
 
425
class FakeRevision(object):
392
426
    """ A fake revision.
393
427
 
394
428
    For when a revision is referenced but not present.
403
437
        self.timezone = 0
404
438
        self.properties = {}
405
439
 
406
 
    def get_apparent_author(self):
407
 
        return self.committer
 
440
    def get_apparent_authors(self):
 
441
        return [self.committer]
408
442
 
409
443
 
410
444
class RevisionCache(object):
411
445
    """A caching revision source"""
 
446
 
412
447
    def __init__(self, real_source, seed_cache=None):
413
448
        self.__real_source = real_source
414
449
        if seed_cache is None:
422
457
            self.__cache[revision_id] = revision
423
458
        return self.__cache[revision_id]
424
459
 
425
 
class SearchBox(gtk.HBox):
 
460
 
 
461
class SearchBox(Gtk.HBox):
426
462
    """A button box for searching in text or lines of annotations"""
427
463
    def __init__(self):
428
 
        gtk.HBox.__init__(self, False, 6)
 
464
        super(SearchBox, self).__init__(homogeneous=False, spacing=6)
429
465
 
430
466
        # Close button
431
 
        button = gtk.Button()
432
 
        image = gtk.Image()
433
 
        image.set_from_stock('gtk-stop', gtk.ICON_SIZE_BUTTON)
 
467
        button = Gtk.Button()
 
468
        image = Gtk.Image()
 
469
        image.set_from_stock('gtk-stop', Gtk.IconSize.BUTTON)
434
470
        button.set_image(image)
435
 
        button.set_relief(gtk.RELIEF_NONE)
436
 
        button.connect("clicked", lambda w: self.hide_all())
437
 
        self.pack_start(button, expand=False, fill=False)
 
471
        button.set_relief(Gtk.ReliefStyle.NONE)
 
472
        button.connect("clicked", lambda w: self.hide())
 
473
        self.pack_start(button, False, False, 0)
438
474
 
439
475
        # Search entry
440
 
        label = gtk.Label()
 
476
        label = Gtk.Label()
441
477
        self._label = label
442
 
        self.pack_start(label, expand=False, fill=False)
 
478
        self.pack_start(label, False, False, 0)
443
479
 
444
 
        entry = gtk.Entry()
 
480
        entry = Gtk.Entry()
445
481
        self._entry = entry
446
482
        entry.connect("activate", lambda w, d: self._do_search(d),
447
483
                      'forward')
448
 
        self.pack_start(entry, expand=False, fill=False)
 
484
        self.pack_start(entry, False, False, 0)
449
485
 
450
486
        # Next/previous buttons
451
 
        button = gtk.Button('_Next')
452
 
        image = gtk.Image()
453
 
        image.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_BUTTON)
 
487
        button = Gtk.Button(_i18n('_Next'), use_underline=True)
 
488
        image = Gtk.Image()
 
489
        image.set_from_stock('gtk-go-forward', Gtk.IconSize.BUTTON)
454
490
        button.set_image(image)
455
491
        button.connect("clicked", lambda w, d: self._do_search(d),
456
492
                       'forward')
457
 
        self.pack_start(button, expand=False, fill=False)
 
493
        self.pack_start(button, False, False, 0)
458
494
 
459
 
        button = gtk.Button('_Previous')
460
 
        image = gtk.Image()
461
 
        image.set_from_stock('gtk-go-back', gtk.ICON_SIZE_BUTTON)
 
495
        button = Gtk.Button(_i18n('_Previous'), use_underline=True)
 
496
        image = Gtk.Image()
 
497
        image.set_from_stock('gtk-go-back', Gtk.IconSize.BUTTON)
462
498
        button.set_image(image)
463
499
        button.connect("clicked", lambda w, d: self._do_search(d),
464
500
                       'backward')
465
 
        self.pack_start(button, expand=False, fill=False)
 
501
        self.pack_start(button, False, False, 0)
466
502
 
467
503
        # Search options
468
 
        check = gtk.CheckButton('Match case')
 
504
        check = Gtk.CheckButton('Match case')
469
505
        self._match_case = check
470
 
        self.pack_start(check, expand=False, fill=False)
 
506
        self.pack_start(check, False, False, 0)
471
507
 
472
 
        check = gtk.CheckButton('Regexp')
 
508
        check = Gtk.CheckButton('Regexp')
473
509
        check.connect("toggled", lambda w: self._set_label())
474
510
        self._regexp = check
475
 
        self.pack_start(check, expand=False, fill=False)
 
511
        self.pack_start(check, False, False, 0)
476
512
 
477
513
        self._view = None
478
514
        self._column = None
505
541
 
506
542
    def _match(self, model, iterator, column):
507
543
        matching_case = self._match_case.get_active()
508
 
        string, = model.get(iterator, column)
 
544
        cell_value, = model.get(iterator, column)
509
545
        key = self._entry.get_text()
510
 
        if self._regexp.get_active():
 
546
        if column == LINE_NUM_COL:
 
547
            # FIXME: For goto-line there are faster algorithms than searching 
 
548
            # every line til we find the right one! -- mbp 2011-01-27
 
549
            return key.strip() == str(cell_value)
 
550
        elif self._regexp.get_active():
511
551
            if matching_case:
512
 
                match = re.compile(key).search(string, 1)
 
552
                match = re.compile(key).search(cell_value, 1)
513
553
            else:
514
 
                match = re.compile(key, re.I).search(string, 1)
 
554
                match = re.compile(key, re.I).search(cell_value, 1)
515
555
        else:
516
556
            if not matching_case:
517
 
                string = string.lower()
 
557
                cell_value = cell_value.lower()
518
558
                key = key.lower()
519
 
            match = string.find(key) != -1
 
559
            match = cell_value.find(key) != -1
520
560
 
521
561
        return match
522
562
 
554
594
        for row in iterate(model, start):
555
595
            if self._match(model, row, self._column):
556
596
                path = model.get_path(row)
557
 
                self._view.set_cursor(path)
 
597
                self._view.set_cursor(path, None, False)
558
598
                self._view.scroll_to_cell(path, use_align=True)
559
599
                break