/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: Curtis Hovey
  • Date: 2012-02-05 05:14:11 UTC
  • mto: This revision was merged to the branch mainline in revision 775.
  • Revision ID: sinzui.is@verizon.net-20120205051411-y9ra08wae1wsfv52
Remove unneeded gtksourceview1 support.

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
31
30
from bzrlib.plugins.gtk.revisionview import RevisionView
32
31
from bzrlib.plugins.gtk.window import Window
33
32
 
45
44
class GAnnotateWindow(Window):
46
45
    """Annotate window."""
47
46
 
48
 
    def __init__(self, all=False, plain=False, parent=None):
 
47
    def __init__(self, all=False, plain=False, parent=None, branch=None):
49
48
        self.all = all
50
49
        self.plain = plain
51
 
        
52
 
        Window.__init__(self, parent)
53
 
        
54
 
        self.set_icon(self.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_BUTTON))
 
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))
55
56
        self.annotate_colormap = AnnotateColorSaturation()
56
57
 
57
58
        self._create()
67
68
        self.revisionview.set_file_id(file_id)
68
69
        self.revision_id = getattr(tree, 'get_revision_id', 
69
70
                                   lambda: CURRENT_REVISION)()
70
 
        
 
71
 
71
72
        # [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
 
        
 
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
 
79
80
        last_seen = None
80
81
        try:
81
82
            branch.lock_read()
82
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)
83
88
            for line_no, (revision, revno, line)\
84
 
                    in enumerate(self._annotate(tree, file_id)):
 
89
                in enumerate(self._annotate(tree, file_id)):
85
90
                if revision.revision_id == last_seen and not self.all:
86
91
                    revno = author = ""
87
92
                else:
88
93
                    last_seen = revision.revision_id
89
 
                    author = revision.get_apparent_author()
 
94
                    author = ", ".join(revision.get_apparent_authors())
90
95
 
91
96
                if revision.revision_id not in self.revisions:
92
97
                    self.revisions[revision.revision_id] = revision
97
102
                                       revno,
98
103
                                       None,
99
104
                                       line.rstrip("\r\n")
100
 
                                      ])
 
105
                                       ])
101
106
                self.annotations.append(revision)
102
107
 
103
108
            if not self.plain:
109
114
 
110
115
        self.annoview.set_model(self.annomodel)
111
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)
112
120
 
113
121
    def jump_to_line(self, lineno):
114
122
        if lineno > len(self.annomodel) or lineno < 1:
117
125
            # bar?
118
126
            print("gannotate: Line number %d does't exist. Defaulting to "
119
127
                  "line 1." % lineno)
120
 
            return
 
128
            return
121
129
        else:
122
130
            row = lineno - 1
123
131
 
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
 
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)
139
135
 
140
136
    def _annotate(self, tree, file_id):
141
137
        current_revision = FakeRevision(CURRENT_REVISION)
143
139
        current_revision.timestamp = time.time()
144
140
        current_revision.message = '[Not yet committed]'
145
141
        current_revision.parent_ids = tree.get_parent_ids()
146
 
        current_revision.properties['branch-nick'] = self.branch.nick
 
142
        current_revision.properties['branch-nick'] = self.branch._get_nick(local=True)
147
143
        current_revno = '%d?' % (self.branch.revno() + 1)
148
144
        repository = self.branch.repository
149
145
        if self.revision_id == CURRENT_REVISION:
150
146
            revision_id = self.branch.last_revision()
151
147
        else:
152
148
            revision_id = self.revision_id
153
 
        dotted = self._dotted_revnos(repository, revision_id)
154
149
        revision_cache = RevisionCache(repository, self.revisions)
155
150
        for origin, text in tree.annotate_iter(file_id):
156
151
            rev_id = origin
160
155
            else:
161
156
                try:
162
157
                    revision = revision_cache.get_revision(rev_id)
163
 
                    revno = dotted.get(rev_id, 'merge')
 
158
                    revno = self.dotted.get(rev_id, 'merge')
164
159
                    if len(revno) > 15:
165
160
                        revno = 'merge'
166
161
                except NoSuchRevision:
172
167
    def _highlight_annotation(self, model, path, iter, now):
173
168
        revision_id, = model.get(iter, REVISION_ID_COL)
174
169
        revision = self.revisions[revision_id]
