/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: Jelmer Vernooij
  • Date: 2011-02-18 13:01:03 UTC
  • Revision ID: jelmer@samba.org-20110218130103-fiyk203auk28thpn
Remove some unused imports, fix some formatting.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Branch window.
 
2
 
 
3
This module contains the code to manage the branch information window,
 
4
which contains both the revision graph and details panes.
 
5
"""
 
6
 
 
7
__copyright__ = "Copyright (c) 2005 Canonical Ltd."
 
8
__author__    = "Scott James Remnant <scott@ubuntu.com>"
 
9
 
 
10
 
 
11
import gtk
 
12
 
 
13
from bzrlib.plugins.gtk import icon_path
 
14
from bzrlib.plugins.gtk.branchview import TreeView
 
15
from bzrlib.plugins.gtk.preferences import PreferencesWindow
 
16
from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
 
17
from bzrlib.plugins.gtk.window import Window
 
18
 
 
19
from bzrlib.config import GlobalConfig
 
20
from bzrlib.revision import NULL_REVISION
 
21
from bzrlib.trace import mutter
 
22
 
 
23
class BranchWindow(Window):
 
24
    """Branch window.
 
25
 
 
26
    This object represents and manages a single window containing information
 
27
    for a particular branch.
 
28
    """
 
29
 
 
30
    def __init__(self, branch, start_revs, maxnum, parent=None):
 
31
        """Create a new BranchWindow.
 
32
 
 
33
        :param branch: Branch object for branch to show.
 
34
        :param start_revs: Revision ids of top revisions.
 
35
        :param maxnum: Maximum number of revisions to display, 
 
36
                       None for no limit.
 
37
        """
 
38
 
 
39
        Window.__init__(self, parent=parent)
 
40
        self.set_border_width(0)
 
41
 
 
42
        self.branch      = branch
 
43
        self.start_revs  = start_revs
 
44
        self.maxnum      = maxnum
 
45
        self.config      = GlobalConfig()
 
46
 
 
47
        if self.config.get_user_option('viz-compact-view') == 'yes':
 
48
            self.compact_view = True
 
49
        else:
 
50
            self.compact_view = False
 
51
 
 
52
        self.set_title(branch._get_nick(local=True) + " - revision history")
 
53
 
 
54
        # user-configured window size
 
55
        size = self._load_size('viz-window-size')
 
56
        if size:
 
57
            width, height = size
 
58
        else:
 
59
            # Use three-quarters of the screen by default
 
60
            screen = self.get_screen()
 
61
            monitor = screen.get_monitor_geometry(0)
 
62
            width = int(monitor.width * 0.75)
 
63
            height = int(monitor.height * 0.75)
 
64
        self.set_default_size(width, height)
 
65
        self.set_size_request(width/3, height/3)
 
66
        self._save_size_on_destroy(self, 'viz-window-size')
 
67
 
 
68
        # FIXME AndyFitz!
 
69
        icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
 
70
        self.set_icon(icon)
 
71
 
 
72
        gtk.accel_map_add_entry("<viz>/Go/Next Revision", gtk.keysyms.Up, gtk.gdk.MOD1_MASK)
 
73
        gtk.accel_map_add_entry("<viz>/Go/Previous Revision", gtk.keysyms.Down, gtk.gdk.MOD1_MASK)
 
74
        gtk.accel_map_add_entry("<viz>/View/Refresh", gtk.keysyms.F5, 0)
 
75
 
 
76
        self.accel_group = gtk.AccelGroup()
 
77
        self.add_accel_group(self.accel_group)
 
78
 
 
79
        if getattr(gtk.Action, 'set_tool_item_type', None) is not None:
 
80
            # Not available before PyGtk-2.10
 
81
            gtk.Action.set_tool_item_type(gtk.MenuToolButton)
 
82
 
 
83
        self.prev_rev_action = gtk.Action("prev-rev", "_Previous Revision", "Go to the previous revision", gtk.STOCK_GO_DOWN)
 
84
        self.prev_rev_action.set_accel_path("<viz>/Go/Previous Revision")
 
85
        self.prev_rev_action.set_accel_group(self.accel_group)
 
86
        self.prev_rev_action.connect("activate", self._back_clicked_cb)
 
87
        self.prev_rev_action.connect_accelerator()
 
88
 
 
89
        self.next_rev_action = gtk.Action("next-rev", "_Next Revision", "Go to the next revision", gtk.STOCK_GO_UP)
 
90
        self.next_rev_action.set_accel_path("<viz>/Go/Next Revision")
 
91
        self.next_rev_action.set_accel_group(self.accel_group)
 
92
        self.next_rev_action.connect("activate", self._fwd_clicked_cb)
 
93
        self.next_rev_action.connect_accelerator()
 
94
 
 
95
        self.refresh_action = gtk.Action("refresh", "_Refresh", "Refresh view", gtk.STOCK_REFRESH)
 
96
        self.refresh_action.set_accel_path("<viz>/View/Refresh")
 
97
        self.refresh_action.set_accel_group(self.accel_group)
 
98
        self.refresh_action.connect("activate", self._refresh_clicked)
 
99
        self.refresh_action.connect_accelerator()
 
100
 
 
101
        self.construct()
 
102
 
 
103
    def _save_size_on_destroy(self, widget, config_name):
 
104
        """Creates a hook that saves the size of widget to config option 
 
