/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
1 by Scott James Remnant
Commit the first version of bzrk.
1
# -*- coding: UTF-8 -*-
2
"""Branch window.
3
4
This module contains the code to manage the branch information window,
5
which contains both the revision graph and details panes.
6
"""
7
8
__copyright__ = "Copyright © 2005 Canonical Ltd."
9
__author__    = "Scott James Remnant <scott@ubuntu.com>"
10
11
12
import gtk
13
import gobject
14
import pango
15
298.2.1 by Daniel Schierbeck
Refactored the GTK window code, creating a single base window class that handles keyboard events.
16
from bzrlib.plugins.gtk.window import Window
338 by Daniel Schierbeck
Added Preferences menu item.
17
from bzrlib.plugins.gtk.preferences import PreferencesWindow
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
18
from bzrlib.revision import Revision
333 by Daniel Schierbeck
Removed unnecessary imports.
19
from treeview import TreeView
1 by Scott James Remnant
Commit the first version of bzrk.
20
298.2.1 by Daniel Schierbeck
Refactored the GTK window code, creating a single base window class that handles keyboard events.
21
class BranchWindow(Window):
1 by Scott James Remnant
Commit the first version of bzrk.
22
    """Branch window.
23
24
    This object represents and manages a single window containing information
25
    for a particular branch.
26
    """
27
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
28
    def __init__(self, branch, start, maxnum, parent=None):
322 by Jelmer Vernooij
Add docstrings.
29
        """Create a new BranchWindow.
30
31
        :param branch: Branch object for branch to show.
32
        :param start: Revision id of top revision.
33
        :param maxnum: Maximum number of revisions to display, 
34
                       None for no limit.
35
        """
36
298.2.1 by Daniel Schierbeck
Refactored the GTK window code, creating a single base window class that handles keyboard events.
37
        Window.__init__(self, parent=parent)
1 by Scott James Remnant
Commit the first version of bzrk.
38
        self.set_border_width(0)
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
39
40
        self.branch = branch
41
        self.start  = start
42
        self.maxnum = maxnum
43
44
        self.set_title(branch.nick + " - revision history")
1 by Scott James Remnant
Commit the first version of bzrk.
45
46
        # Use three-quarters of the screen by default
47
        screen = self.get_screen()
4 by Scott James Remnant
Use the size of the first monitor rather than the entire screen
48
        monitor = screen.get_monitor_geometry(0)
49
        width = int(monitor.width * 0.75)
50
        height = int(monitor.height * 0.75)
1 by Scott James Remnant
Commit the first version of bzrk.
51
        self.set_default_size(width, height)
52
53
        # FIXME AndyFitz!
54
        icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
55
        self.set_icon(icon)
56
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
57
        self.accel_group = gtk.AccelGroup()
58
        self.add_accel_group(self.accel_group)
59
1 by Scott James Remnant
Commit the first version of bzrk.
60
        self.construct()
61
62
    def construct(self):
63
        """Construct the window contents."""
331 by Daniel Schierbeck
Added basic menu bar.
64
        vbox = gtk.VBox(spacing=0)
44 by David Allouche
reorganise branch window
65
        self.add(vbox)
66
358 by Daniel Schierbeck
Generalized the hiding/showing code.
67
        top = self.construct_top()
68
331 by Daniel Schierbeck
Added basic menu bar.
69
        vbox.pack_start(self.construct_menubar(), expand=False, fill=True)
44 by David Allouche
reorganise branch window
70
        vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
280.2.1 by Gary van der Merwe
Add a message to the viz window to indicate that graph is still loading.
71
        vbox.pack_start(self.construct_loading_msg(), expand=False, fill=True)
72
        
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
73
        paned = gtk.VPaned()
358 by Daniel Schierbeck
Generalized the hiding/showing code.
74
        paned.pack1(top, resize=True, shrink=False)
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
75
        paned.pack2(self.construct_bottom(), resize=False, shrink=True)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
76
        paned.show()
44 by David Allouche
reorganise branch window
77
        vbox.pack_start(paned, expand=True, fill=True)
78
        vbox.set_focus_child(paned)
79
80
        vbox.show()
331 by Daniel Schierbeck
Added basic menu bar.
81
82
    def construct_menubar(self):
83
        menubar = gtk.MenuBar()
84
85
        file_menu = gtk.Menu()
334 by Daniel Schierbeck
Added icons to menus.
86
        file_menuitem = gtk.MenuItem("_File")
331 by Daniel Schierbeck
Added basic menu bar.
87
        file_menuitem.set_submenu(file_menu)
88
334 by Daniel Schierbeck
Added icons to menus.
89
        file_menu_close = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
