/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
450.4.1 by Daniel Schierbeck
Added tag icon to branch history window.
16
from bzrlib.plugins.gtk import icon_path
523.3.2 by Jelmer Vernooij
Share same menu for context menu and main menu.
17
from bzrlib.plugins.gtk.branchview import TreeView, treemodel
365 by Daniel Schierbeck
Fixed locks and made tagging work.
18
from bzrlib.plugins.gtk.tags import AddTagDialog
338 by Daniel Schierbeck
Added Preferences menu item.
19
from bzrlib.plugins.gtk.preferences import PreferencesWindow
523.3.2 by Jelmer Vernooij
Share same menu for context menu and main menu.
20
from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
21
from bzrlib.plugins.gtk.window import Window
511.6.1 by Jelmer Vernooij
Add Branch/Index option if bzr-search is available.
22
23
from bzrlib.config import BranchConfig, GlobalConfig
443 by Szilveszter Farkas (Phanatic)
Trivial fix for #149061 (be able to show the diff for revision 1).
24
from bzrlib.revision import Revision, NULL_REVISION
511.6.1 by Jelmer Vernooij
Add Branch/Index option if bzr-search is available.
25
from bzrlib.trace import mutter
1 by Scott James Remnant
Commit the first version of bzrk.
26
298.2.1 by Daniel Schierbeck
Refactored the GTK window code, creating a single base window class that handles keyboard events.
27
class BranchWindow(Window):
1 by Scott James Remnant
Commit the first version of bzrk.
28
    """Branch window.
29
30
    This object represents and manages a single window containing information
31
    for a particular branch.
32
    """
33
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
34
    def __init__(self, branch, start_revs, maxnum, parent=None):
322 by Jelmer Vernooij
Add docstrings.
35
        """Create a new BranchWindow.
36
37
        :param branch: Branch object for branch to show.
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
38
        :param start_revs: Revision ids of top revisions.
322 by Jelmer Vernooij
Add docstrings.
39
        :param maxnum: Maximum number of revisions to display, 
40
                       None for no limit.
41
        """
42
298.2.1 by Daniel Schierbeck
Refactored the GTK window code, creating a single base window class that handles keyboard events.
43
        Window.__init__(self, parent=parent)
1 by Scott James Remnant
Commit the first version of bzrk.
44
        self.set_border_width(0)
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
45
330.2.4 by Daniel Schierbeck
Made use of compact view optional.
46
        self.branch      = branch
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
47
        self.start_revs  = start_revs
330.2.4 by Daniel Schierbeck
Made use of compact view optional.
48
        self.maxnum      = maxnum
330.2.5 by Daniel Schierbeck
Support persistence of compact view option.
49
        self.config      = GlobalConfig()
50
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
51
        self._sizes      = {} # window and widget sizes
52
330.2.5 by Daniel Schierbeck
Support persistence of compact view option.
53
        if self.config.get_user_option('viz-compact-view') == 'yes':
54
            self.compact_view = True
55
        else:
56
            self.compact_view = False
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
57
58
        self.set_title(branch.nick + " - revision history")
1 by Scott James Remnant
Commit the first version of bzrk.
59
60
        # Use three-quarters of the screen by default
61
        screen = self.get_screen()
4 by Scott James Remnant
Use the size of the first monitor rather than the entire screen
62
        monitor = screen.get_monitor_geometry(0)
63
        width = int(monitor.width * 0.75)
64
        height = int(monitor.height * 0.75)
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
65
        # user-configured window size
531.7.10 by Scott Scriven
Simplified size-loading code. No longer saves identical config every time vis runs.
66
        size = self._load_size('viz-window-size')
67
        if size:
68
            width, height = size
1 by Scott James Remnant
Commit the first version of bzrk.
69
        self.set_default_size(width, height)
531.7.8 by Scott Scriven
Made viz window shrinkable.
70
        self.set_size_request(width/3, height/3)
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
71
        self.connect("size-allocate", self._on_size_allocate, 'viz-window-size')
1 by Scott James Remnant
Commit the first version of bzrk.
72
73
        # FIXME AndyFitz!
74
        icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
75
        self.set_icon(icon)
76
384 by Daniel Schierbeck
Added accelerator for Next Revision action.
77
        gtk.accel_map_add_entry("<viz>/Go/Next Revision", gtk.keysyms.Up, gtk.gdk.MOD1_MASK)
383 by Daniel Schierbeck
Switched to using symbolic names for keyvals.
78
        gtk.accel_map_add_entry("<viz>/Go/Previous Revision", gtk.keysyms.Down, gtk.gdk.MOD1_MASK)
499.1.1 by Russ Brown
Added Refresh menu option with keyboard shortcut to viz
79
        gtk.accel_map_add_entry("<viz>/View/Refresh", gtk.keysyms.F5, 0)
382 by Daniel Schierbeck
Made accelerator for Previous Revision work.
80
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
81
        self.accel_group = gtk.AccelGroup()
82
        self.add_accel_group(self.accel_group)
83
388 by Daniel Schierbeck
Switched to using the Previous/Next Revision actions to create tool buttons.
84
        gtk.Action.set_tool_item_type(gtk.MenuToolButton)