175
 
        model.set(iter, HIGHLIGHT_COLOR_COL,
176
 
                  self.annotate_colormap.get_color(revision, now))
 
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)
177
173
 
178
174
    def _selected_revision(self):
179
175
        (path, col) = self.annoview.get_cursor()
183
179
 
184
180
    def _activate_selected_revision(self, w):
185
181
        rev_id = self._selected_revision()
186
 
        if rev_id is None:
 
182
        if not rev_id or rev_id == NULL_REVISION:
187
183
            return
188
184
        selected = self.revisions[rev_id]
189
185
        self.revisionview.set_revision(selected)
198
194
        self.revisionview = self._create_log_view()
199
195
        self.annoview = self._create_annotate_view()
200
196
 
201
 
        vbox = gtk.VBox(False)
 
197
        vbox = Gtk.VBox(homogeneous=False, spacing=0)
202
198
        vbox.show()
203
199
 
204
 
        sw = gtk.ScrolledWindow()
205
 
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
206
 
        sw.set_shadow_type(gtk.SHADOW_IN)
 
200
        sw = Gtk.ScrolledWindow()
 
201
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
 
202
        sw.set_shadow_type(Gtk.ShadowType.IN)
207
203
        sw.add(self.annoview)
208
204
        self.annoview.gwindow = self
209
205
        sw.show()
210
206
 
211
 
        swbox = gtk.VBox()
212
 
        swbox.pack_start(sw)
 
207
        swbox = Gtk.VBox()
 
208
        swbox.pack_start(sw, True, True, 0)
213
209
        swbox.show()
214
210
 
215
 
        hbox = gtk.HBox(False, 6)
 
211
        hbox = Gtk.HBox(homogeneous=False, spacing=6)
216
212
        self.back_button = self._create_back_button()
217
 
        hbox.pack_start(self.back_button, expand=False, fill=True)
 
213
        hbox.pack_start(self.back_button, False, True, 0)
218
214
        self.forward_button = self._create_forward_button()
219
 
        hbox.pack_start(self.forward_button, expand=False, fill=True)
 
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)
220
220
        hbox.show()
221
 
        vbox.pack_start(hbox, expand=False, fill=True)
222
 
        
223
 
        self.pane = pane = gtk.VPaned()
 
221
        vbox.pack_start(hbox, False, True, 0)
 
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, expand=True, fill=True)
 
227
        vbox.pack_start(pane, True, True, 0)
228
228
 
229
229
        self._search = SearchBox()
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,
 
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,
234
234
                             self._search_by_text)
235
 
        accels.connect_group(gtk.keysyms.g, gtk.gdk.CONTROL_MASK,
236
 
                             gtk.ACCEL_LOCKED,
 
235
        accels.connect(Gdk.KEY_g, Gdk.ModifierType.CONTROL_MASK,
 
236
                             Gtk.AccelFlags.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, accel_group, window, key, modifiers):
 
242
    def _search_by_text(self, *ignored): # (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, accel_group, window, key, modifiers):
 
246
    def _search_by_line(self, *ignored): # 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 row_diff(self, tv, path, tvc):
251
 
        row = path[0]
 
250
    def line_diff(self, tv, path, tvc):
 
251
        row = path.get_indices()[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()
265
 
        window.set_diff("Diff for row %d" % (row+1), tree1, tree2)
 
264
        window = DiffWindow(self)
 
265
        window.set_diff("Diff for line %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.row_diff)
 
275
        tv.connect("row-activated", self.line_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.STATE_NORMAL])
283
 
        col = gtk.TreeViewColumn()
 
282
                          tv.get_style().bg[Gtk.StateType.NORMAL])
 
283
        col = Gtk.TreeViewColumn()
284
284
        col.set_resizable(False)
285
 
        col.pack_start(cell, expand=True)
 
285
        col.pack_start(cell, 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.ELLIPSIZE_END)
 
291
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
292
292
        cell.set_property("cell-background-gdk",
293
 
                          self.get_style().bg[gtk.STATE_NORMAL])
294
 
        col = gtk.TreeViewColumn("Committer")
 
293
                          self.get_style().bg[Gtk.StateType.NORMAL])
 
294
        col = Gtk.TreeViewColumn("Committer")
295
295
        col.set_resizable(True)
296
 
        col.pack_start(cell, expand=True)
 
296
        col.pack_start(cell, 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.STATE_NORMAL])
305
 
        col = gtk.TreeViewColumn("Revno")
 
