/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
307 by Daniel Schierbeck
Made load notification work again.
24
    __gsignals__ = {
25
            'revisions-loaded': (gobject.SIGNAL_RUN_FIRST, 
26
                                 gobject.TYPE_NONE,
308 by Daniel Schierbeck
Made Show Diff work again.
27
                                 ()),
28
            'revision-selected': (gobject.SIGNAL_RUN_FIRST,
29
                                  gobject.TYPE_NONE,
30
                                  ())
307 by Daniel Schierbeck
Made load notification work again.
31
    }
32
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
33
    def __init__(self, branch, start, maxnum, broken_line_length=None):
322 by Jelmer Vernooij
Add docstrings.
34
        """Create a new TreeView.
35
36
        :param branch: Branch object for branch to show.
37
        :param start: Revision id of top revision.
38
        :param maxnum: Maximum number of revisions to display, 
39
                       None for no limit.
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
40
        :param broken_line_length: After how much lines to break 
41
                                   branches.
322 by Jelmer Vernooij
Add docstrings.
42
        """
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
43
        gtk.ScrolledWindow.__init__(self)
44
303 by Daniel Schierbeck
Made basic signaling work.
45
        self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
46
        self.set_shadow_type(gtk.SHADOW_IN)
47
303 by Daniel Schierbeck
Made basic signaling work.
48
        self.construct_treeview()
49
316 by Daniel Schierbeck
Removed viz.TreeView.set_branch()
50
        self.branch = branch
51
        self.branch.lock_read()
52
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
53
        gobject.idle_add(self.populate, start, maxnum, 
54
                         broken_line_length)
316 by Daniel Schierbeck
Removed viz.TreeView.set_branch()
55
303 by Daniel Schierbeck
Made basic signaling work.
56
        self.revision = None
57
        self.children = None
58
        self.parents  = None
59
314 by Daniel Schierbeck
Moved branch locking into treeview.
60
        self.connect('destroy', lambda w: self.branch.unlock())
61
303 by Daniel Schierbeck
Made basic signaling work.
62
    def get_revision(self):
322 by Jelmer Vernooij
Add docstrings.
63
        """Return revision id of currently selected revision, or None."""
303 by Daniel Schierbeck
Made basic signaling work.
64
        return self.revision
65
305 by Daniel Schierbeck
Moved revision selection to the new view.
66
    def set_revision(self, revid):
322 by Jelmer Vernooij
Add docstrings.
67
        """Change the currently selected revision.
68
69
        :param revid: Revision id of revision to display.
70
        """
305 by Daniel Schierbeck
Moved revision selection to the new view.
71
        self.treeview.set_cursor(self.index[revid])
72
        self.treeview.grab_focus()
73
303 by Daniel Schierbeck
Made basic signaling work.
74
    def get_children(self):
322 by Jelmer Vernooij
Add docstrings.
75
        """Return the children of the currently selected revision.
76
77
        :return: list of revision ids.
78
        """
303 by Daniel Schierbeck
Made basic signaling work.
79
        return self.children
80
81
    def get_parents(self):
322 by Jelmer Vernooij
Add docstrings.
82
        """Return the parents of the currently selected revision.
83
84
        :return: list of revision ids.
85
        """
303 by Daniel Schierbeck
Made basic signaling work.
86
        return self.parents
316 by Daniel Schierbeck
Removed viz.TreeView.set_branch()
87
        
304 by Daniel Schierbeck
Made forward/back buttons work again.
88
    def back(self):
322 by Jelmer Vernooij
Add docstrings.
89
        """Signal handler for the Back button."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
90
        (path, col) = self.treeview.get_cursor()
91
        revision = self.model[path][treemodel.REVISION]
92
        parents = self.model[path][treemodel.PARENTS]
93
        if not len(parents):
94
            return
95
96
        for parent_id in parents:
97
            parent_index = self.index[parent_id]
98
            parent = self.model[parent_index][treemodel.REVISION]
99
            if same_branch(revision, parent):
100
                self.treeview.set_cursor(parent_index)
101
                break
102
        else:
103
            self.treeview.set_cursor(self.index[parents[0]])
104
        self.treeview.grab_focus()
105
106
    def forward(self):
322 by Jelmer Vernooij
Add docstrings.
107
        """Signal handler for the Forward button."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