85
385 by Daniel Schierbeck
Created a single action for Previous Revision.
86
        self.prev_rev_action = gtk.Action("prev-rev", "_Previous Revision", "Go to the previous revision", gtk.STOCK_GO_DOWN)
87
        self.prev_rev_action.set_accel_path("<viz>/Go/Previous Revision")
88
        self.prev_rev_action.set_accel_group(self.accel_group)
89
        self.prev_rev_action.connect("activate", self._back_clicked_cb)
90
        self.prev_rev_action.connect_accelerator()
91
386 by Daniel Schierbeck
Created a single action for Next Revision.
92
        self.next_rev_action = gtk.Action("next-rev", "_Next Revision", "Go to the next revision", gtk.STOCK_GO_UP)
93
        self.next_rev_action.set_accel_path("<viz>/Go/Next Revision")
94
        self.next_rev_action.set_accel_group(self.accel_group)
95
        self.next_rev_action.connect("activate", self._fwd_clicked_cb)
96
        self.next_rev_action.connect_accelerator()
97
499.1.1 by Russ Brown
Added Refresh menu option with keyboard shortcut to viz
98
        self.refresh_action = gtk.Action("refresh", "_Refresh", "Refresh view", gtk.STOCK_REFRESH)
99
        self.refresh_action.set_accel_path("<viz>/View/Refresh")
100
        self.refresh_action.set_accel_group(self.accel_group)
101
        self.refresh_action.connect("activate", self._refresh_clicked)
102
        self.refresh_action.connect_accelerator()
103
1 by Scott James Remnant
Commit the first version of bzrk.
104
        self.construct()
105
369 by Daniel Schierbeck
Fixed bug with compact view toggling.
106
    def set_revision(self, revid):
107
        self.treeview.set_revision_id(revid)
330.2.4 by Daniel Schierbeck
Made use of compact view optional.
108
1 by Scott James Remnant
Commit the first version of bzrk.
109
    def construct(self):
110
        """Construct the window contents."""
331 by Daniel Schierbeck
Added basic menu bar.
111
        vbox = gtk.VBox(spacing=0)
44 by David Allouche
reorganise branch window
112
        self.add(vbox)
113
375 by Daniel Schierbeck
Fixed crash when toggling compact view.
114
        self.paned = gtk.VPaned()
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
115
        self.paned.pack1(self.construct_top(), resize=False, shrink=True)
116
        self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
375 by Daniel Schierbeck
Fixed crash when toggling compact view.
117
        self.paned.show()
358 by Daniel Schierbeck
Generalized the hiding/showing code.
118
531.7.2 by Scott Scriven
Made 'vis' save/load visibility of its toolbar.
119
        nav = self.construct_navigation()
120
        menubar = self.construct_menubar()
121
        vbox.pack_start(menubar, expand=False, fill=True)
122
        vbox.pack_start(nav, expand=False, fill=True)
123
369 by Daniel Schierbeck
Fixed bug with compact view toggling.
124
        vbox.pack_start(self.paned, expand=True, fill=True)
125
        vbox.set_focus_child(self.paned)
44 by David Allouche
reorganise branch window
126
127
        vbox.show()
331 by Daniel Schierbeck
Added basic menu bar.
128
129
    def construct_menubar(self):
130
        menubar = gtk.MenuBar()
131
132
        file_menu = gtk.Menu()
334 by Daniel Schierbeck
Added icons to menus.
133
        file_menuitem = gtk.MenuItem("_File")
331 by Daniel Schierbeck
Added basic menu bar.
134
        file_menuitem.set_submenu(file_menu)
135
362 by Daniel Schierbeck
Added accel group to File -> Close menu item.
136
        file_menu_close = gtk.ImageMenuItem(gtk.STOCK_CLOSE, self.accel_group)
331 by Daniel Schierbeck
Added basic menu bar.
137
        file_menu_close.connect('activate', lambda x: self.destroy())
138
        
363 by Daniel Schierbeck
Added File -> Quit menu item.
139
        file_menu_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accel_group)
140
        file_menu_quit.connect('activate', lambda x: gtk.main_quit())
141
        
408 by Daniel Schierbeck
Made the close menu item actually appear when the viz is opened from another window.
142
        if self._parent is not None:
406 by Daniel Schierbeck
Made the viz show the close menu item only if opened from another window.
143
            file_menu.add(file_menu_close)
363 by Daniel Schierbeck
Added File -> Quit menu item.
144
        file_menu.add(file_menu_quit)
331 by Daniel Schierbeck
Added basic menu bar.
145
338 by Daniel Schierbeck
Added Preferences menu item.
146
        edit_menu = gtk.Menu()
147
        edit_menuitem = gtk.MenuItem("_Edit")
148
        edit_menuitem.set_submenu(edit_menu)
149
361 by Daniel Schierbeck
Added branch settings menu item.
150
        edit_menu_branchopts = gtk.MenuItem("Branch Settings")
151
        edit_menu_branchopts.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
152
407 by Daniel Schierbeck
Renamed Preferences menu item into Global Settings.
153
        edit_menu_globopts = gtk.MenuItem("Global Settings")
154
        edit_menu_globopts.connect('activate', lambda x: PreferencesWindow().show())
338 by Daniel Schierbeck
Added Preferences menu item.
155
361 by Daniel Schierbeck
Added branch settings menu item.
156
        edit_menu.add(edit_menu_branchopts)
