16
from bzrlib.plugins.gtk.window import Window
17
16
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.branchview import TreeView, treemodel
20
from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
21
from bzrlib.plugins.gtk.window import Window
22
23
from bzrlib.config import BranchConfig, GlobalConfig
23
24
from bzrlib.revision import Revision, NULL_REVISION
59
62
monitor = screen.get_monitor_geometry(0)
60
63
width = int(monitor.width * 0.75)
61
64
height = int(monitor.height * 0.75)
65
# user-configured window size
66
size = self._load_size('viz-window-size')
62
69
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')
65
74
icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
105
114
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)
115
self.paned.pack1(self.construct_top(), resize=False, shrink=True)
116
self.paned.pack2(self.construct_bottom(), resize=True, shrink=False)
108
117
self.paned.show()
110
vbox.pack_start(self.construct_menubar(), expand=False, fill=True)
111
vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
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)
113
124
vbox.pack_start(self.paned, expand=True, fill=True)
114
125
vbox.set_focus_child(self.paned)
136
147
edit_menuitem = gtk.MenuItem("_Edit")
137
148
edit_menuitem.set_submenu(edit_menu)
139
edit_menu_find = gtk.ImageMenuItem(gtk.STOCK_FIND)
141
150
edit_menu_branchopts = gtk.MenuItem("Branch Settings")
142
151
edit_menu_branchopts.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
144
153
edit_menu_globopts = gtk.MenuItem("Global Settings")
145
154
edit_menu_globopts.connect('activate', lambda x: PreferencesWindow().show())
147
edit_menu.add(edit_menu_find)
148
156
edit_menu.add(edit_menu_branchopts)
149
157
edit_menu.add(edit_menu_globopts)
161
169
view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
162
170
view_menu_toolbar.set_active(True)
171
if self.config.get_user_option('viz-toolbar-visible') == 'False':
172
view_menu_toolbar.set_active(False)
163
174
view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
165
176
view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
166
177
view_menu_compact.set_active(self.compact_view)
167
178
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)
169
192
view_menu.add(view_menu_toolbar)
170
193
view_menu.add(view_menu_compact)
194
view_menu.add(view_menu_diffs)
195
view_menu.add(view_menu_wide_diffs)
171
196
view_menu.add(gtk.SeparatorMenuItem())
173
198
self.mnu_show_revno_column = gtk.CheckMenuItem("Show Revision _Number Column")
203
228
go_menu.add(gtk.SeparatorMenuItem())
204
229
go_menu.add(self.go_menu_tags)
206
revision_menu = gtk.Menu()
231
self.revision_menu = RevisionMenu(self.branch.repository, [], self.branch, parent=self)
207
232
revision_menuitem = gtk.MenuItem("_Revision")
208
revision_menuitem.set_submenu(revision_menu)
210
revision_menu_diff = gtk.MenuItem("View Changes")
211
revision_menu_diff.connect('activate',
214
revision_menu_compare = gtk.MenuItem("Compare with...")
215
revision_menu_compare.connect('activate',
216
self._compare_with_cb)
218
revision_menu_tag = gtk.MenuItem("Tag Revision")
219
revision_menu_tag.connect('activate', self._tag_revision_cb)
221
revision_menu.add(revision_menu_tag)
222
revision_menu.add(revision_menu_diff)
223
revision_menu.add(revision_menu_compare)
233
revision_menuitem.set_submenu(self.revision_menu)
225
235
branch_menu = gtk.Menu()
226
236
branch_menuitem = gtk.MenuItem("_Branch")
234
244
except ImportError:
235
245
mutter("Didn't find search plugin")
247
branch_menu.add(gtk.SeparatorMenuItem())
237
249
branch_index_menuitem = gtk.MenuItem("_Index")
238
250
branch_index_menuitem.connect('activate', self._branch_index_cb)
239
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)
241
257
help_menu = gtk.Menu()
242
258
help_menuitem = gtk.MenuItem("_Help")
243
259
help_menuitem.set_submenu(help_menu)
283
299
align = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
284
300
align.set_padding(5, 0, 0, 0)
285
301
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')
311
336
def construct_bottom(self):
312
337
"""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
313
345
from bzrlib.plugins.gtk.revisionview import RevisionView
314
346
self.revisionview = RevisionView(branch=self.branch)
315
(width, height) = self.get_size()
316
self.revisionview.set_size_request(width, int(height / 2.5))
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')
317
354
self.revisionview.show()
318
355
self.revisionview.set_show_callback(self._show_clicked_cb)
319
356
self.revisionview.connect('notify::revision', self._go_clicked_cb)
320
357
self.treeview.connect('tag-added', lambda w, t, r: self.revisionview.update_tags())
321
return self.revisionview
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
323
370
def _tag_selected_cb(self, menuitem, revid):
324
371
self.treeview.set_revision_id(revid)
374
423
self.revisionview.set_revision(revision)
375
424
self.revisionview.set_children(children)
426
self.update_diff_panel(revision, parents)
377
428
def _tree_revision_activated(self, widget, path, col):
378
429
# TODO: more than one parent
379
430
"""Callback for when a treeview row gets activated."""
388
439
self.show_diff(revision.revision_id, parent_id)
389
440
self.treeview.grab_focus()
391
def _menu_diff_cb(self,w):
392
(path, focus) = self.treeview.treeview.get_cursor()
393
revid = self.treeview.model[path][treemodel.REVID]
395
parentids = self.branch.repository.revision_parents(revid)
397
if len(parentids) == 0:
398
parentid = NULL_REVISION
400
parentid = parentids[0]
402
self.show_diff(revid,parentid)
404
442
def _back_clicked_cb(self, *args):
405
443
"""Callback for when the back button is clicked."""
406
444
self.treeview.back()
419
457
self.show_diff(revid, parentid)
420
458
self.treeview.grab_focus()
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"""
426
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
428
rb = RevisionBrowser(self.branch,self)
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)
438
460
def _set_revision_cb(self, w, revision_id):
439
461
self.treeview.set_revision_id(revision_id)
450
472
self.treeview.set_property('compact', self.compact_view)
451
473
self.treeview.refresh()
453
def _tag_revision_cb(self, w):
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:
461
if response == gtk.RESPONSE_OK:
462
self.treeview.add_tag(dialog.tagname, dialog._revid)
467
self.treeview.set_sensitive(True)
469
475
def _branch_index_cb(self, w):
470
476
from bzrlib.plugins.search import index as _mod_index
471
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
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())
473
505
def _about_dialog_cb(self, w):
474
506
from bzrlib.plugins.gtk.about import AboutDialog
482
514
def _toolbar_visibility_changed(self, col):
483
515
if col.get_active():
486
518
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')
488
549
def _show_about_cb(self, w):
489
550
dialog = AboutDialog()
516
577
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)
518
607
def show_diff(self, revid=None, parentid=None):
519
608
"""Open a new window to show a diff between the given revisions."""
520
609
from bzrlib.plugins.gtk.diff import DiffWindow
530
619
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)