16
from bzrlib.plugins.gtk.window import Window
16
17
from bzrlib.plugins.gtk import icon_path
17
from bzrlib.plugins.gtk.branchview import TreeView, treemodel
18
18
from bzrlib.plugins.gtk.tags import AddTagDialog
19
19
from bzrlib.plugins.gtk.preferences import PreferencesWindow
20
from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
21
from bzrlib.plugins.gtk.window import Window
23
from bzrlib.config import BranchConfig, GlobalConfig
20
from bzrlib.plugins.gtk.branchview import TreeView, treemodel
24
21
from bzrlib.revision import Revision, NULL_REVISION
25
from bzrlib.trace import mutter
22
from bzrlib.config import BranchConfig
23
from bzrlib.config import GlobalConfig
27
25
class BranchWindow(Window):
62
58
monitor = screen.get_monitor_geometry(0)
63
59
width = int(monitor.width * 0.75)
64
60
height = int(monitor.height * 0.75)
65
# user-configured window size
66
size = self._load_size('viz-window-size')
69
61
self.set_default_size(width, height)
70
self.set_size_request(width/3, height/3)
71
self.connect("size-allocate", self._on_size_allocate, 'viz-window-size')
74
64
icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
114
104
self.paned = gtk.VPaned()
115
self.paned.pack1(self.construct_top(), resize=False, shrink=True)
116
self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
105
self.paned.pack1(self.construct_top(), resize=True, shrink=False)
106
self.paned.pack2(self.construct_bottom(), resize=False, shrink=True)
117
107
self.paned.show()
119
nav = self.construct_navigation()
120
menubar = self.construct_menubar()
121
vbox.pack_start(menubar, expand=False, fill=True)
122
vbox.pack_start(nav, expand=False, fill=True)
109
vbox.pack_start(self.construct_menubar(), expand=False, fill=True)
110
vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
124
112
vbox.pack_start(self.paned, expand=True, fill=True)
125
113
vbox.set_focus_child(self.paned)
147
135
edit_menuitem = gtk.MenuItem("_Edit")
148
136
edit_menuitem.set_submenu(edit_menu)
138
edit_menu_find = gtk.ImageMenuItem(gtk.STOCK_FIND)
150
140
edit_menu_branchopts = gtk.MenuItem("Branch Settings")
151
141
edit_menu_branchopts.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
153
143
edit_menu_globopts = gtk.MenuItem("Global Settings")
154
144
edit_menu_globopts.connect('activate', lambda x: PreferencesWindow().show())
146
edit_menu.add(edit_menu_find)
156
147
edit_menu.add(edit_menu_branchopts)
157
148
edit_menu.add(edit_menu_globopts)
169
160
view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
170
161
view_menu_toolbar.set_active(True)
171
if self.config.get_user_option('viz-toolbar-visible') == 'False':
172
view_menu_toolbar.set_active(False)
174
162
view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
176
164
view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
177
165
view_menu_compact.set_active(self.compact_view)
178
166
view_menu_compact.connect('activate', self._brokenlines_toggled_cb)
180
view_menu_diffs = gtk.CheckMenuItem("Show Diffs")
181
view_menu_diffs.set_active(False)
182
if self.config.get_user_option('viz-show-diffs') == 'True':
183
view_menu_diffs.set_active(True)
184
view_menu_diffs.connect('toggled', self._diff_visibility_changed)
186
view_menu_wide_diffs = gtk.CheckMenuItem("Wide Diffs")
187
view_menu_wide_diffs.set_active(False)
188
if self.config.get_user_option('viz-wide-diffs') == 'True':
189
view_menu_wide_diffs.set_active(True)
190
view_menu_wide_diffs.connect('toggled', self._diff_placement_changed)
192
168
view_menu.add(view_menu_toolbar)
193
169
view_menu.add(view_menu_compact)
194
view_menu.add(view_menu_diffs)
195
view_menu.add(view_menu_wide_diffs)
196
170
view_menu.add(gtk.SeparatorMenuItem())
198
172
self.mnu_show_revno_column = gtk.CheckMenuItem("Show Revision _Number Column")
228
202
go_menu.add(gtk.SeparatorMenuItem())
229
203
go_menu.add(self.go_menu_tags)
231
self.revision_menu = RevisionMenu(self.branch.repository, [], self.branch, parent=self)
205
revision_menu = gtk.Menu()
232
206
revision_menuitem = gtk.MenuItem("_Revision")
233
revision_menuitem.set_submenu(self.revision_menu)
207
revision_menuitem.set_submenu(revision_menu)
209
revision_menu_diff = gtk.MenuItem("View Changes")
210
revision_menu_diff.connect('activate',
213
revision_menu_compare = gtk.MenuItem("Compare with...")
214
revision_menu_compare.connect('activate',
215
self._compare_with_cb)
217
revision_menu_tag = gtk.MenuItem("Tag Revision")
218
revision_menu_tag.connect('activate', self._tag_revision_cb)
220
revision_menu.add(revision_menu_tag)
221
revision_menu.add(revision_menu_diff)
222
revision_menu.add(revision_menu_compare)
235
224
branch_menu = gtk.Menu()
236
225
branch_menuitem = gtk.MenuItem("_Branch")
239
228
branch_menu.add(gtk.MenuItem("Pu_ll Revisions"))
240
229
branch_menu.add(gtk.MenuItem("Pu_sh Revisions"))
243
from bzrlib.plugins import search
245
mutter("Didn't find search plugin")
247
branch_menu.add(gtk.SeparatorMenuItem())
249
branch_index_menuitem = gtk.MenuItem("_Index")
250
branch_index_menuitem.connect('activate', self._branch_index_cb)
251
branch_menu.add(branch_index_menuitem)
253
branch_search_menuitem = gtk.MenuItem("_Search")
254
branch_search_menuitem.connect('activate', self._branch_search_cb)
255
branch_menu.add(branch_search_menuitem)
257
231
help_menu = gtk.Menu()
258
232
help_menuitem = gtk.MenuItem("_Help")
259
233
help_menuitem.set_submenu(help_menu)
299
273
align = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
300
274
align.set_padding(5, 0, 0, 0)
301
275
align.add(self.treeview)
302
# user-configured size
303
size = self._load_size('viz-graph-size')
306
align.set_size_request(width, height)
308
(width, height) = self.get_size()
309
align.set_size_request(width, int(height / 2.5))
310
align.connect('size-allocate', self._on_size_allocate, 'viz-graph-size')
336
301
def construct_bottom(self):
337
302
"""Construct the bottom half of the window."""
338
if self.config.get_user_option('viz-wide-diffs') == 'True':
339
self.diff_paned = gtk.VPaned()
341
self.diff_paned = gtk.HPaned()
342
(width, height) = self.get_size()
343
self.diff_paned.set_size_request(20, 20) # shrinkable
345
303
from bzrlib.plugins.gtk.revisionview import RevisionView
346
304
self.revisionview = RevisionView(branch=self.branch)
347
self.revisionview.set_size_request(width/3, int(height / 2.5))
348
# user-configured size
349
size = self._load_size('viz-revisionview-size')
352
self.revisionview.set_size_request(width, height)
353
self.revisionview.connect('size-allocate', self._on_size_allocate, 'viz-revisionview-size')
305
(width, height) = self.get_size()
306
self.revisionview.set_size_request(width, int(height / 2.5))
354
307
self.revisionview.show()
355
308
self.revisionview.set_show_callback(self._show_clicked_cb)
356
309
self.revisionview.connect('notify::revision', self._go_clicked_cb)
357
310
self.treeview.connect('tag-added', lambda w, t, r: self.revisionview.update_tags())
358
self.diff_paned.pack1(self.revisionview)
360
from bzrlib.plugins.gtk.diff import DiffWidget
361
self.diff = DiffWidget()
362
self.diff_paned.pack2(self.diff)
364
self.diff_paned.show_all()
365
if self.config.get_user_option('viz-show-diffs') != 'True':
368
return self.diff_paned
311
return self.revisionview
370
313
def _tag_selected_cb(self, menuitem, revid):
371
314
self.treeview.set_revision_id(revid)
423
364
self.revisionview.set_revision(revision)
424
365
self.revisionview.set_children(children)
426
self.update_diff_panel(revision, parents)
428
367
def _tree_revision_activated(self, widget, path, col):
429
368
# TODO: more than one parent
430
369
"""Callback for when a treeview row gets activated."""
439
378
self.show_diff(revision.revision_id, parent_id)
440
379
self.treeview.grab_focus()
381
def _menu_diff_cb(self,w):
382
(path, focus) = self.treeview.treeview.get_cursor()
383
revid = self.treeview.model[path][treemodel.REVID]
385
parentids = self.branch.repository.revision_parents(revid)
387
if len(parentids) == 0:
388
parentid = NULL_REVISION
390
parentid = parentids[0]
392
self.show_diff(revid,parentid)
442
394
def _back_clicked_cb(self, *args):
443
395
"""Callback for when the back button is clicked."""
444
396
self.treeview.back()
457
409
self.show_diff(revid, parentid)
458
410
self.treeview.grab_focus()
412
def _compare_with_cb(self,w):
413
"""Callback for revision 'compare with' menu. Will show a small
414
dialog with branch revisions to compare with selected revision in TreeView"""
416
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
418
rb = RevisionBrowser(self.branch,self)
421
if ret == gtk.RESPONSE_OK:
422
(path, focus) = self.treeview.treeview.get_cursor()
423
revid = self.treeview.model[path][treemodel.REVID]
424
self.show_diff(revid, rb.selected_revid)
460
428
def _set_revision_cb(self, w, revision_id):
461
429
self.treeview.set_revision_id(revision_id)
472
440
self.treeview.set_property('compact', self.compact_view)
473
441
self.treeview.refresh()
475
def _branch_index_cb(self, w):
476
from bzrlib.plugins.search import index as _mod_index
477
_mod_index.index_url(self.branch.base)
479
def _branch_search_cb(self, w):
480
from bzrlib.plugins.search import index as _mod_index
481
from bzrlib.plugins.gtk.search import SearchDialog
482
from bzrlib.plugins.search import errors as search_errors
443
def _tag_revision_cb(self, w):
485
index = _mod_index.open_index_url(self.branch.base)
486
except search_errors.NoSearchIndex:
487
dialog = gtk.MessageDialog(self, type=gtk.MESSAGE_QUESTION,
488
buttons=gtk.BUTTONS_OK_CANCEL,
489
message_format="This branch has not been indexed yet. "
491
if dialog.run() == gtk.RESPONSE_OK:
493
index = _mod_index.index_url(self.branch.base)
498
dialog = SearchDialog(index)
500
if dialog.run() == gtk.RESPONSE_OK:
501
self.set_revision(dialog.get_revision())
445
self.treeview.set_sensitive(False)
446
dialog = AddTagDialog(self.branch.repository, self.treeview.get_revision().revision_id, self.branch)
447
response = dialog.run()
448
if response != gtk.RESPONSE_NONE:
451
if response == gtk.RESPONSE_OK:
452
self.treeview.add_tag(dialog.tagname, dialog._revid)
457
self.treeview.set_sensitive(True)
505
459
def _about_dialog_cb(self, w):
506
460
from bzrlib.plugins.gtk.about import AboutDialog
514
468
def _toolbar_visibility_changed(self, col):
515
469
if col.get_active():
518
472
self.toolbar.hide()
519
self.config.set_user_option('viz-toolbar-visible', col.get_active())
521
def _make_diff_nonzero_size(self):
522
"""make sure the diff isn't zero-width or zero-height"""
523
alloc = self.diff.get_allocation()
524
if (alloc.width < 10) or (alloc.height < 10):
525
width, height = self.get_size()
526
self.revisionview.set_size_request(width/3, int(height / 2.5))
528
def _diff_visibility_changed(self, col):
529
"""Hide or show the diff panel."""
532
self._make_diff_nonzero_size()
535
self.config.set_user_option('viz-show-diffs', str(col.get_active()))
536
self.update_diff_panel()
538
def _diff_placement_changed(self, col):
539
"""Toggle the diff panel's position."""
540
self.config.set_user_option('viz-wide-diffs', str(col.get_active()))
542
old = self.paned.get_child2()
543
self.paned.remove(old)
544
self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
545
self._make_diff_nonzero_size()
547
self.treeview.emit('revision-selected')
549
474
def _show_about_cb(self, w):
550
475
dialog = AboutDialog()
577
502
self.go_menu_tags.show_all()
579
def _load_size(self, name):
580
"""Read and parse 'name' from self.config.
581
The value is a string, formatted as WIDTHxHEIGHT
582
Returns None, or (width, height)
584
size = self.config.get_user_option(name)
586
width, height = [int(num) for num in size.split('x')]
587
# avoid writing config every time we start
588
self._sizes[name] = (width, height)
592
def _on_size_allocate(self, widget, allocation, name):
593
"""When window has been resized, save the new size."""
595
if name in self._sizes:
596
width, height = self._sizes[name]
598
size_changed = (width != allocation.width) or \
599
(height != allocation.height)
602
width, height = allocation.width, allocation.height
603
self._sizes[name] = (width, height)
604
value = '%sx%s' % (width, height)
605
self.config.set_user_option(name, value)
607
504
def show_diff(self, revid=None, parentid=None):
608
505
"""Open a new window to show a diff between the given revisions."""
609
506
from bzrlib.plugins.gtk.diff import DiffWindow
619
516
window.set_diff(description, rev_tree, parent_tree)
622
def update_diff_panel(self, revision=None, parents=None):
623
"""Show the current revision in the diff panel."""
624
if self.config.get_user_option('viz-show-diffs') != 'True':
627
if not revision: # default to selected row
628
revision = self.treeview.get_revision()
629
if (not revision) or (revision == NULL_REVISION):
632
if not parents: # default to selected row's parents
633
parents = self.treeview.get_parents()
634
if len(parents) == 0:
637
parent_id = parents[0]
639
rev_tree = self.branch.repository.revision_tree(revision.revision_id)
640
parent_tree = self.branch.repository.revision_tree(parent_id)
642
self.diff.set_diff(rev_tree, parent_tree)