105
           config_name when the window is destroyed/closed."""
 
106
        def save_size(src):
 
107
            width, height = widget.allocation.width, widget.allocation.height
 
108
            value = '%sx%s' % (width, height)
 
109
            self.config.set_user_option(config_name, value)
 
110
        self.connect("destroy", save_size)
 
111
 
 
112
    def set_revision(self, revid):
 
113
        self.treeview.set_revision_id(revid)
 
114
 
 
115
    def construct(self):
 
116
        """Construct the window contents."""
 
117
        vbox = gtk.VBox(spacing=0)
 
118
        self.add(vbox)
 
119
 
 
120
        self.paned = gtk.VPaned()
 
121
        self.paned.pack1(self.construct_top(), resize=False, shrink=True)
 
122
        self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
 
123
        self.paned.show()
 
124
 
 
125
        nav = self.construct_navigation()
 
126
        menubar = self.construct_menubar()
 
127
        vbox.pack_start(menubar, expand=False, fill=True)
 
128
        vbox.pack_start(nav, expand=False, fill=True)
 
129
 
 
130
        vbox.pack_start(self.paned, expand=True, fill=True)
 
131
        vbox.set_focus_child(self.paned)
 
132
 
 
133
        self.treeview.connect('revision-selected',
 
134
                self._treeselection_changed_cb)
 
135
        self.treeview.connect('revision-activated',
 
136
                self._tree_revision_activated)
 
137
 
 
138
        self.treeview.connect('tag-added', lambda w, t, r: self._update_tags())
 
139
        vbox.show()
 
140
 
 
141
    def construct_menubar(self):
 
142
        menubar = gtk.MenuBar()
 
143
 
 
144
        file_menu = gtk.Menu()
 
145
        file_menuitem = gtk.MenuItem("_File")
 
146
        file_menuitem.set_submenu(file_menu)
 
147
 
 
148
        file_menu_close = gtk.ImageMenuItem(gtk.STOCK_CLOSE, self.accel_group)
 
149
        file_menu_close.connect('activate', lambda x: self.destroy())
 
150
 
 
151
        file_menu_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accel_group)
 
152
        file_menu_quit.connect('activate', lambda x: gtk.main_quit())
 
153
 
 
154
        if self._parent is not None:
 
155
            file_menu.add(file_menu_close)
 
156
        file_menu.add(file_menu_quit)
 
157
 
 
158
        edit_menu = gtk.Menu()
 
159
        edit_menuitem = gtk.MenuItem("_Edit")
 
160
        edit_menuitem.set_submenu(edit_menu)
 
161
 
 
162
        edit_menu_branchopts = gtk.MenuItem("Branch Settings")
 
163
        edit_menu_branchopts.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
 
164
 
 
165
        edit_menu_globopts = gtk.MenuItem("Global Settings")
 
166
        edit_menu_globopts.connect('activate', lambda x: PreferencesWindow().show())
 
167
 
 
168
        edit_menu.add(edit_menu_branchopts)
 
169
        edit_menu.add(edit_menu_globopts)
 
170
 
 
171
        view_menu = gtk.Menu()
 
172
        view_menuitem = gtk.MenuItem("_View")
 
173
        view_menuitem.set_submenu(view_menu)
 
174
 
 
175
        view_menu_refresh = self.refresh_action.create_menu_item()
 
176
        view_menu_refresh.connect('activate', self._refresh_clicked)
 
177
 
 
178
        view_menu.add(view_menu_refresh)
 
179
        view_menu.add(gtk.SeparatorMenuItem())
 
180
 
 
181
        view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
 
182
        view_menu_toolbar.set_active(True)
 
183
        if self.config.get_user_option('viz-toolbar-visible') == 'False':
 
184
            view_menu_toolbar.set_active(False)
 
185
            self.toolbar.hide()
 
186
        view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
 
187
 
 
188
        view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
 
189
        view_menu_compact.set_active(self.compact_view)
 
190
        view_menu_compact.connect('activate', self._brokenlines_toggled_cb)
 
191
 
 
192
        view_menu_diffs = gtk.CheckMenuItem("Show Diffs")
 
193
        view_menu_diffs.set_active(False)
 
194
        if self.config.get_user_option('viz-show-diffs') == 'True':
 
195
            view_menu_diffs.set_active(True)
 
196
        view_menu_diffs.connect('toggled', self._diff_visibility_changed)
 
197
 
 
198
        view_menu_wide_diffs = gtk.CheckMenuItem("Wide Diffs")
 
199
        view_menu_wide_diffs.set_active(False)
 
200
        if self.config.get_user_option('viz-wide-diffs') == 'True':
 
201
            view_menu_wide_diffs.set_active(True)
 
202
        view_menu_wide_diffs.connect('toggled', self._diff_placement_changed)
 
203
 
 
204
        view_menu_wrap_diffs = gtk.CheckMenuItem("Wrap _Long Lines in Diffs")
 
205
        view_menu_wrap_diffs.set_active(False)
 
206
        if self.config.get_user_option('viz-wrap-diffs') == 'True':
 
207
            view_menu_wrap_diffs.set_active(True)
 
208
        view_menu_wrap_diffs.connect('toggled', self._diff_wrap_changed)
 
209
 
 
210
        view_menu.add(view_menu_toolbar)
 
211
        view_menu.add(view_menu_compact)
 
212
        view_menu.add(gtk.SeparatorMenuItem())
 
213
        view_menu.add(view_menu_diffs)
 
214
        view_menu.add(view_menu_wide_diffs)
 
215
        view_menu.add(view_menu_wrap_diffs)
 
216
        view_menu.add(gtk.SeparatorMenuItem())
 
217
 
 
218
        self.mnu_show_revno_column = gtk.CheckMenuItem("Show Revision _Number Column")
 
219
        self.mnu_show_date_column = gtk.CheckMenuItem("Show _Date Column")
 
220
 
 
221
        # Revision numbers are pointless if there are multiple branches
 
222
        if len(self.start_revs) > 1:
 
223
            self.mnu_show_revno_column.set_sensitive(False)
 
224
            self.treeview.set_property('revno-column-visible', False)
 
225
 
 
226
        for (col, name) in [(self.mnu_show_revno_column, "revno"), 
 
227
                            (self.mnu_show_date_column, "date")]:
 
228
            col.set_active(self.treeview.get_property(name + "-column-visible"))
 
229
            col.connect('toggled', self._col_visibility_changed, name)
 
230
            view_menu.add(col)
 
231
 
 
232
        go_menu = gtk.Menu()
 
233
        go_menu.set_accel_group(self.accel_group)
 
234
        go_menuitem = gtk.MenuItem("_Go")
 
235
        go_menuitem.set_submenu(go_menu)
 
236
 
 
237
        go_menu_next = self.next_rev_action.create_menu_item()
 
238
        go_menu_prev = self.prev_rev_action.create_menu_item()
 
239
 
 
240
        tag_image = gtk.Image()
 
241
        tag_image.set_from_file(icon_path("tag-16.png"))
 
242
        self.go_menu_tags = gtk.ImageMenuItem("_Tags")
 
243
        self.go_menu_tags.set_image(tag_image)
 
244
        self.treeview.connect('refreshed', lambda w: self._update_tags())
 
245
 
 
246
        go_menu.add(go_menu_next)
 
247
        go_menu.add(go_menu_prev)
 
248
        go_menu.add(gtk.SeparatorMenuItem())
 
249
        go_menu.add(self.go_menu_tags)
 
250
 
 
251
        self.revision_menu = RevisionMenu(self.branch.repository, [], self.branch, parent=self)
 
252
        revision_menuitem = gtk.MenuItem("_Revision")
 
253
        revision_menuitem.set_submenu(self.revision_menu)
 
254
 
 
255
        branch_menu = gtk.Menu()
 
256
        branch_menuitem = gtk.MenuItem("_Branch")
 
257
        branch_menuitem.set_submenu(branch_menu)
 
258
 
 
259
        branch_menu.add(gtk.MenuItem("Pu_ll Revisions"))
 
260
        branch_menu.add(gtk.MenuItem("Pu_sh Revisions"))
 
261
 
 
262
        try:
 
263
            from bzrlib.plugins import search
 
264
        except ImportError:
 
265
            mutter("Didn't find search plugin")
 
266
        else:
 
267
            branch_menu.add(gtk.SeparatorMenuItem())
 
268
 
 
269
            branch_index_menuitem = gtk.MenuItem("_Index")
 
270
            branch_index_menuitem.connect('activate', self._branch_index_cb)
 
271
            branch_menu.add(branch_index_menuitem)
 
272
 
 
273
            branch_search_menuitem = gtk.MenuItem("_Search")
 
274
            branch_search_menuitem.connect('activate', self._branch_search_cb)
 
275
            branch_menu.add(branch_search_menuitem)
 
276
 
 
277
        help_menu = gtk.Menu()
 
278
        help_menuitem = gtk.MenuItem("_Help")
 
279
        help_menuitem.set_submenu(help_menu)
 
280
 
 
281
        help_about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT, self.accel_group)
 
282
        help_about_menuitem.connect('activate', self._about_dialog_cb)
 
283
 
 
284
        help_menu.add(help_about_menuitem)
 
285
 
 
286
        menubar.add(file_menuitem)
 
287
        menubar.add(edit_menuitem)
 
288
        menubar.add(view_menuitem)
 
289
        menubar.add(go_menuitem)
 
290
        menubar.add(revision_menuitem)
 
291
        menubar.add(branch_menuitem)
 
292
        menubar.add(help_menuitem)
 
293
        menubar.show_all()
 
294
 
 
295
        return menubar
 
296
 
 
297
    def construct_top(self):
 
298
        """Construct the top-half of the window."""
 
299
        # FIXME: Make broken_line_length configurable
 
300
 
 
301
        self.treeview = TreeView(self.branch, self.start_revs, self.maxnum, self.compact_view)
 
302
 
 
303
        for col in ["revno", "date"]:
 
304
            option = self.config.get_user_option(col + '-column-visible')
 
305
            if option is not None:
 
306
                self.treeview.set_property(col + '-column-visible', option == 'True')
 
307
            else:
 
308
                self.treeview.set_property(col + '-column-visible', False)
 
309
 
 
310
        self.treeview.show()
 
311
 
 
312
        align = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
 
313
        align.set_padding(5, 0, 0, 0)
 
314
        align.add(self.treeview)
 
315
        # user-configured size
 
316
        size = self._load_size('viz-graph-size')
 
317
        if size:
 
318
            width, height = size
 
319
            align.set_size_request(width, height)
 
320
        else:
 
321
            (width, height) = self.get_size()
 
322
            align.set_size_request(width, int(height / 2.5))
 
323
        self._save_size_on_destroy(align, 'viz-graph-size')
 
324
        align.show()
 
325
 
 
326
        return align
 
327
 
 
328
    def construct_navigation(self):
 
329
        """Construct the navigation buttons."""
 
330
        self.toolbar = gtk.Toolbar()
 
331
        self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
 
332
 
 
333
        self.prev_button = self.prev_rev_action.create_tool_item()
 
334
        self.toolbar.insert(self.prev_button, -1)
 
335
 
 
336
        self.next_button = self.next_rev_action.create_tool_item()
 
337
        self.toolbar.insert(self.next_button, -1)
 
338
 
 
339
        self.toolbar.insert(gtk.SeparatorToolItem(), -1)
 
340
 
 
341
        refresh_button = gtk.ToolButton(gtk.STOCK_REFRESH)
 
342
        refresh_button.connect('clicked', self._refresh_clicked)
 
343
        self.toolbar.insert(refresh_button, -1)
 
344
 
 
345
        self.toolbar.show_all()
 
346
 
 
347
        return self.toolbar
 
348
 
 
349
    def construct_bottom(self):
 
350
        """Construct the bottom half of the window."""
 
351
        if self.config.get_user_option('viz-wide-diffs') == 'True':
 
352
            self.diff_paned = gtk.VPaned()
 
353
        else:
 
354
            self.diff_paned = gtk.HPaned()
 
355
        (width, height) = self.get_size()
 
356
        self.diff_paned.set_size_request(20, 20) # shrinkable
 
357
 
 
358
        from bzrlib.plugins.gtk.revisionview import RevisionView
 
359
        self.revisionview = RevisionView(branch=self.branch)
 
360
        self.revisionview.set_size_request(width/3, int(height / 2.5))
 
361
        # user-configured size
 
362
        size = self._load_size('viz-revisionview-size')
 
363
        if size:
 
364
            width, height = size
 
365
            self.revisionview.set_size_request(width, height)
 
366
        self._save_size_on_destroy(self.revisionview, 'viz-revisionview-size')
 
367
        self.revisionview.show()
 
368
        self.revisionview.set_show_callback(self._show_clicked_cb)
 
369
        self.revisionview.connect('notify::revision', self._go_clicked_cb)
 
370
        self.treeview.connect('tag-added', lambda w, t, r: self.revisionview.update_tags())
 
371
        self.diff_paned.pack1(self.revisionview)
 
372
 
 
373
        from bzrlib.plugins.gtk.diff import DiffWidget
 
374
        self.diff = DiffWidget()
 
375
        self.diff_paned.pack2(self.diff)
 
376
 
 
377
        self.diff_paned.show_all()
 
378
        if self.config.get_user_option('viz-show-diffs') != 'True':
 
379
            self.diff.hide()
 
380
 
 
381
        return self.diff_paned
 
382
 
 
383
    def _tag_selected_cb(self, menuitem, revid):
 
384
        self.treeview.set_revision_id(revid)
 
385
 
 
386
    def _treeselection_changed_cb(self, selection, *args):
 
387
        """callback for when the treeview changes."""
 
388
        revision = self.treeview.get_revision()
 
389
        parents  = self.treeview.get_parents()
 
390
        children = self.treeview.get_children()
 
391
 
 
392
        self.revision_menu.set_revision_ids([revision.revision_id])
 
393
 
 
394
        if revision and revision != NULL_REVISION:
 
395
            prev_menu = gtk.Menu()
 
396
            if len(parents) > 0:
 
397
                self.prev_rev_action.set_sensitive(True)
 
398
                for parent_id in parents:
 
399
                    if parent_id and parent_id != NULL_REVISION:
 
400
                        parent = self.branch.repository.get_revision(parent_id)
 
401
                        try:
 
402
                            str = ' (' + parent.properties['branch-nick'] + ')'
 
403
                        except KeyError:
 
404
                            str = ""
 
405
 
 
406
                        item = gtk.MenuItem(parent.message.split("\n")[0] + str)
 
407
                        item.connect('activate', self._set_revision_cb, parent_id)
 
408
                        prev_menu.add(item)
 
409
                prev_menu.show_all()
 
410
            else:
 
411
                self.prev_rev_action.set_sensitive(False)
 
412
                prev_menu.hide()
 
413
 
 
414
            if getattr(self.prev_button, 'set_menu', None) is not None:
 
415
                self.prev_button.set_menu(prev_menu)
 
416
 
 
417
            next_menu = gtk.Menu()
 
418
            if len(children) > 0:
 
419
                self.next_rev_action.set_sensitive(True)
 
420
                for child_id in children:
 
421
                    child = self.branch.repository.get_revision(child_id)
 
422
                    try:
 
423
                        str = ' (' + child.properties['branch-nick'] + ')'
 
424
                    except KeyError:
 
425
                        str = ""
 
426
 
 
427
                    item = gtk.MenuItem(child.message.split("\n")[0] + str)
 
428
                    item.connect('activate', self._set_revision_cb, child_id)
 
429
                    next_menu.add(item)
 
430
                next_menu.show_all()
 
431
            else:
 
432
                self.next_rev_action.set_sensitive(False)
 
433
                next_menu.hide()
 
434
 
 
435
            if getattr(self.next_button, 'set_menu', None) is not None:
 
436
                self.next_button.set_menu(next_menu)
 
437
 
 
438
            self.revisionview.set_revision(revision)
 
439
            self.revisionview.set_children(children)
 
440
            self.update_diff_panel(revision, parents)
 
441
 
 
442
    def _tree_revision_activated(self, widget, path, col):
 
443
        # TODO: more than one parent
 
444
        """Callback for when a treeview row gets activated."""
 
445
        revision = self.treeview.get_revision()
 
446
        parents  = self.treeview.get_parents()
 
447
 
 
448
        if len(parents) == 0:
 
449
            parent_id = NULL_REVISION
 
450
        else:
 
451
            parent_id = parents[0]
 
452
 
 
453
        self.show_diff(revision.revision_id, parent_id)
 
454
        self.treeview.grab_focus()
 
455
 
 
456
    def _back_clicked_cb(self, *args):
 
457
        """Callback for when the back button is clicked."""
 
458
        self.treeview.back()
 
459
 
 
460
    def _fwd_clicked_cb(self, *args):
 
461
        """Callback for when the forward button is clicked."""
 
462
        self.treeview.forward()
 
463
 
 
464
    def _go_clicked_cb(self, w, p):
 
465
        """Callback for when the go button for a parent is clicked."""
 
466
        if self.revisionview.get_revision() is not None:
 
467
            self.treeview.set_revision(self.revisionview.get_revision())
 
468
 
 
469
    def _show_clicked_cb(self, revid, parentid):
 
470
        """Callback for when the show button for a parent is clicked."""
 
471
        self.show_diff(revid, parentid)
 
472
        self.treeview.grab_focus()
 
473
 
 
474
    def _set_revision_cb(self, w, revision_id):
 
475
        self.treeview.set_revision_id(revision_id)
 
476
 
 
477
    def _brokenlines_toggled_cb(self, button):
 
478
        self.compact_view = button.get_active()
 
479
 
 
480
        if self.compact_view:
 
481
            option = 'yes'
 
482
        else:
 
483
            option = 'no'
 
484
 
 
485
        self.config.set_user_option('viz-compact-view', option)
 
486
        self.treeview.set_property('compact', self.compact_view)
 
487
        self.treeview.refresh()
 
488
 
 
489
    def _branch_index_cb(self, w):
 
490
        from bzrlib.plugins.search import index as _mod_index
 
491
        _mod_index.index_url(self.branch.base)
 
492
 
 
493
    def _branch_search_cb(self, w):
 
494
        from bzrlib.plugins.search import index as _mod_index
 
495
        from bzrlib.plugins.gtk.search import SearchDialog
 
496
        from bzrlib.plugins.search import errors as search_errors
 
497
 
 
498
        try:
 
499
            index = _mod_index.open_index_url(self.branch.base)
 
500
        except search_errors.NoSearchIndex:
 
501
            dialog = gtk.MessageDialog(self, type=gtk.MESSAGE_QUESTION, 
 
502
                buttons=gtk.BUTTONS_OK_CANCEL, 
 
503
                message_format="This branch has not been indexed yet. "
 
504
                               "Index now?")
 
505
            if dialog.run() == gtk.RESPONSE_OK:
 
506
                dialog.destroy()
 
507
                index = _mod_index.index_url(self.branch.base)
 
508
            else:
 
509
                dialog.destroy()
 
510
                return
 
511
 
 
512
        dialog = SearchDialog(index)
 
513
 
 
514
        if dialog.run() == gtk.RESPONSE_OK:
 
515
            self.set_revision(dialog.get_revision())
 
516
 
 
517
        dialog.destroy()
 
518
 
 
519
    def _about_dialog_cb(self, w):
 
520
        from bzrlib.plugins.gtk.about import AboutDialog
 
521
        AboutDialog().run()
 
522
 
 
523
    def _col_visibility_changed(self, col, property):
 
524
        self.config.set_user_option(property + '-column-visible', col.get_active())
 
525
        self.treeview.set_property(property + '-column-visible', col.get_active())
 
526
 
 
527
    def _toolbar_visibility_changed(self, col):
 
528
        if col.get_active():
 
529
            self.toolbar.show()
 
530
        else:
 
531
            self.toolbar.hide()
 
532
        self.config.set_user_option('viz-toolbar-visible', col.get_active())
 
533
 
 
534
    def _make_diff_nonzero_size(self):
 
535
        """make sure the diff isn't zero-width or zero-height"""
 