331 by Daniel Schierbeck
Added basic menu bar.
90
        file_menu_close.connect('activate', lambda x: self.destroy())
91
        
92
        file_menu.add(file_menu_close)
93
338 by Daniel Schierbeck
Added Preferences menu item.
94
        edit_menu = gtk.Menu()
95
        edit_menuitem = gtk.MenuItem("_Edit")
96
        edit_menuitem.set_submenu(edit_menu)
97
340 by Daniel Schierbeck
Added edit->find menu item stub.
98
        edit_menu_find = gtk.ImageMenuItem(gtk.STOCK_FIND)
99
338 by Daniel Schierbeck
Added Preferences menu item.
100
        edit_menu_prefs = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
101
        edit_menu_prefs.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
102
340 by Daniel Schierbeck
Added edit->find menu item stub.
103
        edit_menu.add(edit_menu_find)
338 by Daniel Schierbeck
Added Preferences menu item.
104
        edit_menu.add(edit_menu_prefs)
105
348 by Daniel Schierbeck
Added toggle item for revision number column.
106
        view_menu = gtk.Menu()
107
        view_menuitem = gtk.MenuItem("_View")
108
        view_menuitem.set_submenu(view_menu)
109
351 by Daniel Schierbeck
Added option to hide the toolbar.
110
        view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
111
        view_menu_toolbar.set_active(True)
112
        view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
113
114
        view_menu.add(view_menu_toolbar)
115
        view_menu.add(gtk.SeparatorMenuItem())
358 by Daniel Schierbeck
Generalized the hiding/showing code.
116
117
        for (label, name) in [("Revision _Number", "revno"), ("_Date", "date")]:
118
            col = gtk.CheckMenuItem("Show " + label + " Column")
119
            col.set_active(self.treeview.get_property(name + "-column-visible"))
120
            col.connect('toggled', self._col_visibility_changed, name)
121
            view_menu.add(col)
348 by Daniel Schierbeck
Added toggle item for revision number column.
122
331 by Daniel Schierbeck
Added basic menu bar.
123
        go_menu = gtk.Menu()
334 by Daniel Schierbeck
Added icons to menus.
124
        go_menuitem = gtk.MenuItem("_Go")
331 by Daniel Schierbeck
Added basic menu bar.
125
        go_menuitem.set_submenu(go_menu)
126
        
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
127
        go_menu_back = gtk.ImageMenuItem(gtk.STOCK_GO_DOWN)
334 by Daniel Schierbeck
Added icons to menus.
128
        go_menu_back.connect("activate", self._back_clicked_cb)
129
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
130
        go_menu_forward = gtk.ImageMenuItem(gtk.STOCK_GO_UP)
334 by Daniel Schierbeck
Added icons to menus.
131
        go_menu_forward.connect("activate", self._fwd_clicked_cb)
331 by Daniel Schierbeck
Added basic menu bar.
132
332 by Daniel Schierbeck
Made tag selection work.
133
        tags_menu = gtk.Menu()
334 by Daniel Schierbeck
Added icons to menus.
134
        go_menu_tags = gtk.MenuItem("_Tags")
135
        go_menu_tags.set_submenu(tags_menu)
332 by Daniel Schierbeck
Made tag selection work.
136
137
        for (tag, revid) in self.branch.tags.get_tag_dict().items():
138
            tag_item = gtk.MenuItem(tag)
139
            tag_item.connect('activate', self._tag_selected_cb, revid)
140
            tags_menu.add(tag_item)
141
334 by Daniel Schierbeck
Added icons to menus.
142
        go_menu.add(go_menu_back)
143
        go_menu.add(go_menu_forward)
144
        go_menu.add(gtk.SeparatorMenuItem())
145
        go_menu.add(go_menu_tags)
146
335 by Daniel Schierbeck
Added Revision menu.
147
        revision_menu = gtk.Menu()
148
        revision_menuitem = gtk.MenuItem("_Revision")
149
        revision_menuitem.set_submenu(revision_menu)
150
336 by Daniel Schierbeck
Changed wording to comply with HIG guidelines.
151
        revision_menu.add(gtk.MenuItem("Tag Revision"))
152
        revision_menu.add(gtk.MenuItem("View Changes"))
335 by Daniel Schierbeck
Added Revision menu.
153
334 by Daniel Schierbeck
Added icons to menus.
154
        branch_menu = gtk.Menu()
155
        branch_menuitem = gtk.MenuItem("_Branch")
156
        branch_menuitem.set_submenu(branch_menu)
157
336 by Daniel Schierbeck
Changed wording to comply with HIG guidelines.
158
        branch_menu.add(gtk.MenuItem("Pu_ll Revisions"))
