/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: 2011-07-31 15:52:43 UTC
  • mto: This revision was merged to the branch mainline in revision 741.
  • Revision ID: sinzui.is@verizon.net-20110731155243-ln8istmxbryhb4pz
Mechanical changes made by pygi.convert.sh.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
import pygtk
20
20
pygtk.require("2.0")
21
 
import gobject
22
 
import gtk
23
 
import pango
 
21
from gi.repository import GObject
 
22
from gi.repository import Gtk
 
23
from gi.repository import Pango
24
24
import re
25
25
 
26
 
from bzrlib import patiencediff, tsort
 
26
from bzrlib import patiencediff
27
27
from bzrlib.errors import NoSuchRevision
28
28
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
29
29
 
30
 
from colormap import AnnotateColorMap, AnnotateColorSaturation
 
30
from bzrlib.plugins.gtk.annotate.colormap import AnnotateColorSaturation
31
31
from bzrlib.plugins.gtk.revisionview import RevisionView
32
32
from bzrlib.plugins.gtk.window import Window
33
33
 
49
49
        self.all = all
50
50
        self.plain = plain
51
51
        self._branch = branch
52
 
        
 
52
 
53
53
        Window.__init__(self, parent)
54
 
        
55
 
        self.set_icon(self.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_BUTTON))
 
54
 
 
55
        self.set_icon(self.render_icon(Gtk.STOCK_FIND, Gtk.IconSize.BUTTON))
56
56
        self.annotate_colormap = AnnotateColorSaturation()
57
57
 
58
58
        self._create()
68
68
        self.revisionview.set_file_id(file_id)
69
69
        self.revision_id = getattr(tree, 'get_revision_id', 
70
70
                                   lambda: CURRENT_REVISION)()
71
 
        
 
71
 
72
72
        # [revision id, line number, author, revno, highlight color, line]
73
 
        self.annomodel = gtk.ListStore(gobject.TYPE_STRING,
74
 
                                       gobject.TYPE_STRING,
75
 
                                       gobject.TYPE_STRING,
76
 
                                       gobject.TYPE_STRING,
77
 
                                       gobject.TYPE_STRING,
78
 
                                       gobject.TYPE_STRING)
79
 
        
 
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
 
80
80
        last_seen = None
81
81
        try:
82
82
            branch.lock_read()
86
86
            for revision_id, revno in revno_map.iteritems():
87
87
                self.dotted[revision_id] = '.'.join(str(num) for num in revno)
88
88
            for line_no, (revision, revno, line)\
89
 
                    in enumerate(self._annotate(tree, file_id)):
 
89
                in enumerate(self._annotate(tree, file_id)):
90
90
                if revision.revision_id == last_seen and not self.all:
91
91
                    revno = author = ""
92
92
                else:
93
93
                    last_seen = revision.revision_id
94
 
                    author = revision.get_apparent_author()
 
94
                    author = ", ".join(revision.get_apparent_authors())
95
95
 
96
96
                if revision.revision_id not in self.revisions:
97
97
                    self.revisions[revision.revision_id] = revision
102
102
                                       revno,
103
103
                                       None,
104
104
                                       line.rstrip("\r\n")
105
 
                                      ])
 
105
                                       ])
106
106
                self.annotations.append(revision)
107
107
 
108
108
            if not self.plain:
125
125
            # bar?
126
126
            print("gannotate: Line number %d does't exist. Defaulting to "
127
127
                  "line 1." % lineno)
128
 
            return
 
128
            return
129
129
        else:
130
130
            row = lineno - 1
131
131
 
139
139
        current_revision.timestamp = time.time()
140
140
        current_revision.message = '[Not yet committed]'
141
141
        current_revision.parent_ids = tree.get_parent_ids()
142
 
        current_revision.properties['branch-nick'] = self.branch.nick
 
142
        current_revision.properties['branch-nick'] = self.branch._get_nick(local=True)
143
143
        current_revno = '%d?' % (self.branch.revno() + 1)
144
144
        repository = self.branch.repository
145
145
        if self.revision_id == CURRENT_REVISION:
193
193
        self.revisionview = self._create_log_view()
194
194
        self.annoview = self._create_annotate_view()
195
195
 
196
 
        vbox = gtk.VBox(False)
 
196
        vbox = Gtk.VBox(False)
197
197
        vbox.show()
198
198
 
199
 
        sw = gtk.ScrolledWindow()
200
 
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
201
 
        sw.set_shadow_type(gtk.SHADOW_IN)
 