536
        alloc = self.diff.get_allocation()
 
537
        if (alloc.width < 10) or (alloc.height < 10):
 
538
            width, height = self.get_size()
 
539
            self.revisionview.set_size_request(width/3, int(height / 2.5))
 
540
 
 
541
    def _diff_visibility_changed(self, col):
 
542
        """Hide or show the diff panel."""
 
543
        if col.get_active():
 
544
            self.diff.show()
 
545
            self._make_diff_nonzero_size()
 
546
        else:
 
547
            self.diff.hide()
 
548
        self.config.set_user_option('viz-show-diffs', str(col.get_active()))
 
549
        self.update_diff_panel()
 
550
 
 
551
    def _diff_placement_changed(self, col):
 
552
        """Toggle the diff panel's position."""
 
553
        self.config.set_user_option('viz-wide-diffs', str(col.get_active()))
 
554
 
 
555
        old = self.paned.get_child2()
 
556
        self.paned.remove(old)
 
557
        self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
 
558
        self._make_diff_nonzero_size()
 
559
 
 
560
        self.treeview.emit('revision-selected')
 
561
 
 
562
    def _diff_wrap_changed(self, widget):
 
563
        """Toggle word wrap in the diff widget."""
 
564
        self.config.set_user_option('viz-wrap-diffs', widget.get_active())
 
