/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
1
# -*- coding: UTF-8 -*-
2
"""Revision history view.
3
4
"""
5
6
__copyright__ = "Copyright © 2005 Canonical Ltd."
7
__author__    = "Daniel Schierbeck <daniel.schierbeck@gmail.com>"
8
314 by Daniel Schierbeck
Moved branch locking into treeview.
9
import sys
10
import string
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
11
import gtk
12
import gobject
13
import pango
14
import re
303 by Daniel Schierbeck
Made basic signaling work.
15
import treemodel
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
16
17
from linegraph import linegraph, same_branch
18
from graphcell import CellRendererGraph
19
from treemodel import TreeModel
330.4.3 by Daniel Schierbeck
Switched to using NULL_REVISION instead of None.
20
from bzrlib.revision import NULL_REVISION
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
21
303 by Daniel Schierbeck
Made basic signaling work.
22
class TreeView(gtk.ScrolledWindow):
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
23
346 by Daniel Schierbeck
Added revno-column-visible property to treeview.
24
    __gproperties__ = {
352 by Daniel Schierbeck
Added branch property to treeview.
25
        'branch': (gobject.TYPE_PYOBJECT,
26
                   'Branch',
27
                   'The Bazaar branch being visualized',
28
                   gobject.PARAM_CONSTRUCT_ONLY | gobject.PARAM_WRITABLE),
29
356 by Daniel Schierbeck
Made revision a property on TreeView.
30
        'revision': (gobject.TYPE_PYOBJECT,
31
                     'Revision',
32
                     'The currently selected revision',
33
                     gobject.PARAM_READWRITE),
34
346 by Daniel Schierbeck
Added revno-column-visible property to treeview.
35
        'revno-column-visible': (gobject.TYPE_BOOLEAN,
36
                                 'Revision number',
37
                                 'Show revision number column',
38
                                 True,
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
39
                                 gobject.PARAM_READWRITE),
40
41
        'date-column-visible': (gobject.TYPE_BOOLEAN,
360 by Daniel Schierbeck
Fixed wrong text in date property.
42
                                 'Date',
43
                                 'Show date column',
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
44
                                 False,
346 by Daniel Schierbeck
Added revno-column-visible property to treeview.
45
                                 gobject.PARAM_READWRITE)
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
46
346 by Daniel Schierbeck
Added revno-column-visible property to treeview.
47
    }
48
307 by Daniel Schierbeck
Made load notification work again.
49
    __gsignals__ = {
345 by Daniel Schierbeck
Made treeview columns instance variables.
50
        'revisions-loaded': (gobject.SIGNAL_RUN_FIRST, 
51
                             gobject.TYPE_NONE,
52
                             ()),
53
        'revision-selected': (gobject.SIGNAL_RUN_FIRST,
54
                              gobject.TYPE_NONE,
55
                              ())
307 by Daniel Schierbeck
Made load notification work again.
56
    }
57
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
58
    def __init__(self, branch, start, maxnum, broken_line_length=None):
322 by Jelmer Vernooij
Add docstrings.
59
        """Create a new TreeView.
60
61
        :param branch: Branch object for branch to show.
62
        :param start: Revision id of top revision.
63
        :param maxnum: Maximum number of revisions to display, 
64
                       None for no limit.
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
65
        :param broken_line_length: After how much lines to break 
66
                                   branches.
322 by Jelmer Vernooij
Add docstrings.
67
        """
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
68
        gtk.ScrolledWindow.__init__(self)
69
303 by Daniel Schierbeck
Made basic signaling work.
70
        self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
71
        self.set_shadow_type(gtk.SHADOW_IN)
72
303 by Daniel Schierbeck
Made basic signaling work.
73
        self.construct_treeview()
74
316 by Daniel Schierbeck
Removed viz.TreeView.set_branch()
75
        self.branch = branch
76
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
77
        gobject.idle_add(self.populate, start, maxnum, 
78
                         broken_line_length)
316 by Daniel Schierbeck
Removed viz.TreeView.set_branch()
79
303 by Daniel Schierbeck
Made basic signaling work.
80
        self.revision = None
81
        self.children = None
82
        self.parents  = None
