/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-06-18 17:41:11 UTC
  • Revision ID: jelmer@samba.org-20110618174111-1f7601d96qs4h52x
Catch org.freedesktop.DBus.Error.NotSupported

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: UTF-8 -*-
2
1
"""Branch window.
3
2
 
4
3
This module contains the code to manage the branch information window,
5
4
which contains both the revision graph and details panes.
6
5
"""
7
6
 
8
 
__copyright__ = "Copyright © 2005 Canonical Ltd."
 
7
__copyright__ = "Copyright (c) 2005 Canonical Ltd."
9
8
__author__    = "Scott James Remnant <scott@ubuntu.com>"
10
9
 
11
10
 
12
11
import gtk
13
 
import gobject
14
 
import pango
15
12
 
16
 
from bzrlib.plugins.gtk.window import Window
17
13
from bzrlib.plugins.gtk import icon_path
18
 
from bzrlib.plugins.gtk.tags import AddTagDialog
 
14
from bzrlib.plugins.gtk.branchview import TreeView
19
15
from bzrlib.plugins.gtk.preferences import PreferencesWindow
20
 
from bzrlib.plugins.gtk.branchview import TreeView, treemodel
 
16
from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
 
17
from bzrlib.plugins.gtk.window import Window
21
18
 
22
 
from bzrlib.config import BranchConfig, GlobalConfig
23
 
from bzrlib.revision import Revision, NULL_REVISION
 
19
from bzrlib.config import GlobalConfig
 
20
from bzrlib.revision import NULL_REVISION
24
21
from bzrlib.trace import mutter
25
22
 
 
23
 
26
24
class BranchWindow(Window):
27
25
    """Branch window.
28
26
 
52
50
        else:
53
51
            self.compact_view = False
54
52
 
55
 
        self.set_title(branch.nick + " - revision history")
 
53
        self.set_title(branch._get_nick(local=True) + " - revision history")
56
54
 
57
 
        # Use three-quarters of the screen by default
58
 
        screen = self.get_screen()
59
 
        monitor = screen.get_monitor_geometry(0)
60
 
        width = int(monitor.width * 0.75)
61
 
        height = int(monitor.height * 0.75)
 
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)
62
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')
63
68
 
64
69
        # FIXME AndyFitz!
65
70
        icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
72
77
        self.accel_group = gtk.AccelGroup()
73
78
        self.add_accel_group(self.accel_group)
74
79
 
75
 
        gtk.Action.set_tool_item_type(gtk.MenuToolButton)
 
80
        if getattr(gtk.Action, 'set_tool_item_type', None) is not None:
 
81
            # Not available before PyGtk-2.10
 
82
            gtk.Action.set_tool_item_type(gtk.MenuToolButton)
76
83
 
77
84
        self.prev_rev_action = gtk.Action("prev-rev", "_Previous Revision", "Go to the previous revision", gtk.STOCK_GO_DOWN)
78
85
        self.prev_rev_action.set_accel_path("<viz>/Go/Previous Revision")
92
99
        self.refresh_action.connect("activate", self._refresh_clicked)
93
100
        self.refresh_action.connect_accelerator()
94
101
 
95
 
        self.construct()
 
102
        self.vbox = self.construct()
 
103
 
 
104
    def _save_size_on_destroy(self, widget, config_name):
 
105
        """Creates a hook that saves the size of widget to config option 
 