407 by Daniel Schierbeck
Renamed Preferences menu item into Global Settings.
157
        edit_menu.add(edit_menu_globopts)
338 by Daniel Schierbeck
Added Preferences menu item.
158
348 by Daniel Schierbeck
Added toggle item for revision number column.
159
        view_menu = gtk.Menu()
160
        view_menuitem = gtk.MenuItem("_View")
161
        view_menuitem.set_submenu(view_menu)
162
499.1.1 by Russ Brown
Added Refresh menu option with keyboard shortcut to viz
163
        view_menu_refresh = self.refresh_action.create_menu_item()
164
        view_menu_refresh.connect('activate', self._refresh_clicked)
165
166
        view_menu.add(view_menu_refresh)
167
        view_menu.add(gtk.SeparatorMenuItem())
168
351 by Daniel Schierbeck
Added option to hide the toolbar.
169
        view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
170
        view_menu_toolbar.set_active(True)
531.7.2 by Scott Scriven
Made 'vis' save/load visibility of its toolbar.
171
        if self.config.get_user_option('viz-toolbar-visible') == 'False':
172
            view_menu_toolbar.set_active(False)
173
            self.toolbar.hide()
351 by Daniel Schierbeck
Added option to hide the toolbar.
174
        view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
175
370 by Daniel Schierbeck
Moved compact graph toggle to the menubar.
176
        view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
177
        view_menu_compact.set_active(self.compact_view)
178
        view_menu_compact.connect('activate', self._brokenlines_toggled_cb)
179
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
180
        view_menu_diffs = gtk.CheckMenuItem("Show Diffs")
531.7.12 by Scott Scriven
Made diff panel default to off.
181
        view_menu_diffs.set_active(False)
182
        if self.config.get_user_option('viz-show-diffs') == 'True':
183
            view_menu_diffs.set_active(True)
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
184
        view_menu_diffs.connect('toggled', self._diff_visibility_changed)
185
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
186
        view_menu_wide_diffs = gtk.CheckMenuItem("Wide Diffs")
187
        view_menu_wide_diffs.set_active(False)
188
        if self.config.get_user_option('viz-wide-diffs') == 'True':
189
            view_menu_wide_diffs.set_active(True)
190
        view_menu_wide_diffs.connect('toggled', self._diff_placement_changed)
191
351 by Daniel Schierbeck
Added option to hide the toolbar.
192
        view_menu.add(view_menu_toolbar)
370 by Daniel Schierbeck
Moved compact graph toggle to the menubar.
193
        view_menu.add(view_menu_compact)
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
194
        view_menu.add(view_menu_diffs)
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
195
        view_menu.add(view_menu_wide_diffs)
351 by Daniel Schierbeck
Added option to hide the toolbar.
196
        view_menu.add(gtk.SeparatorMenuItem())
358 by Daniel Schierbeck
Generalized the hiding/showing code.
197
452.4.2 by Jelmer Vernooij
Hide revision number column if more than one branch was specified.
198
        self.mnu_show_revno_column = gtk.CheckMenuItem("Show Revision _Number Column")
199
        self.mnu_show_date_column = gtk.CheckMenuItem("Show _Date Column")
200
201
        # Revision numbers are pointless if there are multiple branches
202
        if len(self.start_revs) > 1:
203
            self.mnu_show_revno_column.set_sensitive(False)
204
            self.treeview.set_property('revno-column-visible', False)
205
206
        for (col, name) in [(self.mnu_show_revno_column, "revno"), 
207
                            (self.mnu_show_date_column, "date")]:
358 by Daniel Schierbeck
Generalized the hiding/showing code.
208
            col.set_active(self.treeview.get_property(name + "-column-visible"))
209
            col.connect('toggled', self._col_visibility_changed, name)
210
            view_menu.add(col)
348 by Daniel Schierbeck
Added toggle item for revision number column.
211
331 by Daniel Schierbeck
Added basic menu bar.
212
        go_menu = gtk.Menu()
382 by Daniel Schierbeck
Made accelerator for Previous Revision work.
213
        go_menu.set_accel_group(self.accel_group)
334 by Daniel Schierbeck
Added icons to menus.
214
        go_menuitem = gtk.MenuItem("_Go")
331 by Daniel Schierbeck
Added basic menu bar.
215
        go_menuitem.set_submenu(go_menu)
216
        
390 by Daniel Schierbeck
Made the Previous/Next Revision menu items local variables.
217
        go_menu_next = self.next_rev_action.create_menu_item()
218
        go_menu_prev = self.prev_rev_action.create_menu_item()
334 by Daniel Schierbeck
Added icons to menus.
219
450.4.1 by Daniel Schierbeck
Added tag icon to branch history window.
220
        tag_image = gtk.Image()
221
        tag_image.set_from_file(icon_path("tag-16.png"))
222
        self.go_menu_tags = gtk.ImageMenuItem("_Tags")
223
        self.go_menu_tags.set_image(tag_image)
423.7.5 by Daniel Schierbeck
Made the revision history window update the Go->Tags menu when a tag is added.
224
        self._update_tags()
399 by Daniel Schierbeck
Made tags menu insensitive when there are no tags to display.
225
390 by Daniel Schierbeck
Made the Previous/Next Revision menu items local variables.
226
        go_menu.add(go_menu_next)