83
347 by Daniel Schierbeck
Added property getter and setter method to the treeview.
84
    def do_get_property(self, property):
85
        if property.name == 'revno-column-visible':
352 by Daniel Schierbeck
Added branch property to treeview.
86
            return self.revno_column.get_visible()
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
87
        elif property.name == 'date-column-visible':
88
            return self.date_column.get_visible()
352 by Daniel Schierbeck
Added branch property to treeview.
89
        elif property.name == 'branch':
90
            return self.branch
356 by Daniel Schierbeck
Made revision a property on TreeView.
91
        elif property.name == 'revision':
92
            return self.revision
347 by Daniel Schierbeck
Added property getter and setter method to the treeview.
93
        else:
94
            raise AttributeError, 'unknown property %s' % property.name
95
96
    def do_set_property(self, property, value):
97
        if property.name == 'revno-column-visible':
98
            self.revno_column.set_visible(value)
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
99
        elif property.name == 'date-column-visible':
100
            self.date_column.set_visible(value)
352 by Daniel Schierbeck
Added branch property to treeview.
101
        elif property.name == 'branch':
102
            self.branch = value
356 by Daniel Schierbeck
Made revision a property on TreeView.
103
        elif property.name == 'revision':
104
            self.set_revision_id(value.revision_id)
347 by Daniel Schierbeck
Added property getter and setter method to the treeview.
105
        else:
106
            raise AttributeError, 'unknown property %s' % property.name
107
303 by Daniel Schierbeck
Made basic signaling work.
108
    def get_revision(self):
322 by Jelmer Vernooij
Add docstrings.
109
        """Return revision id of currently selected revision, or None."""
303 by Daniel Schierbeck
Made basic signaling work.
110
        return self.revision
111
356 by Daniel Schierbeck
Made revision a property on TreeView.
112
    def set_revision_id(self, revid):
322 by Jelmer Vernooij
Add docstrings.
113
        """Change the currently selected revision.
114
115
        :param revid: Revision id of revision to display.
116
        """
305 by Daniel Schierbeck
Moved revision selection to the new view.
117
        self.treeview.set_cursor(self.index[revid])
118
        self.treeview.grab_focus()
119
303 by Daniel Schierbeck
Made basic signaling work.
120
    def get_children(self):
322 by Jelmer Vernooij
Add docstrings.
121
        """Return the children of the currently selected revision.
122
123
        :return: list of revision ids.
124
        """
303 by Daniel Schierbeck
Made basic signaling work.
125
        return self.children
126
127
    def get_parents(self):
322 by Jelmer Vernooij
Add docstrings.
128
        """Return the parents of the currently selected revision.
129
130
        :return: list of revision ids.
131
        """
303 by Daniel Schierbeck
Made basic signaling work.
132
        return self.parents
316 by Daniel Schierbeck
Removed viz.TreeView.set_branch()
133
        
304 by Daniel Schierbeck
Made forward/back buttons work again.
134
    def back(self):
322 by Jelmer Vernooij
Add docstrings.
135
        """Signal handler for the Back button."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
136
        (path, col) = self.treeview.get_cursor()
137
        revision = self.model[path][treemodel.REVISION]
138
        parents = self.model[path][treemodel.PARENTS]
139
        if not len(parents):
140
            return
141
142
        for parent_id in parents:
143
            parent_index = self.index[parent_id]
144
            parent = self.model[parent_index][treemodel.REVISION]
145
            if same_branch(revision, parent):
146
                self.treeview.set_cursor(parent_index)
147
                break
148
        else:
149
            self.treeview.set_cursor(self.index[parents[0]])
150
        self.treeview.grab_focus()
151
152
    def forward(self):
322 by Jelmer Vernooij
Add docstrings.
153
        """Signal handler for the Forward button."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
154
        (path, col) = self.treeview.get_cursor()
155
        revision = self.model[path][treemodel.REVISION]
156
        children = self.model[path][treemodel.CHILDREN]
157
        if not len(children):
158
            return
159
160
        for child_id in children:
161
            child_index = self.index[child_id]
162
            child = self.model[child_index][treemodel.REVISION]
163
            if same_branch(child, revision):
164
                self.treeview.set_cursor(child_index)
165
                break
166
        else:
167
            self.treeview.set_cursor(self.index[children[0]])
168
        self.treeview.grab_focus()
169
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
170
    def populate(self, start, maxnum, broken_line_length=None):
322 by Jelmer Vernooij
Add docstrings.
171
        """Fill the treeview with contents.
172
173
        :param start: Revision id of revision to start with.
174
        :param maxnum: Maximum number of revisions to display, or None 
175
                       for no limit.
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
176
        :param broken_line_length: After how much lines branches \
177
                       should be broken.
322 by Jelmer Vernooij
Add docstrings.
178
        """
365 by Daniel Schierbeck
Fixed locks and made tagging work.
179
        try:
180
            self.branch.lock_read()
181
            (linegraphdata, index, columns_len) = linegraph(self.branch.repository,
182
                                                            start,
183
                                                            maxnum, 
184
                                                            broken_line_length)
185
186
            self.model = TreeModel(self.branch.repository, linegraphdata)
187
            self.graph_cell.columns_len = columns_len
188
            width = self.graph_cell.get_size(self.treeview)[2]
189
            self.graph_column.set_fixed_width(width)
190
            self.graph_column.set_max_width(width)
191
            self.index = index
192
            self.treeview.set_model(self.model)
193
            self.treeview.set_cursor(0)
194
            self.emit('revisions-loaded')
195
196
        finally:
197
            self.branch.unlock()
304 by Daniel Schierbeck
Made forward/back buttons work again.
198
199
        return False
200
364 by Daniel Schierbeck
Simplified TreeView.show_diff() and made the Revision -> View Changes menu item work.
201
    def show_diff(self, revid=None, parentid=None):
306 by Daniel Schierbeck
Made clicking a row work again.
202
        """Open a new window to show a diff between the given revisions."""
203
        from bzrlib.plugins.gtk.diff import DiffWindow
204
        window = DiffWindow(parent=self)
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
205
364 by Daniel Schierbeck
Simplified TreeView.show_diff() and made the Revision -> View Changes menu item work.
206
        if revid is None:
207
            revid = self.revision.revision_id
208
209
            if parentid is None and len(self.parents) > 0:
210
                parentid = self.parents[0]
330.4.3 by Daniel Schierbeck
Switched to using NULL_REVISION instead of None.
211
212
        if parentid is None:
213
            parentid = NULL_REVISION
214
364 by Daniel Schierbeck
Simplified TreeView.show_diff() and made the Revision -> View Changes menu item work.
215
        rev_tree    = self.branch.repository.revision_tree(revid)
216
        parent_tree = self.branch.repository.revision_tree(parentid)
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
217
364 by Daniel Schierbeck
Simplified TreeView.show_diff() and made the Revision -> View Changes menu item work.
218
        description = revid + " - " + self.branch.nick
306 by Daniel Schierbeck
Made clicking a row work again.
219
        window.set_diff(description, rev_tree, parent_tree)
220
        window.show()
221
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
222
    def construct_treeview(self):
223
        self.treeview = gtk.TreeView()
224
225
        self.treeview.set_rules_hint(True)
330.1.2 by Daniel Schierbeck
Replaced literal column index with equivalent symbol.
226
        self.treeview.set_search_column(treemodel.REVNO)
330.1.1 by Daniel Schierbeck
Added tooltip to the treeview.
227
        self.treeview.set_tooltip_column(treemodel.MESSAGE)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
228
303 by Daniel Schierbeck
Made basic signaling work.
229
        self.treeview.get_selection().connect("changed",
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
230
                self._on_selection_changed)
231
232
        self.treeview.connect("row-activated", 
233
                self._on_revision_activated)
234
235
        self.treeview.connect("button-release-event", 
236
                self._on_revision_selected)
237
238
        self.treeview.set_property('fixed-height-mode', True)
239
240
        self.add(self.treeview)
241
        self.treeview.show()
242
243
        cell = gtk.CellRendererText()
244
        cell.set_property("width-chars", 15)
245
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
345 by Daniel Schierbeck
Made treeview columns instance variables.
246
        self.revno_column = gtk.TreeViewColumn("Revision No")
247
        self.revno_column.set_resizable(True)
248
        self.revno_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