565
        self.diff._on_wraplines_toggled(widget)
 
566
 
 
567
    def _refresh_clicked(self, w):
 
568
        self.treeview.refresh()
 
569
 
 
570
    def _update_tags(self):
 
571
        menu = gtk.Menu()
 
572
 
 
573
        if self.branch.supports_tags():
 
574
            tags = self.branch.tags.get_tag_dict().items()
 
575
            tags.sort(reverse=True)
 
576
            for tag, revid in tags:
 
577
                tag_image = gtk.Image()
 
578
                tag_image.set_from_file(icon_path('tag-16.png'))
 
579
                tag_item = gtk.ImageMenuItem(tag.replace('_', '__'))
 
580
                tag_item.set_image(tag_image)
 
581
                tag_item.connect('activate', self._tag_selected_cb, revid)
 
582
                tag_item.set_sensitive(self.treeview.has_revision_id(revid))
 
583
                menu.add(tag_item)
 
584
            self.go_menu_tags.set_submenu(menu)
 
585
 
 
586
            self.go_menu_tags.set_sensitive(len(tags) != 0)
 
587
        else:
 
588
            self.go_menu_tags.set_sensitive(False)
 
589
 
 
590
        self.go_menu_tags.show_all()
 
591
 
 
592
    def _load_size(self, name):
 