227
        go_menu.add(go_menu_prev)
334 by Daniel Schierbeck
Added icons to menus.
228
        go_menu.add(gtk.SeparatorMenuItem())
423.7.5 by Daniel Schierbeck
Made the revision history window update the Go->Tags menu when a tag is added.
229
        go_menu.add(self.go_menu_tags)
334 by Daniel Schierbeck
Added icons to menus.
230
523.3.2 by Jelmer Vernooij
Share same menu for context menu and main menu.
231
        self.revision_menu = RevisionMenu(self.branch.repository, [], self.branch, parent=self)
335 by Daniel Schierbeck
Added Revision menu.
232
        revision_menuitem = gtk.MenuItem("_Revision")
523.3.2 by Jelmer Vernooij
Share same menu for context menu and main menu.
233
        revision_menuitem.set_submenu(self.revision_menu)
335 by Daniel Schierbeck
Added Revision menu.
234
334 by Daniel Schierbeck
Added icons to menus.
235
        branch_menu = gtk.Menu()
236
        branch_menuitem = gtk.MenuItem("_Branch")
237
        branch_menuitem.set_submenu(branch_menu)
238
336 by Daniel Schierbeck
Changed wording to comply with HIG guidelines.
239
        branch_menu.add(gtk.MenuItem("Pu_ll Revisions"))
240
        branch_menu.add(gtk.MenuItem("Pu_sh Revisions"))
371.1.1 by Daniel Schierbeck
Added About dialog to the viz.
241
511.6.1 by Jelmer Vernooij
Add Branch/Index option if bzr-search is available.
242
        try:
243
            from bzrlib.plugins import search
244
        except ImportError:
245
            mutter("Didn't find search plugin")
246
        else:
526 by Jelmer Vernooij
Switch to found revision when clicking ok in search window.
247
            branch_menu.add(gtk.SeparatorMenuItem())
248
511.6.1 by Jelmer Vernooij
Add Branch/Index option if bzr-search is available.
249
            branch_index_menuitem = gtk.MenuItem("_Index")
250
            branch_index_menuitem.connect('activate', self._branch_index_cb)
251
            branch_menu.add(branch_index_menuitem)
252
524 by Jelmer Vernooij
Add search dialog.
253
            branch_search_menuitem = gtk.MenuItem("_Search")
254
            branch_search_menuitem.connect('activate', self._branch_search_cb)
255
            branch_menu.add(branch_search_menuitem)
256
423.9.1 by Daniel Schierbeck
Added Help->About menu item to the viz.
257
        help_menu = gtk.Menu()
258
        help_menuitem = gtk.MenuItem("_Help")
259
        help_menuitem.set_submenu(help_menu)
260
261
        help_about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT, self.accel_group)
262
        help_about_menuitem.connect('activate', self._about_dialog_cb)
263
264
        help_menu.add(help_about_menuitem)
265
331 by Daniel Schierbeck
Added basic menu bar.
266
        menubar.add(file_menuitem)
338 by Daniel Schierbeck
Added Preferences menu item.
267
        menubar.add(edit_menuitem)
348 by Daniel Schierbeck
Added toggle item for revision number column.
268
        menubar.add(view_menuitem)
331 by Daniel Schierbeck
Added basic menu bar.
269
        menubar.add(go_menuitem)
335 by Daniel Schierbeck
Added Revision menu.
270
        menubar.add(revision_menuitem)
331 by Daniel Schierbeck
Added basic menu bar.
271
        menubar.add(branch_menuitem)
423.9.1 by Daniel Schierbeck
Added Help->About menu item to the viz.
272
        menubar.add(help_menuitem)
331 by Daniel Schierbeck
Added basic menu bar.
273
        menubar.show_all()
274
275
        return menubar
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
276
277
    def construct_top(self):
278
        """Construct the top-half of the window."""
329 by Jelmer Vernooij
Make broken_line_length setting from higher up.
279
        # FIXME: Make broken_line_length configurable
330.2.5 by Daniel Schierbeck
Support persistence of compact view option.
280
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
281
        self.treeview = TreeView(self.branch, self.start_revs, self.maxnum, self.compact_view)
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
282
373 by Daniel Schierbeck
Made column display options persisted.
283
        self.treeview.connect('revision-selected',
303 by Daniel Schierbeck
Made basic signaling work.
284
                self._treeselection_changed_cb)
423.1.17 by Gary van der Merwe
Reuse the viz treeview in the revision browser.
285
        self.treeview.connect('revision-activated',
286
                self._tree_revision_activated)
303 by Daniel Schierbeck
Made basic signaling work.
287
423.7.5 by Daniel Schierbeck
Made the revision history window update the Go->Tags menu when a tag is added.
288
        self.treeview.connect('tag-added', lambda w, t, r: self._update_tags())
289
373 by Daniel Schierbeck
Made column display options persisted.
290
        for col in ["revno", "date"]:
291
            option = self.config.get_user_option(col + '-column-visible')
292
            if option is not None:
293
                self.treeview.set_property(col + '-column-visible', option == 'True')
464.1.1 by Adrian Wilkins
Fixed column visibility properties not loading
294
            else:
295
                self.treeview.set_property(col + '-column-visible', False)
373 by Daniel Schierbeck
Made column display options persisted.
296
1 by Scott James Remnant
Commit the first version of bzrk.
297
        self.treeview.show()
