/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: David Planella
  • Date: 2011-03-06 08:24:07 UTC
  • mfrom: (718 trunk)
  • mto: This revision was merged to the branch mainline in revision 719.
  • Revision ID: david.planella@ubuntu.com-20110306082407-y9zwkjje5oue9egw
Added preliminary internationalization support. Merged from trunk.

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
26
from bzrlib import patiencediff
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 bzrlib.plugins.gtk.i18n import _i18n
 
30
from colormap import AnnotateColorSaturation
31
31
from bzrlib.plugins.gtk.revisionview import RevisionView
32
32
from bzrlib.plugins.gtk.window import Window
33
33
 
50
50
        self.plain = plain
51
51
        self._branch = branch
52
52
 
53
 
        super(GAnnotateWindow, self).__init__(parent=parent)
 
53
        Window.__init__(self, parent)
54
54
 
55
 
        self.set_icon(
56
 
            self.render_icon_pixbuf(Gtk.STOCK_FIND, Gtk.IconSize.BUTTON))
 
55
        self.set_icon(self.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_BUTTON))
57
56
        self.annotate_colormap = AnnotateColorSaturation()
58
57
 
59
58
        self._create()
71
70
                                   lambda: CURRENT_REVISION)()
72
71
 
73
72
        # [revision id, line number, author, revno, highlight color, line]
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)
 
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)
80
79
 
81
80
        last_seen = None
82
81
        try:
130
129
        else:
131
130
            row = lineno - 1
132
131
 
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)
 
132
        self.annoview.set_cursor(row)
 
133
        self.annoview.scroll_to_cell(row, use_align=True)
 
134
 
136
135
 
137
136
    def _annotate(self, tree, file_id):
138
137
        current_revision = FakeRevision(CURRENT_REVISION)
168
167
    def _highlight_annotation(self, model, path, iter, now):
169
168
        revision_id, = model.get(iter, REVISION_ID_COL)
170
169
        revision = self.revisions[revision_id]
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)
 
170
        model.set(iter, HIGHLIGHT_COLOR_COL,
 
171
                  self.annotate_colormap.get_color(revision, now))
174
172
 
175
173
    def _selected_revision(self):
176
174
        (path, col) = self.annoview.get_cursor()
195
193
        self.revisionview = self._create_log_view()
196
194
        self.annoview = self._create_annotate_view()
197
195
 
198
 
        vbox = Gtk.VBox(homogeneous=False, spacing=0)
 
196
        vbox = gtk.VBox(False)
199
197
        vbox.show()
200
198
 
201
 
        sw = Gtk.ScrolledWindow()
202
 
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
203
 
        sw.set_shadow_type(Gtk.ShadowType.IN)
 
199
        sw = gtk.ScrolledWindow()
 
200
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
201
        sw.set_shadow_type(gtk.SHADOW_IN)
204
202
        sw.add(self.annoview)
205
203
        self.annoview.gwindow = self
206
204
        sw.show()
207
205
 
208
 
        swbox = Gtk.VBox()
209
 
        swbox.pack_start(sw, True, True, 0)
 
206
        swbox = gtk.VBox()
 
207
        swbox.pack_start(sw)
210
208
        swbox.show()
211
209
 
212
 
        hbox = Gtk.HBox(homogeneous=False, spacing=6)
 
210
        hbox = gtk.HBox(False, 6)
213
211
        self.back_button = self._create_back_button()
214
 
        hbox.pack_start(self.back_button, False, True, 0)
 
212
        hbox.pack_start(self.back_button, expand=False, fill=True)
215
213
        self.forward_button = self._create_forward_button()
216
 
        hbox.pack_start(self.forward_button, False, True, 0)
 
214
        hbox.pack_start(self.forward_button, expand=False, fill=True)
217
215
        self.find_button = self._create_find_button()
218
 
        hbox.pack_start(self.find_button, False, True, 0)
 
216
        hbox.pack_start(self.find_button, expand=False, fill=True)
219
217
        self.goto_button = self._create_goto_button()
220
 
        hbox.pack_start(self.goto_button, False, True, 0)
 
218
        hbox.pack_start(self.goto_button, expand=False, fill=True)
221
219
        hbox.show()
222
 
        vbox.pack_start(hbox, False, True, 0)
 
220
        vbox.pack_start(hbox, expand=False, fill=True)
223
221
 
224
 
        self.pane = pane = Gtk.Paned.new(Gtk.Orientation.VERTICAL)
 