108
        (path, col) = self.treeview.get_cursor()
109
        revision = self.model[path][treemodel.REVISION]
110
        children = self.model[path][treemodel.CHILDREN]
111
        if not len(children):
112
            return
113
114
        for child_id in children:
115
            child_index = self.index[child_id]
116
            child = self.model[child_index][treemodel.REVISION]
117
            if same_branch(child, revision):
118
                self.treeview.set_cursor(child_index)
119
                break
120
        else:
121
            self.treeview.set_cursor(self.index[children[0]])
122
        self.treeview.grab_focus()
123
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
124
    def populate(self, start, maxnum, broken_line_length=None):
322 by Jelmer Vernooij
Add docstrings.
125
        """Fill the treeview with contents.
126
127
        :param start: Revision id of revision to start with.
128
        :param maxnum: Maximum number of revisions to display, or None 
129
                       for no limit.
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
130
        :param broken_line_length: After how much lines branches \
131
                       should be broken.
322 by Jelmer Vernooij
Add docstrings.
132
        """
328 by Jelmer Vernooij
Use repository instead of branch in more places, to make it easier to support multiple branches in viz.
133
        (linegraphdata, index, columns_len) = linegraph(self.branch.repository,
304 by Daniel Schierbeck
Made forward/back buttons work again.
134
                                                        start,
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
135
                                                        maxnum, 
136
                                                        broken_line_length)
304 by Daniel Schierbeck
Made forward/back buttons work again.
137
328 by Jelmer Vernooij
Use repository instead of branch in more places, to make it easier to support multiple branches in viz.
138
        self.model = TreeModel(self.branch.repository, linegraphdata)
304 by Daniel Schierbeck
Made forward/back buttons work again.
139
        self.graph_cell.columns_len = columns_len
140
        width = self.graph_cell.get_size(self.treeview)[2]
141
        self.graph_column.set_fixed_width(width)
142
        self.graph_column.set_max_width(width)
143
        self.index = index
144
        self.treeview.set_model(self.model)
145
        self.treeview.set_cursor(0)
307 by Daniel Schierbeck
Made load notification work again.
146
        self.emit('revisions-loaded')
304 by Daniel Schierbeck
Made forward/back buttons work again.
147
148
        return False
149
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
150
    def show_diff(self, branch, revid, parentid=None):
306 by Daniel Schierbeck
Made clicking a row work again.
151
        """Open a new window to show a diff between the given revisions."""
152
        from bzrlib.plugins.gtk.diff import DiffWindow
153
        window = DiffWindow(parent=self)
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
154
155
        rev_tree    = branch.repository.revision_tree(revid)
330.4.3 by Daniel Schierbeck
Switched to using NULL_REVISION instead of None.
156
157
        if parentid is None:
158
            parentid = NULL_REVISION
159
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
160
        parent_tree = branch.repository.revision_tree(parentid)
161
306 by Daniel Schierbeck
Made clicking a row work again.
162
        description = revid + " - " + branch.nick
163
        window.set_diff(description, rev_tree, parent_tree)
164
        window.show()
165
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
166
    def construct_treeview(self):
167
        self.treeview = gtk.TreeView()
168
169
        self.treeview.set_rules_hint(True)
330.1.2 by Daniel Schierbeck
Replaced literal column index with equivalent symbol.
170
        self.treeview.set_search_column(treemodel.REVNO)
330.1.1 by Daniel Schierbeck
Added tooltip to the treeview.
171
        self.treeview.set_tooltip_column(treemodel.MESSAGE)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
172
303 by Daniel Schierbeck
Made basic signaling work.
173
        self.treeview.get_selection().connect("changed",
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
174
                self._on_selection_changed)
175
176
        self.treeview.connect("row-activated", 
177
                self._on_revision_activated)
