/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to viz/branchwin.py

  • Committer: Mateusz Korniak
  • Date: 2007-09-02 15:42:18 UTC
  • mto: This revision was merged to the branch mainline in revision 274.
  • Revision ID: matkor@laptop-hp-20070902154218-nba0woaqjsn20f9n
Ignoring eric3 project files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
1
# -*- coding: UTF-8 -*-
3
2
"""Branch window.
4
3
 
10
9
__author__    = "Scott James Remnant <scott@ubuntu.com>"
11
10
 
12
11
 
13
 
import os
14
 
 
15
12
import gtk
16
13
import gobject
17
14
import pango
18
15
 
19
16
from bzrlib.osutils import format_date
20
17
 
21
 
from graph import graph
 
18
from graph import distances, graph, same_branch
22
19
from graphcell import CellRendererGraph
23
20
 
24
21
 
36
33
 
37
34
        # Use three-quarters of the screen by default
38
35
        screen = self.get_screen()
39
 
        width = int(screen.get_width() * 0.75)
40
 
        height = int(screen.get_height() * 0.75)
 
36
        monitor = screen.get_monitor_geometry(0)
 
37
        width = int(monitor.width * 0.75)
 
38
        height = int(monitor.height * 0.75)
41
39
        self.set_default_size(width, height)
42
40
 
43
41
        # FIXME AndyFitz!
44
42
        icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
45
43
        self.set_icon(icon)
46
44
 
 
45
        self.accel_group = gtk.AccelGroup()
 
46
        self.add_accel_group(self.accel_group)
 
47
 
47
48
        self.construct()
48
49
 
49
50
    def construct(self):
50
51
        """Construct the window contents."""
 
52
        vbox = gtk.VBox(spacing=0)
 
53
        self.add(vbox)
 
54
 
 
55
        vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
 
56
 
 
57
        paned = gtk.VPaned()
 
58
        paned.pack1(self.construct_top(), resize=True, shrink=False)
 
59
        paned.pack2(self.construct_bottom(), resize=False, shrink=True)
 
60
        paned.show()
 
61
        vbox.pack_start(paned, expand=True, fill=True)
 
62
        vbox.set_focus_child(paned)
 
63
 
 
64
        vbox.show()
 
65
 
 
66
    def construct_top(self):
 
67
        """Construct the top-half of the window."""
51
68
        scrollwin = gtk.ScrolledWindow()
52
69
        scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
53
70
        scrollwin.set_shadow_type(gtk.SHADOW_IN)
54
 
        scrollwin.set_border_width(12)
55
 
        self.add(scrollwin)
56
71
        scrollwin.show()
57
72
 
58
73
        self.treeview = gtk.TreeView()
59
74
        self.treeview.set_rules_hint(True)
60
75
        self.treeview.set_search_column(4)
 
76
        self.treeview.connect("cursor-changed", self._treeview_cursor_cb)
 
77
        self.treeview.connect("row-activated", self._treeview_row_activated_cb)
 
78
        self.treeview.connect("button-release-event", 
 
79
                self._treeview_row_mouseclick)
61
80
        scrollwin.add(self.treeview)
62
81
        self.treeview.show()
63
82
 
64
83
        cell = CellRendererGraph()
65
84
        column = gtk.TreeViewColumn()
66
 
        column.set_resizable(False)
 
85
        column.set_resizable(True)
67
86
        column.pack_start(cell, expand=False)
68
87
        column.add_attribute(cell, "node", 1)
69
88
        column.add_attribute(cell, "in-lines", 2)
96
115
        column.add_attribute(cell, "text", 6)
97
116
        self.treeview.append_column(column)
98
117
 
99
 
    def set_branch(self, branch, start):
 
118
        return scrollwin
 
119
 
 
120
    def construct_navigation(self):
 
121
        """Construct the navigation buttons."""
 
122
        frame = gtk.Frame()
 
123
        frame.set_shadow_type(gtk.SHADOW_OUT)
 
124
        frame.show()
 
125
        
 
126
        hbox = gtk.HBox(spacing=12)
 
127
        frame.add(hbox)
 
128
        hbox.show()
 
129
 
 
130
        self.back_button = gtk.Button(stock=gtk.STOCK_GO_BACK)
 
131
        self.back_button.set_relief(gtk.RELIEF_NONE)
 
132
        self.back_button.add_accelerator("clicked", self.accel_group, ord('['),
 
133
                                         0, 0)
 
134
        self.back_button.connect("clicked", self._back_clicked_cb)
 
135
        hbox.pack_start(self.back_button, expand=False, fill=True)
 
136
        self.back_button.show()
 
137
 
 
138
        self.fwd_button = gtk.Button(stock=gtk.STOCK_GO_FORWARD)
 
139
        self.fwd_button.set_relief(gtk.RELIEF_NONE)
 
140
        self.fwd_button.add_accelerator("clicked", self.accel_group, ord(']'),
 
141
                                        0, 0)
 
142
        self.fwd_button.connect("clicked", self._fwd_clicked_cb)
 
143
        hbox.pack_start(self.fwd_button, expand=False, fill=True)
 
144
        self.fwd_button.show()
 
145
 
 
146
        return frame
 
147
 
 
148
    def construct_bottom(self):
 
149
        """Construct the bottom half of the window."""
 
150
        from bzrlib.plugins.gtk.logview import LogView
 
151
        self.logview = LogView()
 
152
        (width, height) = self.get_size()
 
153
        self.logview.set_size_request(width, int(height / 2.5))
 
154
        self.logview.show()
 
155
        self.logview.set_show_callback(self._show_clicked_cb)
 
156
        self.logview.set_go_callback(self._go_clicked_cb)
 
157
        return self.logview
 
158
 
 
159
    def set_branch(self, branch, start, maxnum):
100
160
        """Set the branch and start position for this window.
