/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
331 by Daniel Schierbeck
Added basic menu bar.
67
        vbox.pack_start(self.construct_menubar(), expand=False, fill=True)
44 by David Allouche
reorganise branch window
68
        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.
69
        vbox.pack_start(self.construct_loading_msg(), expand=False, fill=True)
70
        
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
71
        paned = gtk.VPaned()
72
        paned.pack1(self.construct_top(), resize=True, shrink=False)
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
73
        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
74
        paned.show()
44 by David Allouche
reorganise branch window
75
        vbox.pack_start(paned, expand=True, fill=True)
76
        vbox.set_focus_child(paned)
77
78
        vbox.show()
331 by Daniel Schierbeck
Added basic menu bar.
79
80
    def construct_menubar(self):
81
        menubar = gtk.MenuBar()
82
83
        file_menu = gtk.Menu()
334 by Daniel Schierbeck
Added icons to menus.
84
        file_menuitem = gtk.MenuItem("_File")
331 by Daniel Schierbeck
Added basic menu bar.
85
        file_menuitem.set_submenu(file_menu)
86
334 by Daniel Schierbeck
Added icons to menus.
87
        file_menu_close = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
331 by Daniel Schierbeck
Added basic menu bar.
88
        file_menu_close.connect('activate', lambda x: self.destroy())
89
        
90
        file_menu.add(file_menu_close)
91
338 by Daniel Schierbeck
Added Preferences menu item.
92
        edit_menu = gtk.Menu()
93
        edit_menuitem = gtk.MenuItem("_Edit")
94
        edit_menuitem.set_submenu(edit_menu)
95
340 by Daniel Schierbeck
Added edit->find menu item stub.
96
        edit_menu_find = gtk.ImageMenuItem(gtk.STOCK_FIND)
97
338 by Daniel Schierbeck
Added Preferences menu item.
98
        edit_menu_prefs = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
99
        edit_menu_prefs.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
100
340 by Daniel Schierbeck
Added edit->find menu item stub.
101
        edit_menu.add(edit_menu_find)
338 by Daniel Schierbeck
Added Preferences menu item.
102
        edit_menu.add(edit_menu_prefs)
103
348 by Daniel Schierbeck
Added toggle item for revision number column.
104
        view_menu = gtk.Menu()
105
        view_menuitem = gtk.MenuItem("_View")
106
        view_menuitem.set_submenu(view_menu)
107
351 by Daniel Schierbeck
Added option to hide the toolbar.
108
        view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
109
        view_menu_toolbar.set_active(True)
110
        view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
111
350 by Daniel Schierbeck
Capitalized menu item label.
112
        view_menu_revno_col = gtk.CheckMenuItem("Show Revision _Number Column")
348 by Daniel Schierbeck
Added toggle item for revision number column.
113
        view_menu_revno_col.set_active(True)
114
        view_menu_revno_col.connect('toggled', self._col_visibility_changed, 'revno')
115
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
116
        view_menu_date_col = gtk.CheckMenuItem("Show _Date Column")
117
        view_menu_date_col.set_active(False)
118
        view_menu_date_col.connect('toggled', self._col_visibility_changed, 'date')
119
351 by Daniel Schierbeck
Added option to hide the toolbar.
120
        view_menu.add(view_menu_toolbar)
121
        view_menu.add(gtk.SeparatorMenuItem())
348 by Daniel Schierbeck
Added toggle item for revision number column.
122
        view_menu.add(view_menu_revno_col)
357 by Daniel Schierbeck
Added support for showing the date column in the viz.
123
        view_menu.add(view_menu_date_col)
348 by Daniel Schierbeck
Added toggle item for revision number column.
124
331 by Daniel Schierbeck
Added basic menu bar.
125
        go_menu = gtk.Menu()
334 by Daniel Schierbeck
Added icons to menus.
126
        go_menuitem = gtk.MenuItem("_Go")
331 by Daniel Schierbeck
Added basic menu bar.
127
        go_menuitem.set_submenu(go_menu)
128
        
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
129
        go_menu_back = gtk.ImageMenuItem(gtk.STOCK_GO_DOWN)
334 by Daniel Schierbeck
Added icons to menus.
130
        go_menu_back.connect("activate", self._back_clicked_cb)
131
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
132
        go_menu_forward = gtk.ImageMenuItem(gtk.STOCK_GO_UP)
334 by Daniel Schierbeck
Added icons to menus.
133
        go_menu_forward.connect("activate", self._fwd_clicked_cb)
331 by Daniel Schierbeck
Added basic menu bar.
134
332 by Daniel Schierbeck
Made tag selection work.
135
        tags_menu = gtk.Menu()
334 by Daniel Schierbeck
Added icons to menus.
136
        go_menu_tags = gtk.MenuItem("_Tags")
137
        go_menu_tags.set_submenu(tags_menu)
332 by Daniel Schierbeck
Made tag selection work.
138
139
        for (tag, revid) in self.branch.tags.get_tag_dict().items():