106
           config_name when the window is destroyed/closed."""
 
107
        def save_size(src):
 
108
            width, height = widget.allocation.width, widget.allocation.height
 
109
            value = '%sx%s' % (width, height)
 
110
            self.config.set_user_option(config_name, value)
 
111
        self.connect("destroy", save_size)
96
112
 
97
113
    def set_revision(self, revid):
98
114
        self.treeview.set_revision_id(revid)
102
118
        vbox = gtk.VBox(spacing=0)
103
119
        self.add(vbox)
104
120
 
105
 
        self.paned = gtk.VPaned()
106
 
        self.paned.pack1(self.construct_top(), resize=True, shrink=False)
107
 
        self.paned.pack2(self.construct_bottom(), resize=False, shrink=True)
 
121
        # order is important here
 
122
        paned = self.construct_paned()
 
123
        nav = self.construct_navigation()
 
124
        menubar = self.construct_menubar()
 
125
 
 
126
        vbox.pack_start(menubar, expand=False, fill=True)
 
127
        vbox.pack_start(nav, expand=False, fill=True)
 
128
        vbox.pack_start(paned, expand=True, fill=True)
 
129
        vbox.set_focus_child(paned)
 
130
 
 
131
 
 
132
        vbox.show()
 
133
 
 
134
        return vbox
 
135
 
 
136
    def construct_paned(self):
 
137
        """Construct the main HPaned/VPaned contents."""
 
138
        if self.config.get_user_option('viz-vertical') == 'True':
 
139
            self.paned = gtk.HPaned()
 
140
        else:
 
141
            self.paned = gtk.VPaned()
 
142
 
 
143
        self.paned.pack1(self.construct_top(), resize=False, shrink=True)
 
144
        self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
108
145
        self.paned.show()
109
146
 
110
 
        vbox.pack_start(self.construct_menubar(), expand=False, fill=True)
111
 
        vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
112
 
        
113
 
        vbox.pack_start(self.paned, expand=True, fill=True)
114
 
        vbox.set_focus_child(self.paned)
115
 
 
116
 
        vbox.show()
 
147
        return self.paned
117
148
 
118
149
    def construct_menubar(self):
119
150
        menubar = gtk.MenuBar()
124
155
 
125
156
        file_menu_close = gtk.ImageMenuItem(gtk.STOCK_CLOSE, self.accel_group)
126
157
        file_menu_close.connect('activate', lambda x: self.destroy())
127
 
        
 
158
 
128
159
        file_menu_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accel_group)
129
160
        file_menu_quit.connect('activate', lambda x: gtk.main_quit())
130
 
        
 
161
 
131
162
        if self._parent is not None:
132
163
            file_menu.add(file_menu_close)
133
164
        file_menu.add(file_menu_quit)
136
167
        edit_menuitem = gtk.MenuItem("_Edit")
137
168
        edit_menuitem.set_submenu(edit_menu)
138
169
 
139
 
        edit_menu_find = gtk.ImageMenuItem(gtk.STOCK_FIND)
140
 
 
141
170
        edit_menu_branchopts = gtk.MenuItem("Branch Settings")
142
171
        edit_menu_branchopts.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
143
172
 
144
173
        edit_menu_globopts = gtk.MenuItem("Global Settings")
145
174
        edit_menu_globopts.connect('activate', lambda x: PreferencesWindow().show())
146
175
 
147
 
        edit_menu.add(edit_menu_find)
148
176
        edit_menu.add(edit_menu_branchopts)
149
177
        edit_menu.add(edit_menu_globopts)
150
178
 
160
188
 
161
189
        view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
162
190
        view_menu_toolbar.set_active(True)
 
191
        if self.config.get_user_option('viz-toolbar-visible') == 'False':
 
192
            view_menu_toolbar.set_active(False)
 
193
            self.toolbar.hide()
163
194
        view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
164
195
 
165
196
        view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
166
197
        view_menu_compact.set_active(self.compact_view)
167
198
        view_menu_compact.connect('activate', self._brokenlines_toggled_cb)
168
199
 
 
200
        view_menu_vertical = gtk.CheckMenuItem("Side-by-side Layout")
 
201
        view_menu_vertical.set_active(False)
 
202
        if self.config.get_user_option('viz-vertical') == 'True':
 
203
            view_menu_vertical.set_active(True)
 
204
        view_menu_vertical.connect('toggled', self._vertical_layout)
 
205
 
 
206
        view_menu_diffs = gtk.CheckMenuItem("Show Diffs")
 
207
        view_menu_diffs.set_active(False)
 
208
        if self.config.get_user_option('viz-show-diffs') == 'True':
 
209
            view_menu_diffs.set_active(True)
 
210
        view_menu_diffs.connect('toggled', self._diff_visibility_changed)
 
211
 
 
212
        view_menu_wide_diffs = gtk.CheckMenuItem("Wide Diffs")
 
213
        view_menu_wide_diffs.set_active(False)
 
214
        if self.config.get_user_option('viz-wide-diffs') == 'True':
 
215
            view_menu_wide_diffs.set_active(True)
 
216
        view_menu_wide_diffs.connect('toggled', self._diff_placement_changed)
 
217
 
 
218
        view_menu_wrap_diffs = gtk.CheckMenuItem("Wrap _Long Lines in Diffs")
 
219
        view_menu_wrap_diffs.set_active(False)
 
220
        if self.config.get_user_option('viz-wrap-diffs') == 'True':
 
221
            view_menu_wrap_diffs.set_active(True)
 
222
        view_menu_wrap_diffs.connect('toggled', self._diff_wrap_changed)
 
223
 
169
224
        view_menu.add(view_menu_toolbar)
170
225
        view_menu.add(view_menu_compact)
 
226
        view_menu.add(view_menu_vertical)
 
227
        view_menu.add(gtk.SeparatorMenuItem())
 
228
        view_menu.add(view_menu_diffs)
 
229
        view_menu.add(view_menu_wide_diffs)
 
230
        view_menu.add(view_menu_wrap_diffs)
171
231
        view_menu.add(gtk.SeparatorMenuItem())
172
232
 
173
233
        self.mnu_show_revno_column = gtk.CheckMenuItem("Show Revision _Number Column")
188
248
        go_menu.set_accel_group(self.accel_group)
189
249
        go_menuitem = gtk.MenuItem("_Go")
190
250
        go_menuitem.set_submenu(go_menu)
191
 
        
 
251
 
192
252
        go_menu_next = self.next_rev_action.create_menu_item()
193
253
        go_menu_prev = self.prev_rev_action.create_menu_item()
194
254
 
196
256
        tag_image.set_from_file(icon_path("tag-16.png"))
197
257
        self.go_menu_tags = gtk.ImageMenuItem("_Tags")
198
258
        self.go_menu_tags.set_image(tag_image)
199
 
        self._update_tags()
 
259
        self.treeview.connect('refreshed', lambda w: self._update_tags())
200
260
 
201
261
        go_menu.add(go_menu_next)
202
262
        go_menu.add(go_menu_prev)
203
263
        go_menu.add(gtk.SeparatorMenuItem())
204
264
        go_menu.add(self.go_menu_tags)
205
265
 
206
 
        revision_menu = gtk.Menu()
 
266
        self.revision_menu = RevisionMenu(self.branch.repository, [],
 
267
            self.branch, parent=self)
207
268
        revision_menuitem = gtk.MenuItem("_Revision")
208
 
        revision_menuitem.set_submenu(revision_menu)
209
 
 
210
 
        revision_menu_diff = gtk.MenuItem("View Changes")
211
 
        revision_menu_diff.connect('activate', 
212
 
                self._menu_diff_cb)
213
 
        
214
 
        revision_menu_compare = gtk.MenuItem("Compare with...")
215
 
        revision_menu_compare.connect('activate',
216
 
                self._compare_with_cb)
217
 
 
218
 
        revision_menu_tag = gtk.MenuItem("Tag Revision")
219
 
        revision_menu_tag.connect('activate', self._tag_revision_cb)
220
 
 
221
 
        revision_menu.add(revision_menu_tag)
222
 
        revision_menu.add(revision_menu_diff)
223
 
        revision_menu.add(revision_menu_compare)
 
269
        revision_menuitem.set_submenu(self.revision_menu)
224
270
 
225
271
        branch_menu = gtk.Menu()
226
272
        branch_menuitem = gtk.MenuItem("_Branch")
234
280
        except ImportError:
235
281
            mutter("Didn't find search plugin")
236
282
        else:
 
283
            branch_menu.add(gtk.SeparatorMenuItem())
 
284
 
237
285
            branch_index_menuitem = gtk.MenuItem("_Index")
238
286
            branch_index_menuitem.connect('activate', self._branch_index_cb)
239
287
            branch_menu.add(branch_index_menuitem)
240
288
 
 
289
            branch_search_menuitem = gtk.MenuItem("_Search")
 
290
            branch_search_menuitem.connect('activate', self._branch_search_cb)
 
291
            branch_menu.add(branch_search_menuitem)
 
292
 
241
293
        help_menu = gtk.Menu()
242
294
        help_menuitem = gtk.MenuItem("_Help")
243
295
        help_menuitem.set_submenu(help_menu)
244
296
 
245
 
        help_about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT, self.accel_group)
 
297
        help_about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT,
 
298
            self.accel_group)
246
299
        help_about_menuitem.connect('activate', self._about_dialog_cb)
247
300
 
248
301
        help_menu.add(help_about_menuitem)
262
315
        """Construct the top-half of the window."""
263
316
        # FIXME: Make broken_line_length configurable
264
317
 
265
 
        self.treeview = TreeView(self.branch, self.start_revs, self.maxnum, self.compact_view)
266
 
 
267
 
        self.treeview.connect('revision-selected',
268
 
                self._treeselection_changed_cb)
269
 
        self.treeview.connect('revision-activated',
270
 
                self._tree_revision_activated)
271
 
 
272
 
        self.treeview.connect('tag-added', lambda w, t, r: self._update_tags())
 
318
        self.treeview = TreeView(self.branch, self.start_revs, self.maxnum,
 
319
            self.compact_view)
273
320
 
274
321
        for col in ["revno", "date"]:
275
322
            option = self.config.get_user_option(col + '-column-visible')
276
323
            if option is not None:
277
 
                self.treeview.set_property(col + '-column-visible', option == 'True')
 
324
                self.treeview.set_property(col + '-column-visible',
 
325
                    option == 'True')
278
326
            else:
279
327
                self.treeview.set_property(col + '-column-visible', False)
280
328
 
283
331
        align = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
284
332
        align.set_padding(5, 0, 0, 0)
285
333
        align.add(self.treeview)
 
334
        # user-configured size
 
335
        size = self._load_size('viz-graph-size')
 
336
        if size:
 
337
            width, height = size
 
338
            align.set_size_request(width, height)
 
339
        else:
 
340
            (width, height) = self.get_size()
 
341
            align.set_size_request(width, int(height / 2.5))
 
342
        self._save_size_on_destroy(align, 'viz-graph-size')
286
343
        align.show()
287
344
 
288
345
        return align
310
367
 
311
368
    def construct_bottom(self):
312
369
        """Construct the bottom half of the window."""
 
370
        if self.config.get_user_option('viz-wide-diffs') == 'True':
 
371
            self.diff_paned = gtk.VPaned()
 
372
        else:
 
373
            self.diff_paned = gtk.HPaned()
 
374
        (width, height) = self.get_size()
 
375
        self.diff_paned.set_size_request(20, 20) # shrinkable
 
376
 
313
377
        from bzrlib.plugins.gtk.revisionview import RevisionView
314
378
        self.revisionview = RevisionView(branch=self.branch)
315
 
        (width, height) = self.get_size()
316
 
        self.revisionview.set_size_request(width, int(height / 2.5))
 
379
        self.revisionview.set_size_request(width/3, int(height / 2.5))
 
380
        # user-configured size
 
381
        size = self._load_size('viz-revisionview-size')
 
382
        if size:
 
383
            width, height = size
 
384
            self.revisionview.set_size_request(width, height)
 
385
        self._save_size_on_destroy(self.revisionview, 'viz-revisionview-size')
317
386
        self.revisionview.show()
318
387
        self.revisionview.set_show_callback(self._show_clicked_cb)
319
388
        self.revisionview.connect('notify::revision', self._go_clicked_cb)
320
 
        self.treeview.connect('tag-added', lambda w, t, r: self.revisionview.update_tags())
321
 
        return self.revisionview
 
389
        self.treeview.connect('tag-added',
 
390
            lambda w, t, r: self.revisionview.update_tags())
 
391
        self.treeview.connect('revision-selected',
 
392
                self._treeselection_changed_cb)
 
393
        self.treeview.connect('revision-activated',
 
394
                self._tree_revision_activated)
 
395
        self.diff_paned.pack1(self.revisionview)
 
396
 
 
397
        from bzrlib.plugins.gtk.diff import DiffWidget
 
398
        self.diff = DiffWidget()
 
399
        self.diff_paned.pack2(self.diff)
 
400
 
 
401
        self.diff_paned.show_all()
 
402
        if self.config.get_user_option('viz-show-diffs') != 'True':
 
403
            self.diff.hide()
 
404
 
 
405
        return self.diff_paned
322
406
 
323
407
    def _tag_selected_cb(self, menuitem, revid):
324
408
        self.treeview.set_revision_id(revid)
329
413
        parents  = self.treeview.get_parents()
330
414
        children = self.treeview.get_children()
331
415
 
332
 
        if revision and revision != NULL_REVISION:
 
416
        if revision and revision.revision_id != NULL_REVISION:
 
417
            self.revision_menu.set_revision_ids([revision.revision_id])
333
418
            prev_menu = gtk.Menu()
334
419
            if len(parents) > 0:
335
420
                self.prev_rev_action.set_sensitive(True)
337
422
                    if parent_id and parent_id != NULL_REVISION:
338
423
                        parent = self.branch.repository.get_revision(parent_id)
339
424
                        try:
340
 
                            str = ' (' + parent.properties['branch-nick'] + ')'
 
425
                            str = ' (%s)' % parent.properties['branch-nick']
341
426
                        except KeyError:
342
427
                            str = ""
343
428
 
349
434
                self.prev_rev_action.set_sensitive(False)
350
435
                prev_menu.hide()
351
436
 
352
 
            self.prev_button.set_menu(prev_menu)
 
437
            if getattr(self.prev_button, 'set_menu', None) is not None:
 
438
                self.prev_button.set_menu(prev_menu)
353
439
 
354
440
            next_menu = gtk.Menu()
355
441
            if len(children) > 0:
357
443
                for child_id in children:
358
444
                    child = self.branch.repository.get_revision(child_id)
359
445
                    try:
360
 
                        str = ' (' + child.properties['branch-nick'] + ')'
 
446
                        str = ' (%s)' % child.properties['branch-nick']
361
447
                    except KeyError:
362
448
                        str = ""
363
449
 
369
455
                self.next_rev_action.set_sensitive(False)
370
456
                next_menu.hide()
371
457
 
372
 
            self.next_button.set_menu(next_menu)
 
458
            if getattr(self.next_button, 'set_menu', None) is not None:
 
459
                self.next_button.set_menu(next_menu)
373
460
 
374
461
            self.revisionview.set_revision(revision)
375
462
            self.revisionview.set_children(children)
376
 
    
 
463
            self.update_diff_panel(revision, parents)
 
464
 
377
465
    def _tree_revision_activated(self, widget, path, col):
378
466
        # TODO: more than one parent
379
467
        """Callback for when a treeview row gets activated."""
381
469
        parents  = self.treeview.get_parents()
382
470
 
383
471
        if len(parents) == 0:
384
 
            parent_id = None
 
472
            parent_id = NULL_REVISION
385
473
        else:
386
474
            parent_id = parents[0]
387
475
 
388
476
        self.show_diff(revision.revision_id, parent_id)
389
477
        self.treeview.grab_focus()
390
 
        
391
 
    def _menu_diff_cb(self,w):
392
 
        (path, focus) = self.treeview.treeview.get_cursor()
393
 
        revid = self.treeview.model[path][treemodel.REVID]
394
 
        
395
 
        parentids = self.branch.repository.revision_parents(revid)
396
 
 
397
 
        if len(parentids) == 0:
398
 
            parentid = NULL_REVISION
399
 
        else:
400
 
            parentid = parentids[0]
401
 
        
402
 
        self.show_diff(revid,parentid)    
403
478
 
404
479
    def _back_clicked_cb(self, *args):
405
480
        """Callback for when the back button is clicked."""
406
481
        self.treeview.back()
407
 
        
 
482
 
408
483
    def _fwd_clicked_cb(self, *args):
409
484
        """Callback for when the forward button is clicked."""
410
485
        self.treeview.forward()
419
494
        self.show_diff(revid, parentid)
420
495
        self.treeview.grab_focus()
421
496
 
422
 
    def _compare_with_cb(self,w):
423
 
        """Callback for revision 'compare with' menu. Will show a small