178
179
        self.treeview.connect("button-release-event", 
180
                self._on_revision_selected)
181
182
        self.treeview.set_property('fixed-height-mode', True)
183
184
        self.add(self.treeview)
185
        self.treeview.show()
186
187
        cell = gtk.CellRendererText()
188
        cell.set_property("width-chars", 15)
189
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
190
        column = gtk.TreeViewColumn("Revision No")
191
        column.set_resizable(True)
192
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
193
        column.set_fixed_width(cell.get_size(self.treeview)[2])
194
        column.pack_start(cell, expand=True)
195
        column.add_attribute(cell, "text", treemodel.REVNO)
196
        self.treeview.append_column(column)
197
198
        self.graph_cell = CellRendererGraph()
199
        self.graph_column = gtk.TreeViewColumn()
200
        self.graph_column.set_resizable(True)
201
        self.graph_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
202
        self.graph_column.pack_start(self.graph_cell, expand=False)
203
        self.graph_column.add_attribute(self.graph_cell, "node", treemodel.NODE)
204
        self.graph_column.add_attribute(self.graph_cell, "in-lines", treemodel.LAST_LINES)
205
        self.graph_column.add_attribute(self.graph_cell, "out-lines", treemodel.LINES)
206
        self.treeview.append_column(self.graph_column)
207
208
        cell = gtk.CellRendererText()
209
        cell.set_property("width-chars", 65)
210
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
211
        column = gtk.TreeViewColumn("Message")
212
        column.set_resizable(True)
213
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
214
        column.set_fixed_width(cell.get_size(self.treeview)[2])
215
        column.pack_start(cell, expand=True)
216
        column.add_attribute(cell, "text", treemodel.MESSAGE)
217
        self.treeview.append_column(column)
218
219
        cell = gtk.CellRendererText()
220
        cell.set_property("width-chars", 15)
221
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
222
        column = gtk.TreeViewColumn("Committer")
223
        column.set_resizable(True)
224
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
225
        column.set_fixed_width(cell.get_size(self.treeview)[2])
226
        column.pack_start(cell, expand=True)
227
        column.add_attribute(cell, "text", treemodel.COMMITER)
228
        self.treeview.append_column(column)
229
230
    def _on_selection_changed(self, selection, *args):
303 by Daniel Schierbeck
Made basic signaling work.
231
        """callback for when the treeview changes."""
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
232
        (model, selected_rows) = selection.get_selected_rows()
233
        if len(selected_rows) > 0:
234
            iter = self.model.get_iter(selected_rows[0])
303 by Daniel Schierbeck
Made basic signaling work.
235
            self.revision = self.model.get_value(iter, treemodel.REVISION)
236
            self.parents = self.model.get_value(iter, treemodel.PARENTS)
237
            self.children = self.model.get_value(iter, treemodel.CHILDREN)
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
238
310 by Daniel Schierbeck
Moved to using custom signal for handling revision selections.
239
            self.emit('revision-selected')
240
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
241
    def _on_revision_selected(self, widget, event):
242
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
243
        if event.button == 3:
244
            menu = RevisionPopupMenu(self.branch.repository, 
312 by Daniel Schierbeck
Made right-clicking work again.
245
                [self.get_revision().revision_id],
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
246
                self.branch)
247
            menu.popup(None, None, None, event.button, event.get_time())
248
249
    def _on_revision_activated(self, widget, path, col):
250
        # TODO: more than one parent
251
        """Callback for when a treeview row gets activated."""
252
        revision_id = self.model[path][treemodel.REVID]
253
        parents = self.model[path][treemodel.PARENTS]
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
254
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
255
        if len(parents) == 0:
330.4.1 by Daniel Schierbeck
Made it possible to view the diff of an orphant revision.
256
            parent_id = None
257
        else:
258
            parent_id = parents[0]
259
301 by Daniel Schierbeck
Initial work on extracting the TreeView from the branch window.
260
        self.show_diff(self.branch, revision_id, parent_id)
261
        self.treeview.grab_focus()