199
        sw = Gtk.ScrolledWindow()
 
200
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
 
201
        sw.set_shadow_type(Gtk.ShadowType.IN)
202
202
        sw.add(self.annoview)
203
203
        self.annoview.gwindow = self
204
204
        sw.show()
205
205
 
206
 
        swbox = gtk.VBox()
207
 
        swbox.pack_start(sw)
 
206
        swbox = Gtk.VBox()
 
207
        swbox.pack_start(sw, True, True, 0)
208
208
        swbox.show()
209
209
 
210
 
        hbox = gtk.HBox(False, 6)
 
210
        hbox = Gtk.HBox(False, 6)
211
211
        self.back_button = self._create_back_button()
212
212
        hbox.pack_start(self.back_button, expand=False, fill=True)
213
213
        self.forward_button = self._create_forward_button()
214
214
        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)
215
219
        hbox.show()
216
220
        vbox.pack_start(hbox, expand=False, fill=True)
217
 
        
218
 
        self.pane = pane = gtk.VPaned()
 
221
 
 
222
        self.pane = pane = Gtk.VPaned()
219
223
        pane.add1(swbox)
220
224
        pane.add2(self.revisionview)
221
225
        pane.show()
223
227
 
224
228
        self._search = SearchBox()
225
229
        swbox.pack_start(self._search, expand=False, fill=True)
226
 
        accels = gtk.AccelGroup()
227
 
        accels.connect_group(gtk.keysyms.f, gtk.gdk.CONTROL_MASK,
228
 
                             gtk.ACCEL_LOCKED,
 
230
        accels = Gtk.AccelGroup()
 
231
        accels.connect_group(Gdk.KEY_f, Gdk.EventMask.CONTROL_MASK,
 
232
                             Gtk.ACCEL_LOCKED,
229
233
                             self._search_by_text)
230
 
        accels.connect_group(gtk.keysyms.g, gtk.gdk.CONTROL_MASK,
231
 
                             gtk.ACCEL_LOCKED,
 
234
        accels.connect_group(Gdk.KEY_g, Gdk.EventMask.CONTROL_MASK,
 
235
                             Gtk.ACCEL_LOCKED,
232
236
                             self._search_by_line)
233
237
        self.add_accel_group(accels)
234
238
 
235
239
        self.add(vbox)
236
240
 
237
 
    def _search_by_text(self, accel_group, window, key, modifiers):
 
241
    def _search_by_text(self, *ignored): # (accel_group, window, key, modifiers):
238
242
        self._search.show_for('text')
239
243
        self._search.set_target(self.annoview, TEXT_LINE_COL)
240
244
 
241
 
    def _search_by_line(self, accel_group, window, key, modifiers):
 
245
    def _search_by_line(self, *ignored): # accel_group, window, key, modifiers):
242
246
        self._search.show_for('line')
243
247
        self._search.set_target(self.annoview, LINE_NUM_COL)
244
248
 
256
260
            else:
257
261
                tree2 = repository.revision_tree(NULL_REVISION)
258
262
        from bzrlib.plugins.gtk.diff import DiffWindow
259
 
        window = DiffWindow()
 
263
        window = DiffWindow(self)
260
264
        window.set_diff("Diff for line %d" % (row+1), tree1, tree2)
261
265
        window.set_file(tree1.id2path(self.file_id))
262
266
        window.show()
263
267
 
264
268
 
265
269
    def _create_annotate_view(self):
266
 
        tv = gtk.TreeView()
 
270
        tv = Gtk.TreeView()
267
271
        tv.set_rules_hint(False)
268
272
        tv.connect("cursor-changed", self._activate_selected_revision)
269
273
        tv.show()
270
274
        tv.connect("row-activated", self.line_diff)
271
275
 
272
 
        cell = gtk.CellRendererText()
 
276
        cell = Gtk.CellRendererText()
273
277
        cell.set_property("xalign", 1.0)
274
278
        cell.set_property("ypad", 0)
275
279
        cell.set_property("family", "Monospace")
276
280
        cell.set_property("cell-background-gdk",
277
 
                          tv.get_style().bg[gtk.STATE_NORMAL])
278
 
        col = gtk.TreeViewColumn()
 
281
                          tv.get_style().bg[Gtk.StateType.NORMAL])
 
282
        col = Gtk.TreeViewColumn()
279
283
        col.set_resizable(False)
280
 
        col.pack_start(cell, expand=True)
 
284
        col.pack_start(cell, True, True, 0)
281
285
        col.add_attribute(cell, "text", LINE_NUM_COL)
282
286
        tv.append_column(col)
283
287
 
284
 
        cell = gtk.CellRendererText()
 
288
        cell = Gtk.CellRendererText()
285
289
        cell.set_property("ypad", 0)
286
 
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
 
290
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
287
291
        cell.set_property("cell-background-gdk",
288
 
                          self.get_style().bg[gtk.STATE_NORMAL])
289
 
        col = gtk.TreeViewColumn("Committer")
 
292
                          self.get_style().bg[Gtk.StateType.NORMAL])
 