222
        self.pane = pane = gtk.VPaned()
225
223
        pane.add1(swbox)
226
224
        pane.add2(self.revisionview)
227
225
        pane.show()
228
 
        vbox.pack_start(pane, True, True, 0)
 
226
        vbox.pack_start(pane, expand=True, fill=True)
229
227
 
230
228
        self._search = SearchBox()
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,
 
229
        swbox.pack_start(self._search, expand=False, fill=True)
 
230
        accels = gtk.AccelGroup()
 
231
        accels.connect_group(gtk.keysyms.f, gtk.gdk.CONTROL_MASK,
 
232
                             gtk.ACCEL_LOCKED,
235
233
                             self._search_by_text)
236
 
        accels.connect(Gdk.KEY_g, Gdk.ModifierType.CONTROL_MASK,
237
 
                             Gtk.AccelFlags.LOCKED,
 
234
        accels.connect_group(gtk.keysyms.g, gtk.gdk.CONTROL_MASK,
 
235
                             gtk.ACCEL_LOCKED,
238
236
                             self._search_by_line)
239
237
        self.add_accel_group(accels)
240
238
 
249
247
        self._search.set_target(self.annoview, LINE_NUM_COL)
250
248
 
251
249
    def line_diff(self, tv, path, tvc):
252
 
        row = path.get_indices()[0]
 
250
        row = path[0]
253
251
        revision = self.annotations[row]
254
252
        repository = self.branch.repository
255
253
        if revision.revision_id == CURRENT_REVISION:
269
267
 
270
268
 
271
269
    def _create_annotate_view(self):
272
 
        tv = Gtk.TreeView()
 
270
        tv = gtk.TreeView()
273
271
        tv.set_rules_hint(False)
274
272
        tv.connect("cursor-changed", self._activate_selected_revision)
275
273
        tv.show()
276
274
        tv.connect("row-activated", self.line_diff)
277
275
 
278
 
        cell = Gtk.CellRendererText()
 
276
        cell = gtk.CellRendererText()
279
277
        cell.set_property("xalign", 1.0)
280
278
        cell.set_property("ypad", 0)
281
279
        cell.set_property("family", "Monospace")
282
280
        cell.set_property("cell-background-gdk",
283
 
                          tv.get_style().bg[Gtk.StateType.NORMAL])
284
 
        col = Gtk.TreeViewColumn()
 
281
                          tv.get_style().bg[gtk.STATE_NORMAL])
 
282
        col = gtk.TreeViewColumn()
285
283
        col.set_resizable(False)
286
 
        col.pack_start(cell, True)
 
284
        col.pack_start(cell, expand=True)
287
285
        col.add_attribute(cell, "text", LINE_NUM_COL)
288
286
        tv.append_column(col)
289
287
 
290
 
        cell = Gtk.CellRendererText()
 
288
        cell = gtk.CellRendererText()
291
289
        cell.set_property("ypad", 0)
292
 
        cell.set_property("ellipsize", Pango.EllipsizeMode.END)
 
290
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
293
291
        cell.set_property("cell-background-gdk",
294
 
                          self.get_style().bg[Gtk.StateType.NORMAL])
295
 
        col = Gtk.TreeViewColumn("Committer")
 
292
                          self.get_style().bg[gtk.STATE_NORMAL])
 
293
        col = gtk.TreeViewColumn("Committer")
296
294
        col.set_resizable(True)
297
 
        col.pack_start(cell, True)
 
295
        col.pack_start(cell, expand=True)
298
296
        col.add_attribute(cell, "text", COMMITTER_COL)
299
297
        tv.append_column(col)
300
298
 
301
 
        cell = Gtk.CellRendererText()
 
299
        cell = gtk.CellRendererText()
302
300
        cell.set_property("xalign", 1.0)
303
301
        cell.set_property("ypad", 0)
304
302
        cell.set_property("cell-background-gdk",
305
 
                          self.get_style().bg[Gtk.StateType.NORMAL])
306
 
        col = Gtk.TreeViewColumn("Revno")
 
303
                          self.get_style().bg[gtk.STATE_NORMAL])
 
304
        col = gtk.TreeViewColumn("Revno")
307
305
        col.set_resizable(False)
308
 
        col.pack_start(cell, True)
 
306
        col.pack_start(cell, expand=True)
309
307
        col.add_attribute(cell, "markup", REVNO_COL)