298
375 by Daniel Schierbeck
Fixed crash when toggling compact view.
299
        align = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
300
        align.set_padding(5, 0, 0, 0)
301
        align.add(self.treeview)
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
302
        # user-configured size
531.7.10 by Scott Scriven
Simplified size-loading code. No longer saves identical config every time vis runs.
303
        size = self._load_size('viz-graph-size')
304
        if size:
305
            width, height = size
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
306
            align.set_size_request(width, height)
307
        else:
308
            (width, height) = self.get_size()
309
            align.set_size_request(width, int(height / 2.5))
310
        align.connect('size-allocate', self._on_size_allocate, 'viz-graph-size')
375 by Daniel Schierbeck
Fixed crash when toggling compact view.
311
        align.show()
312
313
        return align
44 by David Allouche
reorganise branch window
314
315
    def construct_navigation(self):
316
        """Construct the navigation buttons."""
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
317
        self.toolbar = gtk.Toolbar()
318
        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
319
388 by Daniel Schierbeck
Switched to using the Previous/Next Revision actions to create tool buttons.
320
        self.prev_button = self.prev_rev_action.create_tool_item()
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
321
        self.toolbar.insert(self.prev_button, -1)
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
322
388 by Daniel Schierbeck
Switched to using the Previous/Next Revision actions to create tool buttons.
323
        self.next_button = self.next_rev_action.create_tool_item()
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
324
        self.toolbar.insert(self.next_button, -1)
330.2.4 by Daniel Schierbeck
Made use of compact view optional.
325
401.1.2 by Daniel Schierbeck
Allowed the treeview to be refreshed.
326
        self.toolbar.insert(gtk.SeparatorToolItem(), -1)
327
328
        refresh_button = gtk.ToolButton(gtk.STOCK_REFRESH)
404 by Daniel Schierbeck
Made the refresh use proper locking.
329
        refresh_button.connect('clicked', self._refresh_clicked)
401.1.2 by Daniel Schierbeck
Allowed the treeview to be refreshed.
330
        self.toolbar.insert(refresh_button, -1)
331
330.2.4 by Daniel Schierbeck
Made use of compact view optional.
332
        self.toolbar.show_all()
325 by Daniel Schierbeck
Switched to using a real toolbar for the viz navigation.
333
334
        return self.toolbar
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
335
336
    def construct_bottom(self):
337
        """Construct the bottom half of the window."""
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
338
        if self.config.get_user_option('viz-wide-diffs') == 'True':
339
            self.diff_paned = gtk.VPaned()
340
        else:
341
            self.diff_paned = gtk.HPaned()
531.7.1 by Scott Scriven
Added a diff panel to otherwise-blank area in 'bzr vis'.
342
        (width, height) = self.get_size()
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
343
        self.diff_paned.set_size_request(20, 20) # shrinkable
531.7.1 by Scott Scriven
Added a diff panel to otherwise-blank area in 'bzr vis'.
344
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
345
        from bzrlib.plugins.gtk.revisionview import RevisionView
412.1.2 by Daniel Schierbeck
Moved retrieval of tags into the revisionview itself.
346
        self.revisionview = RevisionView(branch=self.branch)
531.7.1 by Scott Scriven
Added a diff panel to otherwise-blank area in 'bzr vis'.
347
        self.revisionview.set_size_request(width/3, int(height / 2.5))
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
348
        # user-configured size
531.7.10 by Scott Scriven
Simplified size-loading code. No longer saves identical config every time vis runs.
349
        size = self._load_size('viz-revisionview-size')
350
        if size:
351
            width, height = size
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
352
            self.revisionview.set_size_request(width, height)
353
        self.revisionview.connect('size-allocate', self._on_size_allocate, 'viz-revisionview-size')
330.3.1 by Daniel Schierbeck
Renamed logview 'revisionview'.
354
        self.revisionview.show()
355
        self.revisionview.set_show_callback(self._show_clicked_cb)
412.1.9 by Daniel Schierbeck
Removed the use of RevisionView.set_go_callback().
356
        self.revisionview.connect('notify::revision', self._go_clicked_cb)
423.7.4 by Daniel Schierbeck
Made revisionview and branchview update when a tag is added.
357
        self.treeview.connect('tag-added', lambda w, t, r: self.revisionview.update_tags())
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
358
        self.diff_paned.pack1(self.revisionview)
531.7.1 by Scott Scriven
Added a diff panel to otherwise-blank area in 'bzr vis'.
359
360
        from bzrlib.plugins.gtk.diff import DiffWidget
361
        self.diff = DiffWidget()
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
362
        self.diff_paned.pack2(self.diff)
531.7.1 by Scott Scriven
Added a diff panel to otherwise-blank area in 'bzr vis'.
363
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
364
        self.diff_paned.show_all()
531.7.12 by Scott Scriven
Made diff panel default to off.
365
        if self.config.get_user_option('viz-show-diffs') != 'True':
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
366
            self.diff.hide()
367
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
368
        return self.diff_paned
332 by Daniel Schierbeck
Made tag selection work.
369
370
    def _tag_selected_cb(self, menuitem, revid):
356 by Daniel Schierbeck
Made revision a property on TreeView.
371
        self.treeview.set_revision_id(revid)