293
        col = Gtk.TreeViewColumn("Committer")
290
294
        col.set_resizable(True)
291
 
        col.pack_start(cell, expand=True)
 
295
        col.pack_start(cell, True, True, 0)
292
296
        col.add_attribute(cell, "text", COMMITTER_COL)
293
297
        tv.append_column(col)
294
298
 
295
 
        cell = gtk.CellRendererText()
 
299
        cell = Gtk.CellRendererText()
296
300
        cell.set_property("xalign", 1.0)
297
301
        cell.set_property("ypad", 0)
298
302
        cell.set_property("cell-background-gdk",
299
 
                          self.get_style().bg[gtk.STATE_NORMAL])
300
 
        col = gtk.TreeViewColumn("Revno")
 
303
                          self.get_style().bg[Gtk.StateType.NORMAL])
 
304
        col = Gtk.TreeViewColumn("Revno")
301
305
        col.set_resizable(False)
302
 
        col.pack_start(cell, expand=True)
 
306
        col.pack_start(cell, True, True, 0)
303
307
        col.add_attribute(cell, "markup", REVNO_COL)
304
308
        tv.append_column(col)
305
309
 
306
 
        cell = gtk.CellRendererText()
 
310
        cell = Gtk.CellRendererText()
307
311
        cell.set_property("ypad", 0)
308
312
        cell.set_property("family", "Monospace")
309
 
        col = gtk.TreeViewColumn()
 
313
        col = Gtk.TreeViewColumn()
310
314
        col.set_resizable(False)
311
 
        col.pack_start(cell, expand=True)
 
315
        col.pack_start(cell, True, True, 0)
312
316
#        col.add_attribute(cell, "foreground", HIGHLIGHT_COLOR_COL)
313
317
        col.add_attribute(cell, "background", HIGHLIGHT_COLOR_COL)
314
318
        col.add_attribute(cell, "text", TEXT_LINE_COL)
315
319
        tv.append_column(col)
316
320
 
317
 
        # FIXME: Now that C-f is now used for search by text we
318
 
        # may as well disable the auto search.
319
 
        tv.set_search_column(LINE_NUM_COL)
 
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
327
 
321
328
        return tv
322
329
 
326
333
        return lv
327
334
 
328
335
    def _create_back_button(self):
329
 
        button = gtk.Button()
 
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)
 
340
        button.set_relief(Gtk.ReliefStyle.NONE)
334
341
        button.show()
335
342
        return button
336
343
 
337
344
    def _create_forward_button(self):
338
 
        button = gtk.Button()
 
345
        button = Gtk.Button()
339
346
        button.set_use_stock(True)
340
347
        button.set_label("gtk-go-forward")
341
348
        button.connect("clicked", lambda w: self.go_forward())
342
 
        button.set_relief(gtk.RELIEF_NONE)
 
349
        button.set_relief(Gtk.ReliefStyle.NONE)
343
350
        button.show()
344
351
        button.set_sensitive(False)
345
352
        return button
346
353
 
 
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.ReliefStyle.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.ReliefStyle.NONE)
 
371
        button.show()
 
372
        button.set_sensitive(True)
 
373
        return button
 
374
 
347
375
    def go_back(self):
348
376
        last_tree = self.tree
349
377
        rev_id = self._selected_revision()
389
417
                return j - i
390
418
 
391
419
 
392
 
class FakeRevision:
 