310
308
        tv.append_column(col)
311
309
 
312
 
        cell = Gtk.CellRendererText()
 
310
        cell = gtk.CellRendererText()
313
311
        cell.set_property("ypad", 0)
314
312
        cell.set_property("family", "Monospace")
315
 
        col = Gtk.TreeViewColumn()
 
313
        col = gtk.TreeViewColumn()
316
314
        col.set_resizable(False)
317
 
        col.pack_start(cell, True)
 
315
        col.pack_start(cell, expand=True)
318
316
#        col.add_attribute(cell, "foreground", HIGHLIGHT_COLOR_COL)
319
317
        col.add_attribute(cell, "background", HIGHLIGHT_COLOR_COL)
320
318
        col.add_attribute(cell, "text", TEXT_LINE_COL)
321
319
        tv.append_column(col)
322
320
 
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)
 
321
        # FIXME: Now that C-f is now used for search by text we
 
322
        # may as well disable the auto search.
 
323
        tv.set_search_column(LINE_NUM_COL)
329
324
 
330
325
        return tv
331
326
 
335
330
        return lv
336
331
 
337
332
    def _create_back_button(self):
338
 
        button = Gtk.Button()
 
333
        button = gtk.Button()
339
334
        button.set_use_stock(True)
340
335
        button.set_label("gtk-go-back")
341
336
        button.connect("clicked", lambda w: self.go_back())
342
 
        button.set_relief(Gtk.ReliefStyle.NONE)
 
337
        button.set_relief(gtk.RELIEF_NONE)
343
338
        button.show()
344
339
        return button
345
340
 
346
341
    def _create_forward_button(self):
347
 
        button = Gtk.Button()
 
342
        button = gtk.Button()
348
343
        button.set_use_stock(True)
349
344
        button.set_label("gtk-go-forward")
350
345
        button.connect("clicked", lambda w: self.go_forward())
351
 
        button.set_relief(Gtk.ReliefStyle.NONE)
 
346
        button.set_relief(gtk.RELIEF_NONE)
352
347
        button.show()
353
348
        button.set_sensitive(False)
354
349
        return button
355
350
 
356
351
    def _create_find_button(self):
357
 
        button = Gtk.Button()
 
352
        button = gtk.Button()
358
353
        button.set_use_stock(True)
359
354
        button.set_label("gtk-find")
360
355
        button.set_tooltip_text("Search for text (Ctrl+F)")
361
356
        button.connect("clicked", self._search_by_text)
362
 
        button.set_relief(Gtk.ReliefStyle.NONE)
 
357
        button.set_relief(gtk.RELIEF_NONE)
363
358
        button.show()
364
359
        button.set_sensitive(True)
365
360
        return button
366
361
 
367
362
    def _create_goto_button(self):
368
 
        button = Gtk.Button()
 
363
        button = gtk.Button()
369
364
        button.set_label("Goto Line")
370
365
        button.set_tooltip_text("Scroll to a line by entering its number (Ctrl+G)")
371
366
        button.connect("clicked", self._search_by_line)
372
 
        button.set_relief(Gtk.ReliefStyle.NONE)
 
367
        button.set_relief(gtk.RELIEF_NONE)
373
368
        button.show()
374
369
        button.set_sensitive(True)
375
370
        return button
398
393
        rev_id = self._selected_revision()
399
394
        if self.file_id in target_tree:
400
395
            offset = self.get_scroll_offset(target_tree)
401
 
            path, col = self.annoview.get_cursor()
402
 
            (row,) = path.get_indices()
 
396
            (row,), col = self.annoview.get_cursor()
403
397
            self.annotate(target_tree, self.branch, self.file_id)
404
398
            new_row = row+offset
405
399
            if new_row < 0:
406
400
                new_row = 0
407
 
            new_path = Gtk.TreePath(path=new_row)
408
 
            self.annoview.set_cursor(new_path, None, False)
 
401
            self.annoview.set_cursor(new_row)
409
402
            return True
410
403
        else:
411
404
            return False
413
406
    def get_scroll_offset(self, tree):
414
407
        old = self.tree.get_file(self.file_id)
415
408
        new = tree.get_file(self.file_id)
416
 
        path, col = self.annoview.get_cursor()
417
 
        (row,) = path.get_indices()
 
409
        (row,), col = self.annoview.get_cursor()
418
410
        matcher = patiencediff.PatienceSequenceMatcher(None, old.readlines(),
419
411
                                                       new.readlines())
