1
# -*- coding: UTF-8 -*-
4
3
This module contains the code to manage the branch information window,
5
4
which contains both the revision graph and details panes.
8
__copyright__ = "Copyright © 2005 Canonical Ltd."
7
__copyright__ = "Copyright (c) 2005 Canonical Ltd."
9
8
__author__ = "Scott James Remnant <scott@ubuntu.com>"
16
13
from bzrlib.plugins.gtk import icon_path
17
from bzrlib.plugins.gtk.branchview import TreeView, treemodel
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
16
from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
21
17
from bzrlib.plugins.gtk.window import Window
23
from bzrlib.config import BranchConfig, GlobalConfig
24
from bzrlib.revision import Revision, NULL_REVISION
19
from bzrlib.config import GlobalConfig
20
from bzrlib.revision import NULL_REVISION
25
21
from bzrlib.trace import mutter
27
23
class BranchWindow(Window):
48
44
self.maxnum = maxnum
49
45
self.config = GlobalConfig()
51
self._sizes = {} # window and widget sizes
53
47
if self.config.get_user_option('viz-compact-view') == 'yes':
54
48
self.compact_view = True
56
50
self.compact_view = False
58
self.set_title(branch.nick + " - revision history")
52
self.set_title(branch._get_nick(local=True) + " - revision history")
60
54
# user-configured window size
61
55
size = self._load_size('viz-window-size')
69
63
height = int(monitor.height * 0.75)
70
64
self.set_default_size(width, height)
71
65
self.set_size_request(width/3, height/3)
72
self.connect("size-allocate", self._on_size_allocate, 'viz-window-size')
66
self._save_size_on_destroy(self, 'viz-window-size')
75
69
icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
82
76
self.accel_group = gtk.AccelGroup()
83
77
self.add_accel_group(self.accel_group)
85
gtk.Action.set_tool_item_type(gtk.MenuToolButton)
79
if getattr(gtk.Action, 'set_tool_item_type', None) is not None:
80
# Not available before PyGtk-2.10
81
gtk.Action.set_tool_item_type(gtk.MenuToolButton)
87
83
self.prev_rev_action = gtk.Action("prev-rev", "_Previous Revision", "Go to the previous revision", gtk.STOCK_GO_DOWN)
88
84
self.prev_rev_action.set_accel_path("<viz>/Go/Previous Revision")
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."""
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)
107
112
def set_revision(self, revid):
108
113
self.treeview.set_revision_id(revid)
125
130
vbox.pack_start(self.paned, expand=True, fill=True)
126
131
vbox.set_focus_child(self.paned)
133
self.treeview.connect('revision-selected',
134
self._treeselection_changed_cb)
135
self.treeview.connect('revision-activated',
136
self._tree_revision_activated)
138
self.treeview.connect('tag-added', lambda w, t, r: self._update_tags())
130
141
def construct_menubar(self):
131
142
menubar = gtk.MenuBar()
137
148
file_menu_close = gtk.ImageMenuItem(gtk.STOCK_CLOSE, self.accel_group)
138
149
file_menu_close.connect('activate', lambda x: self.destroy())
140
151
file_menu_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accel_group)
141
152
file_menu_quit.connect('activate', lambda x: gtk.main_quit())
143
154
if self._parent is not None:
144
155
file_menu.add(file_menu_close)
145
156
file_menu.add(file_menu_quit)
177
188
view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
178
189
view_menu_compact.set_active(self.compact_view)
179
190
view_menu_compact.connect('activate', self._brokenlines_toggled_cb)
181
192
view_menu_diffs = gtk.CheckMenuItem("Show Diffs")
182
193
view_menu_diffs.set_active(False)
183
194
if self.config.get_user_option('viz-show-diffs') == 'True':
184
195
view_menu_diffs.set_active(True)
185
196
view_menu_diffs.connect('toggled', self._diff_visibility_changed)
187
198
view_menu_wide_diffs = gtk.CheckMenuItem("Wide Diffs")
188
199
view_menu_wide_diffs.set_active(False)
189
200
if self.config.get_user_option('viz-wide-diffs') == 'True':
190
201
view_menu_wide_diffs.set_active(True)
191
202
view_menu_wide_diffs.connect('toggled', self._diff_placement_changed)
193
204
view_menu_wrap_diffs = gtk.CheckMenuItem("Wrap _Long Lines in Diffs")
194
205
view_menu_wrap_diffs.set_active(False)
195
206
if self.config.get_user_option('viz-wrap-diffs') == 'True':
196
207
view_menu_wrap_diffs.set_active(True)
197
208
view_menu_wrap_diffs.connect('toggled', self._diff_wrap_changed)
199
210
view_menu.add(view_menu_toolbar)
200
211
view_menu.add(view_menu_compact)
201
212
view_menu.add(gtk.SeparatorMenuItem())
222
233
go_menu.set_accel_group(self.accel_group)
223
234
go_menuitem = gtk.MenuItem("_Go")
224
235
go_menuitem.set_submenu(go_menu)
226
237
go_menu_next = self.next_rev_action.create_menu_item()
227
238
go_menu_prev = self.prev_rev_action.create_menu_item()
230
241
tag_image.set_from_file(icon_path("tag-16.png"))
231
242
self.go_menu_tags = gtk.ImageMenuItem("_Tags")
232
243
self.go_menu_tags.set_image(tag_image)
244
self.treeview.connect('refreshed', lambda w: self._update_tags())
235
246
go_menu.add(go_menu_next)
236
247
go_menu.add(go_menu_prev)
290
301
self.treeview = TreeView(self.branch, self.start_revs, self.maxnum, self.compact_view)
292
self.treeview.connect('revision-selected',
293
self._treeselection_changed_cb)
294
self.treeview.connect('revision-activated',
295
self._tree_revision_activated)
297
self.treeview.connect('tag-added', lambda w, t, r: self._update_tags())
299
303
for col in ["revno", "date"]:
300
304
option = self.config.get_user_option(col + '-column-visible')
301
305
if option is not None:
317
321
(width, height) = self.get_size()
318
322
align.set_size_request(width, int(height / 2.5))
319
align.connect('size-allocate', self._on_size_allocate, 'viz-graph-size')
323
self._save_size_on_destroy(align, 'viz-graph-size')
360
364
width, height = size
361
365
self.revisionview.set_size_request(width, height)
362
self.revisionview.connect('size-allocate', self._on_size_allocate, 'viz-revisionview-size')
366
self._save_size_on_destroy(self.revisionview, 'viz-revisionview-size')
363
367
self.revisionview.show()
364
368
self.revisionview.set_show_callback(self._show_clicked_cb)
365
369
self.revisionview.connect('notify::revision', self._go_clicked_cb)
407
411
self.prev_rev_action.set_sensitive(False)
410
self.prev_button.set_menu(prev_menu)
414
if getattr(self.prev_button, 'set_menu', None) is not None:
415
self.prev_button.set_menu(prev_menu)
412
417
next_menu = gtk.Menu()
413
418
if len(children) > 0:
427
432
self.next_rev_action.set_sensitive(False)
430
self.next_button.set_menu(next_menu)
435
if getattr(self.next_button, 'set_menu', None) is not None:
436
self.next_button.set_menu(next_menu)
432
438
self.revisionview.set_revision(revision)
433
439
self.revisionview.set_children(children)
440
446
parents = self.treeview.get_parents()
442
448
if len(parents) == 0:
449
parent_id = NULL_REVISION
445
451
parent_id = parents[0]
447
453
self.show_diff(revision.revision_id, parent_id)
448
454
self.treeview.grab_focus()
450
456
def _back_clicked_cb(self, *args):
451
457
"""Callback for when the back button is clicked."""
452
458
self.treeview.back()
454
460
def _fwd_clicked_cb(self, *args):
455
461
"""Callback for when the forward button is clicked."""
456
462
self.treeview.forward()
513
519
def _about_dialog_cb(self, w):
514
520
from bzrlib.plugins.gtk.about import AboutDialog
516
521
AboutDialog().run()
518
523
def _col_visibility_changed(self, col, property):
553
558
self._make_diff_nonzero_size()
555
560
self.treeview.emit('revision-selected')
557
562
def _diff_wrap_changed(self, widget):
558
563
"""Toggle word wrap in the diff widget."""
559
564
self.config.set_user_option('viz-wrap-diffs', widget.get_active())
560
565
self.diff._on_wraplines_toggled(widget)
562
def _show_about_cb(self, w):
563
dialog = AboutDialog()
564
dialog.connect('response', lambda d,r: d.destroy())
567
567
def _refresh_clicked(self, w):
568
568
self.treeview.refresh()
573
573
if self.branch.supports_tags():
574
574
tags = self.branch.tags.get_tag_dict().items()
575
tags.sort(reverse=True)
577
576
for tag, revid in tags:
578
577
tag_image = gtk.Image()
579
578
tag_image.set_from_file(icon_path('tag-16.png'))
580
579
tag_item = gtk.ImageMenuItem(tag.replace('_', '__'))
581
580
tag_item.set_image(tag_image)
582
581
tag_item.connect('activate', self._tag_selected_cb, revid)
582
tag_item.set_sensitive(self.treeview.has_revision_id(revid))
583
583
menu.add(tag_item)
584
584
self.go_menu_tags.set_submenu(menu)
599
599
width, height = [int(num) for num in size.split('x')]
600
600
# avoid writing config every time we start
601
self._sizes[name] = (width, height)
602
601
return width, height
605
def _on_size_allocate(self, widget, allocation, name):
606
"""When window has been resized, save the new size."""
608
if name in self._sizes:
609
width, height = self._sizes[name]
611
size_changed = (width != allocation.width) or \
612
(height != allocation.height)
615
width, height = allocation.width, allocation.height
616
self._sizes[name] = (width, height)
617
value = '%sx%s' % (width, height)
618
self.config.set_user_option(name, value)
620
def show_diff(self, revid=None, parentid=None):
604
def show_diff(self, revid=None, parentid=NULL_REVISION):
621
605
"""Open a new window to show a diff between the given revisions."""
622
606
from bzrlib.plugins.gtk.diff import DiffWindow
623
607
window = DiffWindow(parent=self)
626
parentid = NULL_REVISION
628
609
rev_tree = self.branch.repository.revision_tree(revid)
629
610
parent_tree = self.branch.repository.revision_tree(parentid)
631
description = revid + " - " + self.branch.nick
612
description = revid + " - " + self.branch._get_nick(local=True)
632
613
window.set_diff(description, rev_tree, parent_tree)
640
621
if not revision: # default to selected row
641
622
revision = self.treeview.get_revision()
642
if (not revision) or (revision == NULL_REVISION):
623
if revision == NULL_REVISION:
645
626
if not parents: # default to selected row's parents
646
627
parents = self.treeview.get_parents()
647
628
if len(parents) == 0:
629
parent_id = NULL_REVISION
650
631
parent_id = parents[0]