420
class FakeRevision(object):
393
421
    """ A fake revision.
394
422
 
395
423
    For when a revision is referenced but not present.
404
432
        self.timezone = 0
405
433
        self.properties = {}
406
434
 
407
 
    def get_apparent_author(self):
408
 
        return self.committer
 
435
    def get_apparent_authors(self):
 
436
        return [self.committer]
409
437
 
410
438
 
411
439
class RevisionCache(object):
412
440
    """A caching revision source"""
 
441
 
413
442
    def __init__(self, real_source, seed_cache=None):
414
443
        self.__real_source = real_source
415
444
        if seed_cache is None:
423
452
            self.__cache[revision_id] = revision
424
453
        return self.__cache[revision_id]
425
454
 
426
 
class SearchBox(gtk.HBox):
 
455
class SearchBox(Gtk.HBox):
427
456
    """A button box for searching in text or lines of annotations"""
428
457
    def __init__(self):
429
 
        gtk.HBox.__init__(self, False, 6)
 
458
        GObject.GObject.__init__(self, False, 6)
430
459
 
431
460
        # Close button
432
 
        button = gtk.Button()
433
 
        image = gtk.Image()
434
 
        image.set_from_stock('gtk-stop', gtk.ICON_SIZE_BUTTON)
 
461
        button = Gtk.Button()
 
462
        image = Gtk.Image()
 
463
        image.set_from_stock('gtk-stop', Gtk.IconSize.BUTTON)
435
464
        button.set_image(image)
436
 
        button.set_relief(gtk.RELIEF_NONE)
 
465
        button.set_relief(Gtk.ReliefStyle.NONE)
437
466
        button.connect("clicked", lambda w: self.hide_all())
438
467
        self.pack_start(button, expand=False, fill=False)
439
468
 
440
469
        # Search entry
441
 
        label = gtk.Label()
 
470
        label = Gtk.Label()
442
471
        self._label = label
443
472
        self.pack_start(label, expand=False, fill=False)
444
473
 
445
 
        entry = gtk.Entry()
 
474
        entry = Gtk.Entry()
446
475
        self._entry = entry
447
476
        entry.connect("activate", lambda w, d: self._do_search(d),
448
477
                      'forward')
449
478
        self.pack_start(entry, expand=False, fill=False)
450
479
 
451
480
        # Next/previous buttons
452
 
        button = gtk.Button('_Next')
453
 
        image = gtk.Image()
454
 
        image.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_BUTTON)
 
481
        button = Gtk.Button('_Next')
 
482
        image = Gtk.Image()
 
483
        image.set_from_stock('gtk-go-forward', Gtk.IconSize.BUTTON)
455
484
        button.set_image(image)
456
485
        button.connect("clicked", lambda w, d: self._do_search(d),
457
486
                       'forward')
458
487
        self.pack_start(button, expand=False, fill=False)
459
488
 
460
 
        button = gtk.Button('_Previous')
461
 
        image = gtk.Image()
462
 
        image.set_from_stock('gtk-go-back', gtk.ICON_SIZE_BUTTON)
 
489
        button = Gtk.Button('_Previous')
 
490
        image = Gtk.Image()
 
491
        image.set_from_stock('gtk-go-back', Gtk.IconSize.BUTTON)
463
492
        button.set_image(image)
464
493
        button.connect("clicked", lambda w, d: self._do_search(d),
465
494
                       'backward')
466
495
        self.pack_start(button, expand=False, fill=False)
467
496
 
468
497
        # Search options
469
 
        check = gtk.CheckButton('Match case')
 
498
        check = Gtk.CheckButton('Match case')
470
499
        self._match_case = check
471
500
        self.pack_start(check, expand=False, fill=False)
472
501
 
473
 
        check = gtk.CheckButton('Regexp')
 
502
        check = Gtk.CheckButton('Regexp')
474
503
        check.connect("toggled", lambda w: self._set_label())
475
504
        self._regexp = check
476
505
        self.pack_start(check, expand=False, fill=False)
506
535
 
507
536
    def _match(self, model, iterator, column):
508
537
        matching_case = self._match_case.get_active()
509
 
        string, = model.get(iterator, column)
 
538
        cell_value, = model.get(iterator, column)
510
539
        key = self._entry.get_text()
511
 
        if self._regexp.get_active():
 
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
545
            if matching_case:
513
 
                match = re.compile(key).search(string, 1)
 
546
                match = re.compile(key).search(cell_value, 1)
514
547
            else:
515
 
                match = re.compile(key, re.I).search(string, 1)
 
548
                match = re.compile(key, re.I).search(cell_value, 1)
516
549
        else:
517
550
            if not matching_case:
518
 
                string = string.lower()
 
551
                cell_value = cell_value.lower()
519
552
                key = key.lower()
520
 
            match = string.find(key) != -1
 
553
            match = cell_value.find(key) != -1
521
554
 
522
555
        return match
523
556