420
412
        for i, j, n in matcher.get_matching_blocks():
457
449
            self.__cache[revision_id] = revision
458
450
        return self.__cache[revision_id]
459
451
 
460
 
 
461
 
class SearchBox(Gtk.HBox):
 
452
class SearchBox(gtk.HBox):
462
453
    """A button box for searching in text or lines of annotations"""
463
454
    def __init__(self):
464
 
        super(SearchBox, self).__init__(homogeneous=False, spacing=6)
 
455
        gtk.HBox.__init__(self, False, 6)
465
456
 
466
457
        # Close button
467
 
        button = Gtk.Button()
468
 
        image = Gtk.Image()
469
 
        image.set_from_stock('gtk-stop', Gtk.IconSize.BUTTON)
 
458
        button = gtk.Button()
 
459
        image = gtk.Image()
 
460
        image.set_from_stock('gtk-stop', gtk.ICON_SIZE_BUTTON)
470
461
        button.set_image(image)
471
 
        button.set_relief(Gtk.ReliefStyle.NONE)
472
 
        button.connect("clicked", lambda w: self.hide())
473
 
        self.pack_start(button, False, False, 0)
 
462
        button.set_relief(gtk.RELIEF_NONE)
 
463
        button.connect("clicked", lambda w: self.hide_all())
 
464
        self.pack_start(button, expand=False, fill=False)
474
465
 
475
466
        # Search entry
476
 
        label = Gtk.Label()
 
467
        label = gtk.Label()
477
468
        self._label = label
478
 
        self.pack_start(label, False, False, 0)
 
469
        self.pack_start(label, expand=False, fill=False)
479
470
 
480
 
        entry = Gtk.Entry()
 
471
        entry = gtk.Entry()
481
472
        self._entry = entry
482
473
        entry.connect("activate", lambda w, d: self._do_search(d),
483
474
                      'forward')
484
 
        self.pack_start(entry, False, False, 0)
 
475
        self.pack_start(entry, expand=False, fill=False)
485
476
 
486
477
        # Next/previous buttons
487
 
        button = Gtk.Button(_i18n('_Next'), use_underline=True)
488
 
        image = Gtk.Image()
489
 
        image.set_from_stock('gtk-go-forward', Gtk.IconSize.BUTTON)
 
478
        button = gtk.Button('_Next')
 
479
        image = gtk.Image()
 
480
        image.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_BUTTON)
490
481
        button.set_image(image)
491
482
        button.connect("clicked", lambda w, d: self._do_search(d),
492
483
                       'forward')
493
 
        self.pack_start(button, False, False, 0)
 
484
        self.pack_start(button, expand=False, fill=False)
494
485
 
495
 
        button = Gtk.Button(_i18n('_Previous'), use_underline=True)
496
 
        image = Gtk.Image()
497
 
        image.set_from_stock('gtk-go-back', Gtk.IconSize.BUTTON)
 
486
        button = gtk.Button('_Previous')
 
487
        image = gtk.Image()
 
488
        image.set_from_stock('gtk-go-back', gtk.ICON_SIZE_BUTTON)
498
489
        button.set_image(image)
499
490
        button.connect("clicked", lambda w, d: self._do_search(d),
500
491
                       'backward')
501
 
        self.pack_start(button, False, False, 0)
 
492
        self.pack_start(button, expand=False, fill=False)
502
493
 
503
494
        # Search options
504
 
        check = Gtk.CheckButton('Match case')
 
495
        check = gtk.CheckButton('Match case')
505
496
        self._match_case = check
506
 
        self.pack_start(check, False, False, 0)
 
497
        self.pack_start(check, expand=False, fill=False)
507
498
 
508
 
        check = Gtk.CheckButton('Regexp')
 
499
        check = gtk.CheckButton('Regexp')
509
500
        check.connect("toggled", lambda w: self._set_label())
510
501
        self._regexp = check
511
 
        self.pack_start(check, False, False, 0)
 
502
        self.pack_start(check, expand=False, fill=False)
512
503
 
513
504
        self._view = None
514
505
        self._column = None
594
585
        for row in iterate(model, start):
595
586
            if self._match(model, row, self._column):
596
587
                path = model.get_path(row)
597
 
                self._view.set_cursor(path, None, False)
 
588
                self._view.set_cursor(path)
598
589
                self._view.scroll_to_cell(path, use_align=True)
599
590
                break