424
 
            dialog with branch revisions to compare with selected revision in TreeView"""
425
 
        
426
 
        from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
427
 
        
428
 
        rb = RevisionBrowser(self.branch,self)
429
 
        ret = rb.run()
430
 
        
431
 
        if ret == gtk.RESPONSE_OK:          
432
 
            (path, focus) = self.treeview.treeview.get_cursor()
433
 
            revid = self.treeview.model[path][treemodel.REVID]
434
 
            self.show_diff(revid, rb.selected_revid)
435
 
            
436
 
        rb.destroy()
437
 
            
438
497
    def _set_revision_cb(self, w, revision_id):
439
498
        self.treeview.set_revision_id(revision_id)
440
499
 
450
509
        self.treeview.set_property('compact', self.compact_view)
451
510
        self.treeview.refresh()
452
511
 
453
 
    def _tag_revision_cb(self, w):
454
 
        try:
455
 
            self.treeview.set_sensitive(False)
456
 
            dialog = AddTagDialog(self.branch.repository, self.treeview.get_revision().revision_id, self.branch)
457
 
            response = dialog.run()
458
 
            if response != gtk.RESPONSE_NONE:
459
 
                dialog.hide()
460
 
            
461
 
                if response == gtk.RESPONSE_OK:
462
 
                    self.treeview.add_tag(dialog.tagname, dialog._revid)
463
 
                
464
 
                dialog.destroy()
465
 
 
466
 
        finally:
467
 
            self.treeview.set_sensitive(True)
468
 
 
469
512
    def _branch_index_cb(self, w):
470
513
        from bzrlib.plugins.search import index as _mod_index
471
514
        _mod_index.index_url(self.branch.base)
472
515
 
 
516
    def _branch_search_cb(self, w):
 
517
        from bzrlib.plugins.search import (
 
518
            index as _mod_index,
 
519
            errors as search_errors,
 
520
            )
 
521
        from bzrlib.plugins.gtk.search import SearchDialog
 
522
 
 
523
        try:
 
524
            index = _mod_index.open_index_url(self.branch.base)
 
525
        except search_errors.NoSearchIndex:
 
526
            dialog = gtk.MessageDialog(self, type=gtk.MESSAGE_QUESTION, 
 
527
                buttons=gtk.BUTTONS_OK_CANCEL, 
 
528
                message_format="This branch has not been indexed yet. "
 
529
                               "Index now?")
 
530
            if dialog.run() == gtk.RESPONSE_OK:
 
531
                dialog.destroy()
 
532
                index = _mod_index.index_url(self.branch.base)
 
533
            else:
 
534
                dialog.destroy()
 
535
                return
 
536
 
 
537
        dialog = SearchDialog(index)
 
538
 
 
539
        if dialog.run() == gtk.RESPONSE_OK:
 
540
            self.set_revision(dialog.get_revision())
 
541
 
 
542
        dialog.destroy()
 
543
 
473
544
    def _about_dialog_cb(self, w):
474
545
        from bzrlib.plugins.gtk.about import AboutDialog
475
 
 
476
546
        AboutDialog().run()
477
547
 
478
548
    def _col_visibility_changed(self, col, property):
481
551
 
482
552
    def _toolbar_visibility_changed(self, col):
483
553
        if col.get_active():
484
 
            self.toolbar.show() 
 
554
            self.toolbar.show()
485
555
        else:
486
556
            self.toolbar.hide()
487
 
 
488
 
    def _show_about_cb(self, w):
489
 
        dialog = AboutDialog()
490
 
        dialog.connect('response', lambda d,r: d.destroy())
491
 
        dialog.run()
 
557
        self.config.set_user_option('viz-toolbar-visible', col.get_active())
 
558
 
 
559
    def _vertical_layout(self, col):
 
560
        """Toggle the layout vertical/horizontal"""
 
561
        self.config.set_user_option('viz-vertical', str(col.get_active()))
 
562
 
 
563
        old = self.paned
 
564
        self.vbox.remove(old)
 
565
        self.vbox.pack_start(self.construct_paned(), expand=True, fill=True)
 
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)
492
610
 
493
611
    def _refresh_clicked(self, w):
494
612
        self.treeview.refresh()
498
616
 
499
617
        if self.branch.supports_tags():
500
618
            tags = self.branch.tags.get_tag_dict().items()
501
 
            tags.sort()
502
 
            tags.reverse()
 
619
            tags.sort(reverse=True)
503
620
            for tag, revid in tags:
504
621
                tag_image = gtk.Image()
505
622
                tag_image.set_from_file(icon_path('tag-16.png'))
506
623
                tag_item = gtk.ImageMenuItem(tag.replace('_', '__'))
507
624
                tag_item.set_image(tag_image)
508
625
                tag_item.connect('activate', self._tag_selected_cb, revid)
 
626
                tag_item.set_sensitive(self.treeview.has_revision_id(revid))
509
627
                menu.add(tag_item)
510
628
            self.go_menu_tags.set_submenu(menu)
511
629
 
515
633
 
516
634
        self.go_menu_tags.show_all()
517
635
 
518
 
    def show_diff(self, revid=None, parentid=None):
 
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):
519
649
        """Open a new window to show a diff between the given revisions."""
520
650
        from bzrlib.plugins.gtk.diff import DiffWindow
521
651
        window = DiffWindow(parent=self)
522
652
 
523
 
        if parentid is None:
524
 
            parentid = NULL_REVISION
525
 
 
526
653
        rev_tree    = self.branch.repository.revision_tree(revid)
527
654
        parent_tree = self.branch.repository.revision_tree(parentid)
528
655
 
529
 
        description = revid + " - " + self.branch.nick
 
656
        description = revid + " - " + self.branch._get_nick(local=True)
530
657
        window.set_diff(description, rev_tree, parent_tree)
531
658
        window.show()
532
659
 
533
 
 
 
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()