159
        branch_menu.add(gtk.MenuItem("Pu_sh Revisions"))
334 by Daniel Schierbeck
Added icons to menus.
160
       
331 by Daniel Schierbeck
Added basic menu bar.
161
        menubar.add(file_menuitem)
338 by Daniel Schierbeck
Added Preferences menu item.
162
        menubar.add(edit_menuitem)
348 by Daniel Schierbeck
Added toggle item for revision number column.
163
        menubar.add(view_menuitem)
331 by Daniel Schierbeck
Added basic menu bar.
164
        menubar.add(go_menuitem)
335 by Daniel Schierbeck
Added Revision menu.
165
        menubar.add(revision_menuitem)
331 by Daniel Schierbeck
Added basic menu bar.
166
        menubar.add(branch_menuitem)
167
        menubar.show_all()
168
169
        return menubar
280.2.1 by Gary van der Merwe
Add a message to the viz window to indicate that graph is still loading.
170
    
171
    def construct_loading_msg(self):
172
        image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
173
                                                 gtk.ICON_SIZE_BUTTON)
174
        image_loading.show()
175
        
176
        label_loading = gtk.Label(_("Please wait, loading ancestral graph..."))
331 by Daniel Schierbeck
Added basic menu bar.
177
        label_loading.set_alignment(0.0, 0.5)  
280.2.1 by Gary van der Merwe
Add a message to the viz window to indicate that graph is still loading.
178
        label_loading.show()
179
        
180
        self.loading_msg_box = gtk.HBox()
181
        self.loading_msg_box.set_spacing(5)
182
        self.loading_msg_box.set_border_width(5)        
183
        self.loading_msg_box.pack_start(image_loading, False, False)
184
        self.loading_msg_box.pack_start(label_loading, True, True)
185
        self.loading_msg_box.show()
186
        
187
        return self.loading_msg_box
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
188
189
    def construct_top(self):
190
        """Construct the top-half of the window."""
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
191
        # FIXME: Make broken_line_length configurable
192
        self.treeview = TreeView(self.branch, self.start, self.maxnum, 32)
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
193
310 by Daniel Schierbeck
Moved to using custom signal for handling revision selections.
194
        self.treeview.connect("revision-selected",
303 by Daniel Schierbeck
Made basic signaling work.
195
                self._treeselection_changed_cb)
196
307 by Daniel Schierbeck
Made load notification work again.
197
        self.treeview.connect('revisions-loaded', 
198
                lambda x: self.loading_msg_box.hide())
199
1 by Scott James Remnant
Commit the first version of bzrk.
200
        self.treeview.show()
201
303 by Daniel Schierbeck
Made basic signaling work.
202
        return self.treeview
44 by David Allouche
reorganise branch window
203
204
    def construct_navigation(self):
205
        """Construct the navigation buttons."""
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
206
        self.toolbar = gtk.Toolbar()
207
        self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
208
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
209
        self.back_button = gtk.MenuToolButton(stock_id=gtk.STOCK_GO_DOWN)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
210
        self.back_button.add_accelerator("clicked", self.accel_group, ord('['),
211
                                         0, 0)
212
        self.back_button.connect("clicked", self._back_clicked_cb)
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
213
        self.toolbar.insert(self.back_button, -1)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
214
        self.back_button.show()
215
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
216
        self.fwd_button = gtk.MenuToolButton(stock_id=gtk.STOCK_GO_UP)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
217
        self.fwd_button.add_accelerator("clicked", self.accel_group, ord(']'),
218
                                        0, 0)
219
        self.fwd_button.connect("clicked", self._fwd_clicked_cb)
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
220
        self.toolbar.insert(self.fwd_button, -1)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
221
        self.fwd_button.show()
222
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
223
        self.toolbar.show()
224
225
        return self.toolbar
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
226
227
    def construct_bottom(self):
228
        """Construct the bottom half of the window."""
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
229
        from bzrlib.plugins.gtk.revisionview import RevisionView
230
        self.revisionview = RevisionView(None, tags=[], show_children=True, branch=self.branch)
44 by David Allouche
reorganise branch window
231
        (width, height) = self.get_size()
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
232
        self.revisionview.set_size_request(width, int(height / 2.5))
233
        self.revisionview.show()
234
        self.revisionview.set_show_callback(self._show_clicked_cb)
235
        self.revisionview.set_go_callback(self._go_clicked_cb)
236
        return self.revisionview
332 by Daniel Schierbeck
Made tag selection work.
237
238
    def _tag_selected_cb(self, menuitem, revid):
356 by Daniel Schierbeck
Made revision a property on TreeView.
239
        self.treeview.set_revision_id(revid)
