/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: Curtis Hovey
  • Date: 2011-08-12 20:25:28 UTC
  • mto: This revision was merged to the branch mainline in revision 741.
  • Revision ID: sinzui.is@verizon.net-20110812202528-4xf4a2t23urx50d2
Updated gst to gtk3.

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