304
                          self.get_style().bg[Gtk.StateType.NORMAL])
 
305
        col = Gtk.TreeViewColumn("Revno")
306
306
        col.set_resizable(False)
307
 
        col.pack_start(cell, expand=True)
 
307
        col.pack_start(cell, 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, expand=True)
 
316
        col.pack_start(cell, 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
 
        # 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)
 
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)
325
328
 
326
329
        return tv
327
330
 
328
331
    def _create_log_view(self):
329
 
        lv = RevisionView()
 
332
        lv = RevisionView(self._branch)
330
333
        lv.show()
331
334
        return lv
332
335
 
333
336
    def _create_back_button(self):
334
 
        button = gtk.Button()
 
337
        button = Gtk.Button()
335
338
        button.set_use_stock(True)
336
339
        button.set_label("gtk-go-back")
337
340
        button.connect("clicked", lambda w: self.go_back())
338
 
        button.set_relief(gtk.RELIEF_NONE)
 
341
        button.set_relief(Gtk.ReliefStyle.NONE)
339
342
        button.show()
340
343
        return button
341
344
 
342
345
    def _create_forward_button(self):
343
 
        button = gtk.Button()
 
346
        button = Gtk.Button()
344
347
        button.set_use_stock(True)
345
348
        button.set_label("gtk-go-forward")
346
349
        button.connect("clicked", lambda w: self.go_forward())
347
 
        button.set_relief(gtk.RELIEF_NONE)
 
350
        button.set_relief(Gtk.ReliefStyle.NONE)
348
351
        button.show()
349
352
        button.set_sensitive(False)
350
353
        return button
351
354
 
 
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
 
352
376
    def go_back(self):
353
377
        last_tree = self.tree
354
378
        rev_id = self._selected_revision()
373
397
        rev_id = self._selected_revision()
374
398
        if self.file_id in target_tree:
375
399
            offset = self.get_scroll_offset(target_tree)
376
 
            (row,), col = self.annoview.get_cursor()
 
400
            path, col = self.annoview.get_cursor()
 
401
            (row,) = path.get_indices()
377
402
            self.annotate(target_tree, self.branch, self.file_id)
378
403
            new_row = row+offset
379
404
            if new_row < 0:
380
405
                new_row = 0
381
 
            self.annoview.set_cursor(new_row)
 
406
            new_path = Gtk.TreePath(path=new_row)
 
407
            self.annoview.set_cursor(new_path, None, False)
382
408
            return True
383
409
        else:
384
410
            return False
386
412
    def get_scroll_offset(self, tree):
387
413
        old = self.tree.get_file(self.file_id)
388
414
        new = tree.get_file(self.file_id)
389
 
        (row,), col = self.annoview.get_cursor()
 
415
        path, col = self.annoview.get_cursor()
 
416
        (row,) = path.get_indices()
390
417
        matcher = patiencediff.PatienceSequenceMatcher(None, old.readlines(),
391
418
                                                       new.readlines())
392
419
        for i, j, n in matcher.get_matching_blocks():
394
421
                return j - i
395
422
 
396
423
 
397
 
class FakeRevision:
 
