19
from gi.repository import GObject
20
from gi.repository import Gdk
21
from gi.repository import Gtk
22
from gi.repository import Pango
25
26
from bzrlib import patiencediff
26
27
from bzrlib.errors import NoSuchRevision
27
28
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
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
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))
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()
198
vbox = Gtk.VBox(homogeneous=False, spacing=0)
196
vbox = gtk.VBox(False)
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
209
swbox.pack_start(sw, True, True, 0)
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)
222
vbox.pack_start(hbox, False, True, 0)
220
vbox.pack_start(hbox, expand=False, fill=True)
224
self.pane = pane = Gtk.Paned.new(Gtk.Orientation.VERTICAL)
222
self.pane = pane = gtk.VPaned()
226
224
pane.add2(self.revisionview)
228
vbox.pack_start(pane, True, True, 0)
226
vbox.pack_start(pane, expand=True, fill=True)
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,
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,
238
236
self._search_by_line)
239
237
self.add_accel_group(accels)
271
269
def _create_annotate_view(self):
273
271
tv.set_rules_hint(False)
274
272
tv.connect("cursor-changed", self._activate_selected_revision)
276
274
tv.connect("row-activated", self.line_diff)
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)
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)
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)
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)
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
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)
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)
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)
353
348
button.set_sensitive(False)
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)
364
359
button.set_sensitive(True)
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)
374
369
button.set_sensitive(True)
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
407
new_path = Gtk.TreePath(path=new_row)
408
self.annoview.set_cursor(new_path, None, False)
401
self.annoview.set_cursor(new_row)
457
449
self.__cache[revision_id] = revision
458
450
return self.__cache[revision_id]
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)
467
button = Gtk.Button()
469
image.set_from_stock('gtk-stop', Gtk.IconSize.BUTTON)
458
button = gtk.Button()
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)
477
468
self._label = label
478
self.pack_start(label, False, False, 0)
469
self.pack_start(label, expand=False, fill=False)
481
472
self._entry = entry
482
473
entry.connect("activate", lambda w, d: self._do_search(d),
484
self.pack_start(entry, False, False, 0)
475
self.pack_start(entry, expand=False, fill=False)
486
477
# Next/previous buttons
487
button = Gtk.Button(_i18n('_Next'), use_underline=True)
489
image.set_from_stock('gtk-go-forward', Gtk.IconSize.BUTTON)
478
button = gtk.Button('_Next')
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),
493
self.pack_start(button, False, False, 0)
484
self.pack_start(button, expand=False, fill=False)
495
button = Gtk.Button(_i18n('_Previous'), use_underline=True)
497
image.set_from_stock('gtk-go-back', Gtk.IconSize.BUTTON)
486
button = gtk.Button('_Previous')
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),
501
self.pack_start(button, False, False, 0)
492
self.pack_start(button, expand=False, fill=False)
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)
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)
513
504
self._view = None
514
505
self._column = None