/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: Daniel Schierbeck
  • Date: 2008-01-13 14:12:49 UTC
  • mto: (423.1.2 trunk)
  • mto: This revision was merged to the branch mainline in revision 429.
  • Revision ID: daniel.schierbeck@gmail.com-20080113141249-gd0i2lknr3yik55r
Moved branch view to its own package.

Show diffs side-by-side

added added

removed removed

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