341 by Daniel Schierbeck
Merged with trunk.
372
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)
373
    def _treeselection_changed_cb(self, selection, *args):
303 by Daniel Schierbeck
Made basic signaling work.
374
        """callback for when the treeview changes."""
375
        revision = self.treeview.get_revision()
376
        parents  = self.treeview.get_parents()
377
        children = self.treeview.get_children()
378
523.3.2 by Jelmer Vernooij
Share same menu for context menu and main menu.
379
        self.revision_menu.set_revision_ids([revision.revision_id])
380
464.2.1 by Adrian Wilkins
Detect the reserved null: revision in appropriate places.
381
        if revision and revision != NULL_REVISION:
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
382
            prev_menu = gtk.Menu()
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
383
            if len(parents) > 0:
385 by Daniel Schierbeck
Created a single action for Previous Revision.
384
                self.prev_rev_action.set_sensitive(True)
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
385
                for parent_id in parents:
464.2.1 by Adrian Wilkins
Detect the reserved null: revision in appropriate places.
386
                    if parent_id and parent_id != NULL_REVISION:
387
                        parent = self.branch.repository.get_revision(parent_id)
388
                        try:
389
                            str = ' (' + parent.properties['branch-nick'] + ')'
390
                        except KeyError:
391
                            str = ""
355 by Daniel Schierbeck
Appended branch nick to parent and child popup menus.
392
464.2.1 by Adrian Wilkins
Detect the reserved null: revision in appropriate places.
393
                        item = gtk.MenuItem(parent.message.split("\n")[0] + str)
394
                        item.connect('activate', self._set_revision_cb, parent_id)
395
                        prev_menu.add(item)
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
396
                prev_menu.show_all()
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
397
            else:
385 by Daniel Schierbeck
Created a single action for Previous Revision.
398
                self.prev_rev_action.set_sensitive(False)
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
399
                prev_menu.hide()
400
401
            self.prev_button.set_menu(prev_menu)
402
403
            next_menu = gtk.Menu()
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
404
            if len(children) > 0:
386 by Daniel Schierbeck
Created a single action for Next Revision.
405
                self.next_rev_action.set_sensitive(True)
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
406
                for child_id in children:
407
                    child = self.branch.repository.get_revision(child_id)
355 by Daniel Schierbeck
Appended branch nick to parent and child popup menus.
408
                    try:
409
                        str = ' (' + child.properties['branch-nick'] + ')'
410
                    except KeyError:
411
                        str = ""
412
413
                    item = gtk.MenuItem(child.message.split("\n")[0] + str)
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
414
                    item.connect('activate', self._set_revision_cb, child_id)
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
415
                    next_menu.add(item)
416
                next_menu.show_all()
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
417
            else:
386 by Daniel Schierbeck
Created a single action for Next Revision.
418
                self.next_rev_action.set_sensitive(False)
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
419
                next_menu.hide()
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
420
376 by Daniel Schierbeck
Changed 'back' into 'prev' and 'fwd' into 'next'.
421
            self.next_button.set_menu(next_menu)
352.1.2 by Daniel Schierbeck
Added dropdown menu to Forward button.
422
412.1.13 by Daniel Schierbeck
Re-added support for displaying the children of a revision.
423
            self.revisionview.set_revision(revision)
424
            self.revisionview.set_children(children)
531.7.1 by Scott Scriven
Added a diff panel to otherwise-blank area in 'bzr vis'.
425
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
426
            self.update_diff_panel(revision, parents)
531.7.1 by Scott Scriven
Added a diff panel to otherwise-blank area in 'bzr vis'.
427
423.1.17 by Gary van der Merwe
Reuse the viz treeview in the revision browser.
428
    def _tree_revision_activated(self, widget, path, col):
429
        # TODO: more than one parent
430
        """Callback for when a treeview row gets activated."""
431
        revision = self.treeview.get_revision()
432
        parents  = self.treeview.get_parents()
433
434
        if len(parents) == 0:
435
            parent_id = None
436
        else:
437
            parent_id = parents[0]
438
439
        self.show_diff(revision.revision_id, parent_id)
440
        self.treeview.grab_focus()
463.3.1 by Javier Derderian
Fixed menu entry 'View Changes'. Bug #215350
441
        
3 by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show
442
    def _back_clicked_cb(self, *args):
