6
6
__copyright__ = "Copyright © 2005 Canonical Ltd."
7
7
__author__ = "Daniel Schierbeck <daniel.schierbeck@gmail.com>"
9
from gi.repository import Gtk
10
from gi.repository import GObject
11
from gi.repository import Pango
13
13
from bzrlib import ui
15
from bzrlib.plugins.gtk.ui import ProgressPanel
16
from linegraph import linegraph, same_branch
17
from graphcell import CellRendererGraph
18
from treemodel import TreeModel
14
19
from bzrlib.revision import NULL_REVISION
16
20
from bzrlib.plugins.gtk import lock
17
from bzrlib.plugins.gtk.ui import ProgressPanel
18
from bzrlib.plugins.gtk.branchview import treemodel
19
from bzrlib.plugins.gtk.branchview.linegraph import linegraph, same_branch
20
from bzrlib.plugins.gtk.branchview.graphcell import CellRendererGraph
23
class TreeView(Gtk.VBox):
23
class TreeView(gtk.VBox):
25
25
__gproperties__ = {
26
'branch': (GObject.TYPE_PYOBJECT,
26
'branch': (gobject.TYPE_PYOBJECT,
28
28
'The Bazaar branch being visualized',
29
GObject.PARAM_CONSTRUCT_ONLY | GObject.PARAM_WRITABLE),
29
gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE),
31
'revision': (GObject.TYPE_PYOBJECT,
31
'revision': (gobject.TYPE_PYOBJECT,
33
33
'The currently selected revision',
34
GObject.PARAM_READWRITE),
34
gobject.PARAM_READWRITE),
36
'revision-number': (GObject.TYPE_STRING,
36
'revision-number': (gobject.TYPE_STRING,
38
38
'The number of the selected revision',
40
GObject.PARAM_READABLE),
40
gobject.PARAM_READABLE),
42
'children': (GObject.TYPE_PYOBJECT,
42
'children': (gobject.TYPE_PYOBJECT,
44
44
'Children of the currently selected revision',
45
GObject.PARAM_READABLE),
45
gobject.PARAM_READABLE),
47
'parents': (GObject.TYPE_PYOBJECT,
47
'parents': (gobject.TYPE_PYOBJECT,
48
48
'Parent revisions',
49
49
'Parents to the currently selected revision',
50
GObject.PARAM_READABLE),
50
gobject.PARAM_READABLE),
52
'revno-column-visible': (GObject.TYPE_BOOLEAN,
52
'revno-column-visible': (gobject.TYPE_BOOLEAN,
53
53
'Revision number column',
54
54
'Show revision number column',
56
GObject.PARAM_READWRITE),
56
gobject.PARAM_READWRITE),
58
'graph-column-visible': (GObject.TYPE_BOOLEAN,
58
'graph-column-visible': (gobject.TYPE_BOOLEAN,
60
60
'Show graph column',
62
GObject.PARAM_READWRITE),
62
gobject.PARAM_READWRITE),
64
'date-column-visible': (GObject.TYPE_BOOLEAN,
64
'date-column-visible': (gobject.TYPE_BOOLEAN,
66
66
'Show date column',
68
GObject.PARAM_READWRITE),
68
gobject.PARAM_READWRITE),
70
'compact': (GObject.TYPE_BOOLEAN,
70
'compact': (gobject.TYPE_BOOLEAN,
72
72
'Break ancestry lines to save space',
74
GObject.PARAM_CONSTRUCT | GObject.PARAM_READWRITE),
74
gobject.PARAM_CONSTRUCT | gobject.PARAM_READWRITE),
76
'mainline-only': (GObject.TYPE_BOOLEAN,
76
'mainline-only': (gobject.TYPE_BOOLEAN,
78
78
'Only show the mainline history.',
80
GObject.PARAM_CONSTRUCT | GObject.PARAM_READWRITE),
80
gobject.PARAM_CONSTRUCT | gobject.PARAM_READWRITE),
85
'revision-selected': (GObject.SignalFlags.RUN_FIRST,
85
'revision-selected': (gobject.SIGNAL_RUN_FIRST,
88
'revision-activated': (GObject.SignalFlags.RUN_FIRST,
90
(GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT)),
91
'tag-added': (GObject.SignalFlags.RUN_FIRST,
93
(GObject.TYPE_STRING, GObject.TYPE_STRING)),
94
'refreshed': (GObject.SignalFlags.RUN_FIRST, None,
88
'revision-activated': (gobject.SIGNAL_RUN_FIRST,
90
(gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)),
91
'tag-added': (gobject.SIGNAL_RUN_FIRST,
93
(gobject.TYPE_STRING, gobject.TYPE_STRING)),
94
'refreshed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
105
105
:param broken_line_length: After how much lines to break
108
Gtk.VBox.__init__(self, homogeneous=False, spacing=0)
108
gtk.VBox.__init__(self, spacing=0)
110
110
self.progress_widget = ProgressPanel()
111
self.pack_start(self.progress_widget, False, True, 0)
111
self.pack_start(self.progress_widget, expand=False, fill=True)
112
112
if getattr(ui.ui_factory, "set_progress_bar_widget", None) is not None:
113
113
# We'are using our own ui, let's tell it to use our widget.
114
114
ui.ui_factory.set_progress_bar_widget(self.progress_widget)
116
self.scrolled_window = Gtk.ScrolledWindow()
117
self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
118
Gtk.PolicyType.AUTOMATIC)
119
self.scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
116
self.scrolled_window = gtk.ScrolledWindow()
117
self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
118
gtk.POLICY_AUTOMATIC)
119
self.scrolled_window.set_shadow_type(gtk.SHADOW_IN)
120
120
self.scrolled_window.show()
121
self.pack_start(self.scrolled_window, True, True, 0)
121
self.pack_start(self.scrolled_window, expand=True, fill=True)
123
123
self.scrolled_window.add(self.construct_treeview())
341
331
self.progress_bar.finished()
343
333
def construct_treeview(self):
344
self.treeview = Gtk.TreeView()
334
self.treeview = gtk.TreeView()
346
336
self.treeview.set_rules_hint(True)
347
# combined revno/summary interactive search
349
# the row in a treemodel is considered "matched" if a REVNO *starts*
350
# from the key (that is the key is found in a REVNO at the offset 0)
351
# or if a MESSAGE *contains* the key anywhere (that is, the key is
352
# found case insensitively in a MESSAGE at any offset)
353
def search_equal_func(model, column, key, iter):
354
return (model.get_value(iter, treemodel.REVNO).find(key) != 0
355
and model.get_value(iter, treemodel.MESSAGE).lower().find(key.lower()) == -1)
357
self.treeview.set_search_equal_func(search_equal_func, None)
358
self.treeview.set_enable_search(True)
360
self.treeview.set_tooltip_column(treemodel.MESSAGE)
337
self.treeview.set_search_column(treemodel.REVNO)
339
# Fix old PyGTK bug - by JAM
340
set_tooltip = getattr(self.treeview, 'set_tooltip_column', None)
341
if set_tooltip is not None:
342
set_tooltip(treemodel.MESSAGE)
362
344
self._prev_cursor_path = None
363
345
self.treeview.connect("cursor-changed",
374
356
self.treeview.show()
376
cell = Gtk.CellRendererText()
358
cell = gtk.CellRendererText()
377
359
cell.set_property("width-chars", 15)
378
cell.set_property("ellipsize", Pango.EllipsizeMode.END)
379
self.revno_column = Gtk.TreeViewColumn("Revision No")
380
self.revno_column.set_resizable(True)
381
self.revno_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
382
self.revno_column.set_fixed_width(
383
cell.get_preferred_width(self.treeview)[1])
384
self.revno_column.pack_start(cell, True)
360
cell.set_property("ellipsize", pango.ELLIPSIZE_END)
361
self.revno_column = gtk.TreeViewColumn("Revision No")
362
self.revno_column.set_resizable(False)
363
self.revno_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
364
self.revno_column.set_fixed_width(cell.get_size(self.treeview)[2])
365
self.revno_column.pack_start(cell, expand=True)
385
366
self.revno_column.add_attribute(cell, "text", treemodel.REVNO)
386
367
self.treeview.append_column(self.revno_column)
388
369
self.graph_cell = CellRendererGraph()
389
self.graph_column = Gtk.TreeViewColumn()
390
self.graph_column.set_resizable(True)
391
self.graph_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
392
self.graph_column.pack_start(self.graph_cell, True)
370
self.graph_column = gtk.TreeViewColumn()
371
self.graph_column.set_resizable(False)
372
self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
373
self.graph_column.pack_start(self.graph_cell, expand=True)
393
374
self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
394
375
self.graph_column.add_attribute(self.graph_cell, "tags", treemodel.TAGS)
395
376
self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
396
377
self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
397
378
self.treeview.append_column(self.graph_column)
399
cell = Gtk.CellRendererText()
380
cell = gtk.CellRendererText()
400
381
cell.set_property("width-chars", 65)
401
cell.set_property("ellipsize", Pango.EllipsizeMode.END)
402
self.summary_column = Gtk.TreeViewColumn("Summary")
403
self.summary_column.set_resizable(True)
382
cell.set_property("ellipsize", pango.ELLIPSIZE_END)
383
self.summary_column = gtk.TreeViewColumn("Summary")
384
self.summary_column.set_resizable(False)
404
385
self.summary_column.set_expand(True)
405
self.summary_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
406
self.summary_column.set_fixed_width(
407
cell.get_preferred_width(self.treeview)[1])
408
self.summary_column.pack_start(cell, True)
386
self.summary_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
387
self.summary_column.set_fixed_width(cell.get_size(self.treeview)[2])
388
self.summary_column.pack_start(cell, expand=True)
409
389
self.summary_column.add_attribute(cell, "markup", treemodel.SUMMARY)
410
390
self.treeview.append_column(self.summary_column)
412
cell = Gtk.CellRendererText()
392
cell = gtk.CellRendererText()
413
393
cell.set_property("width-chars", 15)
414
cell.set_property("ellipsize", Pango.EllipsizeMode.END)
415
self.authors_column = Gtk.TreeViewColumn("Author(s)")
394
cell.set_property("ellipsize", pango.ELLIPSIZE_END)
395
self.authors_column = gtk.TreeViewColumn("Author(s)")
416
396
self.authors_column.set_resizable(False)
417
self.authors_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
397
self.authors_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
418
398
self.authors_column.set_fixed_width(200)
419
self.authors_column.pack_start(cell, True)
399
self.authors_column.pack_start(cell, expand=True)
420
400
self.authors_column.add_attribute(cell, "text", treemodel.AUTHORS)
421
401
self.treeview.append_column(self.authors_column)
423
cell = Gtk.CellRendererText()
403
cell = gtk.CellRendererText()
424
404
cell.set_property("width-chars", 20)
425
cell.set_property("ellipsize", Pango.EllipsizeMode.END)
426
self.date_column = Gtk.TreeViewColumn("Date")
405
cell.set_property("ellipsize", pango.ELLIPSIZE_END)
406
self.date_column = gtk.TreeViewColumn("Date")
427
407
self.date_column.set_visible(False)
428
self.date_column.set_resizable(True)
429
self.date_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
408
self.date_column.set_resizable(False)
409
self.date_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
430
410
self.date_column.set_fixed_width(130)
431
self.date_column.pack_start(cell, True)
411
self.date_column.pack_start(cell, expand=True)
432
412
self.date_column.add_attribute(cell, "text", treemodel.TIMESTAMP)
433
413
self.treeview.append_column(self.date_column)
435
415
return self.treeview
437
417
def _on_selection_changed(self, treeview):
438
418
"""callback for when the treeview changes."""
439
419
(path, focus) = treeview.get_cursor()