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