101
161
 
102
162
        Creates a new TreeModel and populates it with information about
103
163
        the new branch before updating the window title and model of the
104
164
        treeview itself.
105
165
        """
 
166
        self.branch = branch
 
167
 
106
168
        # [ revision, node, last_lines, lines, message, committer, timestamp ]
107
 
        model = gtk.ListStore(gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
108
 
                              gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
109
 
                              str, str, str)
 
169
        self.model = gtk.ListStore(gobject.TYPE_PYOBJECT,
 
170
                                   gobject.TYPE_PYOBJECT,
 
171
                                   gobject.TYPE_PYOBJECT,
 
172
                                   gobject.TYPE_PYOBJECT,
 
173
                                   str, str, str)
 
174
        self.index = {}
 
175
        self.set_title(branch.nick + " - bzrk")
 
176
        gobject.idle_add(self.populate_model, start, maxnum)
110
177
 
 
178
    def populate_model(self, start, maxnum):
 
179
        index = 0
 
180
        
111
181
        last_lines = []
112
 
        for revision, node, lines in graph(branch, start):
 
182
        (self.revisions, colours, self.children, self.parent_ids,
 
183
            merge_sorted) = distances(self.branch.repository, start)
 
184
        for (index, (revision, node, lines)) in enumerate(graph(
 
185
                self.revisions, colours, merge_sorted)):
 
186
            # FIXME: at this point we should be able to show the graph order
 
187
            # and lines with no message or commit data - and then incrementally
 
188
            # fill the timestamp, committer etc data as desired.
113
189
            message = revision.message.split("\n")[0]
114
190
            if revision.committer is not None:
115
191
                timestamp = format_date(revision.timestamp, revision.timezone)
116
192
            else:
117
193
                timestamp = None
118
 
 
119
 
            model.append([ revision, node, last_lines, lines,
120
 
                           message, revision.committer, timestamp ])
 
194
            self.model.append([revision, node, last_lines, lines,
 
195
                               message, revision.committer, timestamp])
 
196
            self.index[revision] = index
121
197
            last_lines = lines
122
 
 
123
 
        self.set_title(os.path.basename(branch.base) + " - bzrk")
124
 
        self.treeview.set_model(model)
 
198
            if maxnum is not None and index > maxnum:
 
199
                break
 
200
        self.treeview.set_model(self.model)
 
201
        return False
 
202
    
 
203
    
 
204
    def _treeview_cursor_cb(self, *args):
 
205
        """Callback for when the treeview cursor changes."""
 
206
        (path, col) = self.treeview.get_cursor()
 
207
        revision = self.model[path][0]
 
208
 
 
209
        self.back_button.set_sensitive(len(self.parent_ids[revision]) > 0)
 
210
        self.fwd_button.set_sensitive(len(self.children[revision]) > 0)
 
211
        tags = []
 
212
        if self.branch.supports_tags():
 
213
            tagdict = self.branch.tags.get_reverse_tag_dict()
 
214
            if tagdict.has_key(revision.revision_id):
 
215
                tags = tagdict[revision.revision_id]
 
216
        self.logview.set_revision(revision, tags)
 
217
 
 
218
    def _back_clicked_cb(self, *args):
 
219
        """Callback for when the back button is clicked."""
 
220
        (path, col) = self.treeview.get_cursor()
 
221
        revision = self.model[path][0]
 
222
        if not len(self.parent_ids[revision]):
 
223
            return
 
224
 
 
225
        for parent_id in self.parent_ids[revision]:
 
226
            parent = self.revisions[parent_id]
 
227
            if same_branch(revision, parent):
 
228
                self.treeview.set_cursor(self.index[parent])
 
229
                break
 
230
        else:
 
231
            next = self.revisions[self.parent_ids[revision][0]]
 
232
            self.treeview.set_cursor(self.index[next])
 
233
        self.treeview.grab_focus()
 
234
 
 
235
    def _fwd_clicked_cb(self, *args):
 
236
        """Callback for when the forward button is clicked."""
 
237
        (path, col) = self.treeview.get_cursor()
 
238
        revision = self.model[path][0]
 
239
        if not len(self.children[revision]):
 
240
            return
 
241
 
 
242
        for child in self.children[revision]:
 
243
            if same_branch(child, revision):
 
244
                self.treeview.set_cursor(self.index[child])
 
245
                break
 
246
        else:
 
247
            prev = list(self.children[revision])[0]
 
248
            self.treeview.set_cursor(self.index[prev])
 
249
        self.treeview.grab_focus()
 
250
 
 
251
    def _go_clicked_cb(self, revid):
 
252
        """Callback for when the go button for a parent is clicked."""
 
253
        self.treeview.set_cursor(self.index[self.revisions[revid]])
 
254
        self.treeview.grab_focus()
 
255
 
 
256
    def show_diff(self, branch, revid, parentid):
 
257
        """Open a new window to show a diff between the given revisions."""
 
258
        from bzrlib.plugins.gtk.diff import DiffWindow
 
259
        window = DiffWindow()
 
260
        (parent_tree, rev_tree) = branch.repository.revision_trees([parentid, 
 
261
                                                                   revid])
 
262
        description = revid + " - " + branch.nick
 
263
        window.set_diff(description, rev_tree, parent_tree)
 
264
        window.show()
 
265
 
 
266
    def _show_clicked_cb(self, revid, parentid):
 
267
        """Callback for when the show button for a parent is clicked."""
 
268
        self.show_diff(self.branch, revid, parentid)
 
269
        self.treeview.grab_focus()
 
270
 
 
271
    def _treeview_row_mouseclick(self, widget, event):
 
272
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
 
273
        if event.button == 3:
 
274
            menu = RevisionPopupMenu(self.branch.repository, 
 
275
                [x.revision_id for x in self.selected_revisions()],
 
276
                self.branch)
 
277
            menu.popup(None, None, None, event.button, event.get_time())
 
278
 
 
279
    def selected_revision(self, path):
 
280
        return self.model[path][0]
 
281
 
 
282
    def selected_revisions(self):
 
283
        return [self.selected_revision(path) for path in \
 
284
                self.treeview.get_selection().get_selected_rows()[1]]
 
285
 
 
286
    def _treeview_row_activated_cb(self, widget, path, col):
 
287
        # TODO: more than one parent
 
288
        """Callback for when a treeview row gets activated."""
 
289
        revision = self.selected_revision(path)
 
290
        if len(self.parent_ids[revision]) == 0:
 
291
            # Ignore revisions without parent
 
292
            return
 
293
        parent_id = self.parent_ids[revision][0]
 
294
        self.show_diff(self.branch, revision.revision_id, parent_id)
 
295
        self.treeview.grab_focus()