/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: Markus Korn
  • Date: 2009-03-05 16:50:39 UTC
  • mto: (635.2.4 trunk)
  • mto: This revision was merged to the branch mainline in revision 639.
  • Revision ID: thekorn@gmx.de-20090305165039-h6xh48wr9lwe1661
* register BranchSelectionBox() as a gobject type to fix (LP: #294396)

Show diffs side-by-side

added added

removed removed

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