424
class FakeRevision(object):
398
425
    """ A fake revision.
399
426
 
400
427
    For when a revision is referenced but not present.
409
436
        self.timezone = 0
410
437
        self.properties = {}
411
438
 
412
 
    def get_apparent_author(self):
413
 
        return self.committer
 
439
    def get_apparent_authors(self):
 
440
        return [self.committer]
414
441
 
415
442
 
416
443
class RevisionCache(object):
417
444
    """A caching revision source"""
 
445
 
418
446
    def __init__(self, real_source, seed_cache=None):
419
447
        self.__real_source = real_source
420
448
        if seed_cache is None:
428
456
            self.__cache[revision_id] = revision
429
457
        return self.__cache[revision_id]
430
458
 
431
 
class SearchBox(gtk.HBox):
 
459
 
 
460
class SearchBox(Gtk.HBox):
432
461
    """A button box for searching in text or lines of annotations"""
433
462
    def __init__(self):
434
 
        gtk.HBox.__init__(self, False, 6)
 
463
        super(SearchBox, self).__init__(homogeneous=False, spacing=6)
435
464
 
436
465
        # Close button
437
 
        button = gtk.Button()
438
 
        image = gtk.Image()
439
 
        image.set_from_stock('gtk-stop', gtk.ICON_SIZE_BUTTON)
 
466
        button = Gtk.Button()
 
467
        image = Gtk.Image()
 
468
        image.set_from_stock('gtk-stop', Gtk.IconSize.BUTTON)
440
469
        button.set_image(image)
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)
 
470
        button.set_relief(Gtk.ReliefStyle.NONE)
 
471
        button.connect("clicked", lambda w: self.hide())
 
472
        self.pack_start(button, False, False, 0)
444
473
 
445
474
        # Search entry
446
 
        label = gtk.Label()
 
475
        label = Gtk.Label()
447
476
        self._label = label
448
 
        self.pack_start(label, expand=False, fill=False)
 
477
        self.pack_start(label, False, False, 0)
449
478
 
450
 
        entry = gtk.Entry()
 
479
        entry = Gtk.Entry()
451
480
        self._entry = entry
452
481
        entry.connect("activate", lambda w, d: self._do_search(d),
453
482
                      'forward')
454
 
        self.pack_start(entry, expand=False, fill=False)
 
483
        self.pack_start(entry, False, False, 0)
455
484
 
456
485
        # Next/previous buttons
457
 
        button = gtk.Button('_Next')
458
 
        image = gtk.Image()
459
 
        image.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_BUTTON)
 
486
        button = Gtk.Button('_Next')
 
487
        image = Gtk.Image()
 
488
        image.set_from_stock('gtk-go-forward', Gtk.IconSize.BUTTON)
460
489
        button.set_image(image)
461
490
        button.connect("clicked", lambda w, d: self._do_search(d),
462
491
                       'forward')
463
 
        self.pack_start(button, expand=False, fill=False)
 
492
        self.pack_start(button, False, False, 0)
464
493
 
465
 
        button = gtk.Button('_Previous')
466
 
        image = gtk.Image()
467
 
        image.set_from_stock('gtk-go-back', gtk.ICON_SIZE_BUTTON)
 
494
        button = Gtk.Button('_Previous')
 
495
        image = Gtk.Image()
 
496
        image.set_from_stock('gtk-go-back', Gtk.IconSize.BUTTON)
468
497
        button.set_image(image)
469
498
        button.connect("clicked", lambda w, d: self._do_search(d),
470
499
                       'backward')
471
 
        self.pack_start(button, expand=False, fill=False)
 
500
        self.pack_start(button, False, False, 0)
472
501
 
473
502
        # Search options
474
 
        check = gtk.CheckButton('Match case')
 
503
        check = Gtk.CheckButton('Match case')
475
504
        self._match_case = check
476
 
        self.pack_start(check, expand=False, fill=False)
 
505
        self.pack_start(check, False, False, 0)
477
506
 
478
 
        check = gtk.CheckButton('Regexp')
 
507
        check = Gtk.CheckButton('Regexp')
479
508
        check.connect("toggled", lambda w: self._set_label())
480
509
        self._regexp = check
481
 
        self.pack_start(check, expand=False, fill=False)
 
510
        self.pack_start(check, False, False, 0)
482
511
 
483
512
        self._view = None
484
513
        self._column = None
511
540
 
512
541
    def _match(self, model, iterator, column):
513
542
        matching_case = self._match_case.get_active()
514
 
        string, = model.get(iterator, column)
 
543
        cell_value, = model.get(iterator, column)
515
544
        key = self._entry.get_text()
516
 
        if self._regexp.get_active():
 
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():
517
550
            if matching_case:
518
 
                match = re.compile(key).search(string, 1)
 
551
                match = re.compile(key).search(cell_value, 1)
519
552
            else:
520
 
                match = re.compile(key, re.I).search(string, 1)
 
553
                match = re.compile(key, re.I).search(cell_value, 1)
521
554
        else:
522
555
            if not matching_case:
523
 
                string = string.lower()
 
556
                cell_value = cell_value.lower()
524
557
                key = key.lower()
525
 
            match = string.find(key) != -1
 
558
            match = cell_value.find(key) != -1
526
559
 
527
560
        return match
528
561
 
560
593
        for row in iterate(model, start):
561
594
            if self._match(model, row, self._column):
562
595
                path = model.get_path(row)
563
 
                self._view.set_cursor(path)
 
596
                self._view.set_cursor(path, None, False)
564
597
                self._view.scroll_to_cell(path, use_align=True)
565
598
                break