443
        """Callback for when the back button is clicked."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
444
        self.treeview.back()
445
        
5 by Scott James Remnant
Reverse the meaning of the Back and Forward buttons so Back actually
446
    def _fwd_clicked_cb(self, *args):
447
        """Callback for when the forward button is clicked."""
304 by Daniel Schierbeck
Made forward/back buttons work again.
448
        self.treeview.forward()
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
449
412.1.9 by Daniel Schierbeck
Removed the use of RevisionView.set_go_callback().
450
    def _go_clicked_cb(self, w, p):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
451
        """Callback for when the go button for a parent is clicked."""
412.1.9 by Daniel Schierbeck
Removed the use of RevisionView.set_go_callback().
452
        if self.revisionview.get_revision() is not None:
453
            self.treeview.set_revision(self.revisionview.get_revision())
152 by Jelmer Vernooij
Cleanup some more code.
454
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
455
    def _show_clicked_cb(self, revid, parentid):
7 by Scott James Remnant
Put some information about the highlighted revision in the bottom pane,
456
        """Callback for when the show button for a parent is clicked."""
423.1.17 by Gary van der Merwe
Reuse the viz treeview in the revision browser.
457
        self.show_diff(revid, parentid)
13 by Scott James Remnant
Keep the focus on the treeview
458
        self.treeview.grab_focus()
46 by Wouter van Heyst
show diff on row activation, LP# 44591
459
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
460
    def _set_revision_cb(self, w, revision_id):
356 by Daniel Schierbeck
Made revision a property on TreeView.
461
        self.treeview.set_revision_id(revision_id)
352.1.1 by Daniel Schierbeck
Added dropdown menu to Back button.
462
330.2.4 by Daniel Schierbeck
Made use of compact view optional.
463
    def _brokenlines_toggled_cb(self, button):
330.2.5 by Daniel Schierbeck
Support persistence of compact view option.
464
        self.compact_view = button.get_active()
465
466
        if self.compact_view:
467
            option = 'yes'
330.2.4 by Daniel Schierbeck
Made use of compact view optional.
468
        else:
330.2.5 by Daniel Schierbeck
Support persistence of compact view option.
469
            option = 'no'
470
471
        self.config.set_user_option('viz-compact-view', option)
401.1.3 by Daniel Schierbeck
Made the compact view toggling cleaner.
472
        self.treeview.set_property('compact', self.compact_view)
473
        self.treeview.refresh()
368 by Daniel Schierbeck
Merged with mainline.
474
511.6.1 by Jelmer Vernooij
Add Branch/Index option if bzr-search is available.
475
    def _branch_index_cb(self, w):
476
        from bzrlib.plugins.search import index as _mod_index
477
        _mod_index.index_url(self.branch.base)
478
524 by Jelmer Vernooij
Add search dialog.
479
    def _branch_search_cb(self, w):
533.11.1 by Jelmer Vernooij
Ask user whether to index if there is no index present yet.
480
        from bzrlib.plugins.search import index as _mod_index
524 by Jelmer Vernooij
Add search dialog.
481
        from bzrlib.plugins.gtk.search import SearchDialog
533.11.1 by Jelmer Vernooij
Ask user whether to index if there is no index present yet.
482
        from bzrlib.plugins.search import errors as search_errors
483
484
        try:
485
            index = _mod_index.open_index_url(self.branch.base)
486
        except search_errors.NoSearchIndex:
487
            dialog = gtk.MessageDialog(self, type=gtk.MESSAGE_QUESTION, 
488
                buttons=gtk.BUTTONS_OK_CANCEL, 
489
                message_format="This branch has not been indexed yet. "
490
                               "Index now?")
491
            if dialog.run() == gtk.RESPONSE_OK:
553 by Jelmer Vernooij
Merge asking the user whether to create an index.
492
                dialog.destroy()
533.11.1 by Jelmer Vernooij
Ask user whether to index if there is no index present yet.
493
                index = _mod_index.index_url(self.branch.base)
494
            else:
553 by Jelmer Vernooij
Merge asking the user whether to create an index.
495
                dialog.destroy()
533.11.1 by Jelmer Vernooij
Ask user whether to index if there is no index present yet.
496
                return
497
498
        dialog = SearchDialog(index)
526 by Jelmer Vernooij
Switch to found revision when clicking ok in search window.
499
        
500
        if dialog.run() == gtk.RESPONSE_OK:
501
            self.set_revision(dialog.get_revision())
502
503
        dialog.destroy()
524 by Jelmer Vernooij
Add search dialog.
504
423.9.1 by Daniel Schierbeck
Added Help->About menu item to the viz.
505
    def _about_dialog_cb(self, w):
506
        from bzrlib.plugins.gtk.about import AboutDialog
507
508
        AboutDialog().run()
509
348 by Daniel Schierbeck
Added toggle item for revision number column.
510
    def _col_visibility_changed(self, col, property):
373 by Daniel Schierbeck
Made column display options persisted.
511
        self.config.set_user_option(property + '-column-visible', col.get_active())
348 by Daniel Schierbeck
Added toggle item for revision number column.
512
        self.treeview.set_property(property + '-column-visible', col.get_active())
351 by Daniel Schierbeck
Added option to hide the toolbar.
513
514
    def _toolbar_visibility_changed(self, col):
515
        if col.get_active():
531.7.2 by Scott Scriven
Made 'vis' save/load visibility of its toolbar.
516
            self.toolbar.show()
351 by Daniel Schierbeck
Added option to hide the toolbar.
517
        else:
518
            self.toolbar.hide()
531.7.2 by Scott Scriven
Made 'vis' save/load visibility of its toolbar.
519
        self.config.set_user_option('viz-toolbar-visible', col.get_active())
371.1.1 by Daniel Schierbeck
Added About dialog to the viz.
520
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
521
    def _make_diff_nonzero_size(self):
522
        """make sure the diff isn't zero-width or zero-height"""
523
        alloc = self.diff.get_allocation()
524
        if (alloc.width < 10) or (alloc.height < 10):
525
            width, height = self.get_size()
526
            self.revisionview.set_size_request(width/3, int(height / 2.5))
527
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
528
    def _diff_visibility_changed(self, col):
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
529
        """Hide or show the diff panel."""
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
530
        if col.get_active():