593
        """Read and parse 'name' from self.config.
 
594
        The value is a string, formatted as WIDTHxHEIGHT
 
595
        Returns None, or (width, height)
 
596
        """
 
597
        size = self.config.get_user_option(name)
 
598
        if size:
 
599
            width, height = [int(num) for num in size.split('x')]
 
600
            # avoid writing config every time we start
 
601
            return width, height
 
602
        return None
 
603
 
 
604
    def show_diff(self, revid=None, parentid=NULL_REVISION):
 
605
        """Open a new window to show a diff between the given revisions."""
 
606
        from bzrlib.plugins.gtk.diff import DiffWindow
 
607
        window = DiffWindow(parent=self)
 
608
 
 
609
        rev_tree    = self.branch.repository.revision_tree(revid)
 
610
        parent_tree = self.branch.repository.revision_tree(parentid)
 
611
 
 
612
        description = revid + " - " + self.branch._get_nick(local=True)
 
613
        window.set_diff(description, rev_tree, parent_tree)
 
614
        window.show()
 
615
 
 
616
    def update_diff_panel(self, revision=None, parents=None):
 
617
        """Show the current revision in the diff panel."""
 
618
        if self.config.get_user_option('viz-show-diffs') != 'True':
 
619
            return
 
620
 
 
621
        if not revision: # default to selected row
 
622
            revision = self.treeview.get_revision()
 
623
        if revision == NULL_REVISION:
 
624
            return
 
625
 
 
626
        if not parents: # default to selected row's parents
 
627
            parents  = self.treeview.get_parents()
 
628
        if len(parents) == 0:
 
629
            parent_id = NULL_REVISION
 
630
        else:
 
631
            parent_id = parents[0]
 
632
 
 
633
        rev_tree    = self.branch.repository.revision_tree(revision.revision_id)
 
634
        parent_tree = self.branch.repository.revision_tree(parent_id)
 
635
 
 
636
        self.diff.set_diff(rev_tree, parent_tree)
 
637
        if self.config.get_user_option('viz-wrap-diffs') == 'True':
 
638
            self.diff._on_wraplines_toggled(wrap=True)
 
639
        self.diff.show_all()