341 by Daniel Schierbeck
Merged with trunk.
240
280.1.2 by Daniel Schierbeck
Switched to handle the 'changed' signal from the treeview's treeselection instead of the 'cursor-changed' signal from the treeview itself, allowing more flexibility (particularly the ability to handle programmatic selections)
241
    def _treeselection_changed_cb(self, selection, *args):
303 by Daniel Schierbeck
Made basic signaling work.
242
        """callback for when the treeview changes."""
243
        revision = self.treeview.get_revision()
244
        parents  = self.treeview.get_parents()
245
        children = self.treeview.get_children()
246
247
        if revision is not None:
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
248
            back_menu = gtk.Menu()
249
            if len(parents) > 0:
250
                self.back_button.set_sensitive(True)
251
                for parent_id in parents:
252
                    parent = self.branch.repository.get_revision(parent_id)
355 by Daniel Schierbeck
Appended branch nick to parent and child popup menus.
253
                    try:
254
                        str = ' (' + parent.properties['branch-nick'] + ')'
255
                    except KeyError:
256
                        str = ""
257
258
                    item = gtk.MenuItem(parent.message.split("\n")[0] + str)
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
259
                    item.connect('activate', self._set_revision_cb, parent_id)
260
                    back_menu.add(item)
261
                back_menu.show_all()
262
            else:
263
                self.back_button.set_sensitive(False)
264
                back_menu.hide()
265
266
            self.back_button.set_menu(back_menu)
267
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
268
            fwd_menu = gtk.Menu()
269
            if len(children) > 0:
270
                self.fwd_button.set_sensitive(True)
271
                for child_id in children:
272
                    child = self.branch.repository.get_revision(child_id)
355 by Daniel Schierbeck
Appended branch nick to parent and child popup menus.
273
                    try:
274
                        str = ' (' + child.properties['branch-nick'] + ')'
275
                    except KeyError:
276
                        str = ""
277
278
                    item = gtk.MenuItem(child.message.split("\n")[0] + str)
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
279
                    item.connect('activate', self._set_revision_cb, child_id)
280
                    fwd_menu.add(item)
281
                fwd_menu.show_all()
282
            else:
283
                self.fwd_button.set_sensitive(False)
284
                fwd_menu.hide()
285
286
            self.fwd_button.set_menu(fwd_menu)
287
280.1.2 by Daniel Schierbeck
Switched to handle the 'changed' signal from the treeview's treeselection instead of the 'cursor-changed' signal from the treeview itself, allowing more flexibility (particularly the ability to handle programmatic selections)
288
            tags = []
289
            if self.branch.supports_tags():
290
                tagdict = self.branch.tags.get_reverse_tag_dict()
291
                if tagdict.has_key(revision.revision_id):
292
                    tags = tagdict[revision.revision_id]
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
293
            self.revisionview.set_revision(revision, tags, children)
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
294
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
295
    def _back_clicked_cb(self, *args):
296
        """Callback for when the back button is clicked."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
297
        self.treeview.back()
298
        
5 by Scott James Remnant
Reverse the meaning of the Back and Forward buttons so Back actually
299
    def _fwd_clicked_cb(self, *args):
300
        """Callback for when the forward button is clicked."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
301
        self.treeview.forward()
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
302
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
303
    def _go_clicked_cb(self, revid):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
304
        """Callback for when the go button for a parent is clicked."""
356 by Daniel Schierbeck
Made revision a property on TreeView.
305
        self.treeview.set_revision_id(revid)
152 by Jelmer Vernooij
Cleanup some more code.
306
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
307
    def _show_clicked_cb(self, revid, parentid):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
308
        """Callback for when the show button for a parent is clicked."""
308 by Daniel Schierbeck
Made Show Diff work again.
309
        self.treeview.show_diff(self.branch, revid, parentid)
13 by Scott James Remnant
Keep the focus on the treeview
310
        self.treeview.grab_focus()
46 by Wouter van Heyst
show diff on row activation, LP# 44591
311
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
312
    def _set_revision_cb(self, w, revision_id):
356 by Daniel Schierbeck
Made revision a property on TreeView.
313
        self.treeview.set_revision_id(revision_id)
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
314
348 by Daniel Schierbeck
Added toggle item for revision number column.
315
    def _col_visibility_changed(self, col, property):
316
        self.treeview.set_property(property + '-column-visible', col.get_active())
351 by Daniel Schierbeck
Added option to hide the toolbar.
317
318
    def _toolbar_visibility_changed(self, col):
319
        if col.get_active():
320
            self.toolbar.show() 
321
        else:
322
            self.toolbar.hide()