531
            self.diff.show()
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
532
            self._make_diff_nonzero_size()
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
533
        else:
534
            self.diff.hide()
535
        self.config.set_user_option('viz-show-diffs', str(col.get_active()))
536
        self.update_diff_panel()
537
531.7.14 by Scott Scriven
Made diff placement configurable (bottom-right, or bottom full-width).
538
    def _diff_placement_changed(self, col):
539
        """Toggle the diff panel's position."""
540
        self.config.set_user_option('viz-wide-diffs', str(col.get_active()))
541
542
        old = self.paned.get_child2()
543
        self.paned.remove(old)
544
        self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
545
        self._make_diff_nonzero_size()
546
547
        self.treeview.emit('revision-selected')
548
371.1.1 by Daniel Schierbeck
Added About dialog to the viz.
549
    def _show_about_cb(self, w):
550
        dialog = AboutDialog()
551
        dialog.connect('response', lambda d,r: d.destroy())
552
        dialog.run()
404 by Daniel Schierbeck
Made the refresh use proper locking.
553
554
    def _refresh_clicked(self, w):
423.1.13 by Gary van der Merwe
Move viz loading msg from branchwin to treeview.
555
        self.treeview.refresh()
423.7.5 by Daniel Schierbeck
Made the revision history window update the Go->Tags menu when a tag is added.
556
557
    def _update_tags(self):
558
        menu = gtk.Menu()
559
560
        if self.branch.supports_tags():
561
            tags = self.branch.tags.get_tag_dict().items()
562
            tags.sort()
563
            tags.reverse()
564
            for tag, revid in tags:
450.4.1 by Daniel Schierbeck
Added tag icon to branch history window.
565
                tag_image = gtk.Image()
566
                tag_image.set_from_file(icon_path('tag-16.png'))
567
                tag_item = gtk.ImageMenuItem(tag.replace('_', '__'))
568
                tag_item.set_image(tag_image)
423.7.5 by Daniel Schierbeck
Made the revision history window update the Go->Tags menu when a tag is added.
569
                tag_item.connect('activate', self._tag_selected_cb, revid)
570
                menu.add(tag_item)
571
            self.go_menu_tags.set_submenu(menu)
572
573
            self.go_menu_tags.set_sensitive(len(tags) != 0)
574
        else:
575
            self.go_menu_tags.set_sensitive(False)
576
577
        self.go_menu_tags.show_all()
578
531.7.10 by Scott Scriven
Simplified size-loading code. No longer saves identical config every time vis runs.
579
    def _load_size(self, name):
580
        """Read and parse 'name' from self.config.
581
        The value is a string, formatted as WIDTHxHEIGHT
582
        Returns None, or (width, height)
583
        """
584
        size = self.config.get_user_option(name)
585
        if size:
586
            width, height = [int(num) for num in size.split('x')]
587
            # avoid writing config every time we start
588
            self._sizes[name] = (width, height)
589
            return width, height
590
        return None
591
531.7.9 by Scott Scriven
Made vis remember window and panel sizes.
592
    def _on_size_allocate(self, widget, allocation, name):
593
        """When window has been resized, save the new size."""
594
        width, height = 0, 0
595
        if name in self._sizes:
596
            width, height = self._sizes[name]
597
598
        size_changed = (width != allocation.width) or \
599
                (height != allocation.height)
600
601
        if size_changed:
602
            width, height = allocation.width, allocation.height
603
            self._sizes[name] = (width, height)
604
            value = '%sx%s' % (width, height)
605
            self.config.set_user_option(name, value)
606
423.1.17 by Gary van der Merwe
Reuse the viz treeview in the revision browser.
607
    def show_diff(self, revid=None, parentid=None):
608
        """Open a new window to show a diff between the given revisions."""
609
        from bzrlib.plugins.gtk.diff import DiffWindow
610
        window = DiffWindow(parent=self)
611
612
        if parentid is None:
613
            parentid = NULL_REVISION
614
615
        rev_tree    = self.branch.repository.revision_tree(revid)
616
        parent_tree = self.branch.repository.revision_tree(parentid)
617
618
        description = revid + " - " + self.branch.nick
619
        window.set_diff(description, rev_tree, parent_tree)
620
        window.show()
621
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
622
    def update_diff_panel(self, revision=None, parents=None):
623
        """Show the current revision in the diff panel."""
531.7.12 by Scott Scriven
Made diff panel default to off.
624
        if self.config.get_user_option('viz-show-diffs') != 'True':
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
625
            return
626
627
        if not revision: # default to selected row
628
            revision = self.treeview.get_revision()
629
        if (not revision) or (revision == NULL_REVISION):
630
            return
631
632
        if not parents: # default to selected row's parents
633
            parents  = self.treeview.get_parents()
634
        if len(parents) == 0:
635
            parent_id = None
636
        else:
637
            parent_id = parents[0]
638
639
        rev_tree    = self.branch.repository.revision_tree(revision.revision_id)
640
        parent_tree = self.branch.repository.revision_tree(parent_id)
531.7.5 by Scott Scriven
Fixed DiffWidget so more than one call to set_diff() will work.
641
531.7.3 by Scott Scriven
Added an option to show/hide the diff panel.
642
        self.diff.set_diff(rev_tree, parent_tree)
643
        self.diff.show_all()