249
        self.revno_column.set_fixed_width(cell.get_size(self.treeview)[2])
250
        self.revno_column.pack_start(cell, expand=True)
251
        self.revno_column.add_attribute(cell, "text", treemodel.REVNO)
252
        self.treeview.append_column(self.revno_column)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
253
254
        self.graph_cell = CellRendererGraph()
255
        self.graph_column = gtk.TreeViewColumn()
256
        self.graph_column.set_resizable(True)
257
        self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
258
        self.graph_column.pack_start(self.graph_cell, expand=False)
259
        self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
260
        self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
261
        self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
262
        self.treeview.append_column(self.graph_column)
263
264
        cell = gtk.CellRendererText()
265
        cell.set_property("width-chars", 65)
266
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
345 by Daniel Schierbeck
Made treeview columns instance variables.
267
        self.msg_column = gtk.TreeViewColumn("Message")
268
        self.msg_column.set_resizable(True)
269
        self.msg_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
270
        self.msg_column.set_fixed_width(cell.get_size(self.treeview)[2])
271
        self.msg_column.pack_start(cell, expand=True)
272
        self.msg_column.add_attribute(cell, "text", treemodel.MESSAGE)
273
        self.treeview.append_column(self.msg_column)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
274
275
        cell = gtk.CellRendererText()
276
        cell.set_property("width-chars", 15)
277
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
345 by Daniel Schierbeck
Made treeview columns instance variables.
278
        self.committer_column = gtk.TreeViewColumn("Committer")
279
        self.committer_column.set_resizable(True)
280
        self.committer_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
281
        self.committer_column.set_fixed_width(cell.get_size(self.treeview)[2])
282
        self.committer_column.pack_start(cell, expand=True)
283
        self.committer_column.add_attribute(cell, "text", treemodel.COMMITER)
284
        self.treeview.append_column(self.committer_column)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
285
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
286
        cell = gtk.CellRendererText()
359 by Daniel Schierbeck
Simplified date format.
287
        cell.set_property("width-chars", 20)
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
288
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
289
        self.date_column = gtk.TreeViewColumn("Date")
290
        self.date_column.set_visible(False)
291
        self.date_column.set_resizable(True)
292
        self.date_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
293
        self.date_column.set_fixed_width(cell.get_size(self.treeview)[2])
294
        self.date_column.pack_start(cell, expand=True)
295
        self.date_column.add_attribute(cell, "text", treemodel.TIMESTAMP)
296
        self.treeview.append_column(self.date_column)
297
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
298
    def _on_selection_changed(self, selection, *args):
303 by Daniel Schierbeck
Made basic signaling work.
299
        """callback for when the treeview changes."""
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
300
        (model, selected_rows) = selection.get_selected_rows()
301
        if len(selected_rows) > 0:
302
            iter = self.model.get_iter(selected_rows[0])
303 by Daniel Schierbeck
Made basic signaling work.
303
            self.revision = self.model.get_value(iter, treemodel.REVISION)
304
            self.parents = self.model.get_value(iter, treemodel.PARENTS)
305
            self.children = self.model.get_value(iter, treemodel.CHILDREN)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
306
310 by Daniel Schierbeck
Moved to using custom signal for handling revision selections.
307
            self.emit('revision-selected')
308
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
309
    def _on_revision_selected(self, widget, event):
310
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
311
        if event.button == 3:
312
            menu = RevisionPopupMenu(self.branch.repository, 
312 by Daniel Schierbeck
Made right-clicking work again.
313
                [self.get_revision().revision_id],
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
314
                self.branch)
315
            menu.popup(None, None, None, event.button, event.get_time())
316
317
    def _on_revision_activated(self, widget, path, col):
318
        # TODO: more than one parent
319
        """Callback for when a treeview row gets activated."""
320
        revision_id = self.model[path][treemodel.REVID]
321
        parents = self.model[path][treemodel.PARENTS]
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
322
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
323
        if len(parents) == 0:
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
324
            parent_id = None
325
        else:
326
            parent_id = parents[0]
327
364 by Daniel Schierbeck
Simplified TreeView.show_diff() and made the Revision -> View Changes menu item work.
328
        self.show_diff(revision_id, parent_id)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
329
        self.treeview.grab_focus()