140
            tag_item = gtk.MenuItem(tag)
141
            tag_item.connect('activate', self._tag_selected_cb, revid)
142
            tags_menu.add(tag_item)
143
334 by Daniel Schierbeck
Added icons to menus.
144
        go_menu.add(go_menu_back)
145
        go_menu.add(go_menu_forward)
146
        go_menu.add(gtk.SeparatorMenuItem())
147
        go_menu.add(go_menu_tags)
148
335 by Daniel Schierbeck
Added Revision menu.
149
        revision_menu = gtk.Menu()
150
        revision_menuitem = gtk.MenuItem("_Revision")
151
        revision_menuitem.set_submenu(revision_menu)
152
336 by Daniel Schierbeck
Changed wording to comply with HIG guidelines.
153
        revision_menu.add(gtk.MenuItem("Tag Revision"))
154
        revision_menu.add(gtk.MenuItem("View Changes"))
335 by Daniel Schierbeck
Added Revision menu.
155
334 by Daniel Schierbeck
Added icons to menus.
156
        branch_menu = gtk.Menu()
157
        branch_menuitem = gtk.MenuItem("_Branch")
158
        branch_menuitem.set_submenu(branch_menu)
159
336 by Daniel Schierbeck
Changed wording to comply with HIG guidelines.
160
        branch_menu.add(gtk.MenuItem("Pu_ll Revisions"))
161
        branch_menu.add(gtk.MenuItem("Pu_sh Revisions"))
334 by Daniel Schierbeck
Added icons to menus.
162
       
331 by Daniel Schierbeck
Added basic menu bar.
163
        menubar.add(file_menuitem)
338 by Daniel Schierbeck
Added Preferences menu item.
164
        menubar.add(edit_menuitem)
348 by Daniel Schierbeck
Added toggle item for revision number column.
165
        menubar.add(view_menuitem)
331 by Daniel Schierbeck
Added basic menu bar.
166
        menubar.add(go_menuitem)
335 by Daniel Schierbeck
Added Revision menu.
167
        menubar.add(revision_menuitem)
331 by Daniel Schierbeck
Added basic menu bar.
168
        menubar.add(branch_menuitem)
169
        menubar.show_all()
170
171
        return menubar
280.2.1 by Gary van der Merwe
Add a message to the viz window to indicate that graph is still loading.
172
    
173
    def construct_loading_msg(self):
174
        image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
175
                                                 gtk.ICON_SIZE_BUTTON)
176
        image_loading.show()
177
        
178
        label_loading = gtk.Label(_("Please wait, loading ancestral graph..."))
331 by Daniel Schierbeck
Added basic menu bar.
179
        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.
180
        label_loading.show()
181
        
182
        self.loading_msg_box = gtk.HBox()
183
        self.loading_msg_box.set_spacing(5)
184
        self.loading_msg_box.set_border_width(5)        
185
        self.loading_msg_box.pack_start(image_loading, False, False)
186
        self.loading_msg_box.pack_start(label_loading, True, True)
187
        self.loading_msg_box.show()
188
        
189
        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
190
191
    def construct_top(self):
192
        """Construct the top-half of the window."""
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
193
        # FIXME: Make broken_line_length configurable
194
        self.treeview = TreeView(self.branch, self.start, self.maxnum, 32)
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
195
310 by Daniel Schierbeck
Moved to using custom signal for handling revision selections.
196
        self.treeview.connect("revision-selected",
303 by Daniel Schierbeck
Made basic signaling work.
197
                self._treeselection_changed_cb)
198
307 by Daniel Schierbeck
Made load notification work again.
199
        self.treeview.connect('revisions-loaded', 
200
                lambda x: self.loading_msg_box.hide())
201
1 by Scott James Remnant
Commit the first version of bzrk.
202
        self.treeview.show()
203
303 by Daniel Schierbeck
Made basic signaling work.
204
        return self.treeview
44 by David Allouche
reorganise branch window
205
206
    def construct_navigation(self):
207
        """Construct the navigation buttons."""
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
208
        self.toolbar = gtk.Toolbar()
209
        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
210
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
211
        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
212
        self.back_button.add_accelerator("clicked", self.accel_group, ord('['),
213
                                         0, 0)
214
        self.back_button.connect("clicked", self._back_clicked_cb)
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
215
        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
216
        self.back_button.show()
217
354 by Daniel Schierbeck
Replaced forward and backward buttons with up and down.
218
        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
219
        self.fwd_button.add_accelerator("clicked", self.accel_group, ord(']'),
220
                                        0, 0)
221
        self.fwd_button.connect("clicked", self._fwd_clicked_cb)
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
222
        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
223
        self.fwd_button.show()
224
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
225
        self.toolbar.show()
226
227
        return self.toolbar
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
228
229
    def construct_bottom(self):
230
        """Construct the bottom half of the window."""
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
231
        from bzrlib.plugins.gtk.revisionview import RevisionView
232
        self.revisionview = RevisionView(None, tags=[], show_children=True, branch=self.branch)
44 by David Allouche
reorganise branch window
233
        (width, height) = self.get_size()
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
234
        self.revisionview.set_size_request(width, int(height / 2.5))
235
        self.revisionview.show()
236
        self.revisionview.set_show_callback(self._show_clicked_cb)
237
        self.revisionview.set_go_callback(self._go_clicked_cb)
238
        return self.revisionview
332 by Daniel Schierbeck
Made tag selection work.
239
240
    def _tag_selected_cb(self, menuitem, revid):
356 by Daniel Schierbeck
Made revision a property on TreeView.
241
        self.treeview.set_revision_id(revid)
341 by Daniel Schierbeck
Merged with trunk.
242
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)
243
    def _treeselection_changed_cb(self, selection, *args):
303 by Daniel Schierbeck
Made basic signaling work.
244
        """callback for when the treeview changes."""
245
        revision = self.treeview.get_revision()
246
        parents  = self.treeview.get_parents()
247
        children = self.treeview.get_children()
248
249
        if revision is not None:
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
250
            back_menu = gtk.Menu()
251
            if len(parents) > 0:
252
                self.back_button.set_sensitive(True)
253
                for parent_id in parents:
254
                    parent = self.branch.repository.get_revision(parent_id)
355 by Daniel Schierbeck
Appended branch nick to parent and child popup menus.
255
                    try:
256
                        str = ' (' + parent.properties['branch-nick'] + ')'
257
                    except KeyError:
258
                        str = ""
259
260
                    item = gtk.MenuItem(parent.message.split("\n")[0] + str)
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
261
                    item.connect('activate', self._set_revision_cb, parent_id)
262
                    back_menu.add(item)
263
                back_menu.show_all()
264
            else:
265
                self.back_button.set_sensitive(False)
266
                back_menu.hide()
267
268
            self.back_button.set_menu(back_menu)
269
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
270
            fwd_menu = gtk.Menu()
271
            if len(children) > 0:
272
                self.fwd_button.set_sensitive(True)
273
                for child_id in children:
274
                    child = self.branch.repository.get_revision(child_id)
355 by Daniel Schierbeck
Appended branch nick to parent and child popup menus.
275
                    try:
276
                        str = ' (' + child.properties['branch-nick'] + ')'
277
                    except KeyError:
278
                        str = ""
279
280
                    item = gtk.MenuItem(child.message.split("\n")[0] + str)
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
281
                    item.connect('activate', self._set_revision_cb, child_id)
282
                    fwd_menu.add(item)
283
                fwd_menu.show_all()
284
            else:
285
                self.fwd_button.set_sensitive(False)
286
                fwd_menu.hide()
287
288
            self.fwd_button.set_menu(fwd_menu)
289
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)
290
            tags = []
291
            if self.branch.supports_tags():
292
                tagdict = self.branch.tags.get_reverse_tag_dict()
293
                if tagdict.has_key(revision.revision_id):
294
                    tags = tagdict[revision.revision_id]
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
295
            self.revisionview.set_revision(revision, tags, children)
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
296
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
297
    def _back_clicked_cb(self, *args):
298
        """Callback for when the back button is clicked."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
299
        self.treeview.back()
300
        
5 by Scott James Remnant
Reverse the meaning of the Back and Forward buttons so Back actually
301
    def _fwd_clicked_cb(self, *args):
302
        """Callback for when the forward button is clicked."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
303
        self.treeview.forward()
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
304
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
305
    def _go_clicked_cb(self, revid):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
306
        """Callback for when the go button for a parent is clicked."""
356 by Daniel Schierbeck
Made revision a property on TreeView.
307
        self.treeview.set_revision_id(revid)
152 by Jelmer Vernooij
Cleanup some more code.
308
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
309
    def _show_clicked_cb(self, revid, parentid):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
310
        """Callback for when the show button for a parent is clicked."""
308 by Daniel Schierbeck
Made Show Diff work again.
311
        self.treeview.show_diff(self.branch, revid, parentid)
13 by Scott James Remnant
Keep the focus on the treeview
312
        self.treeview.grab_focus()
46 by Wouter van Heyst
show diff on row activation, LP# 44591
313
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
314
    def _set_revision_cb(self, w, revision_id):
356 by Daniel Schierbeck
Made revision a property on TreeView.
315
        self.treeview.set_revision_id(revision_id)
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
316
348 by Daniel Schierbeck
Added toggle item for revision number column.
317
    def _col_visibility_changed(self, col, property):
318
        self.treeview.set_property(property + '-column-visible', col.get_active())
351 by Daniel Schierbeck
Added option to hide the toolbar.
319
320
    def _toolbar_visibility_changed(self, col):
321
        if col.get_active():
322
            self.toolbar.show() 
323
        else:
324
            self.toolbar.hide()