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
24
class BranchWindow(Window):
48
45
self.maxnum = maxnum
49
46
self.config = GlobalConfig()
51
self._sizes = {} # window and widget sizes
53
48
if self.config.get_user_option('viz-compact-view') == 'yes':
54
49
self.compact_view = True
56
51
self.compact_view = False
58
self.set_title(branch.nick + " - revision history")
53
self.set_title(branch._get_nick(local=True) + " - revision history")
60
55
# user-configured window size
61
56
size = self._load_size('viz-window-size')
69
64
height = int(monitor.height * 0.75)
70
65
self.set_default_size(width, height)
71
66
self.set_size_request(width/3, height/3)
72
self.connect("size-allocate", self._on_size_allocate, 'viz-window-size')
67
self._save_size_on_destroy(self, 'viz-window-size')
75
70
icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
82
77
self.accel_group = gtk.AccelGroup()
83
78
self.add_accel_group(self.accel_group)
85
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)
87
84
self.prev_rev_action = gtk.Action("prev-rev", "_Previous Revision", "Go to the previous revision", gtk.STOCK_GO_DOWN)
88
85
self.prev_rev_action.set_accel_path("<viz>/Go/Previous Revision")
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."""
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)
107
113
def set_revision(self, revid):
108
114
self.treeview.set_revision_id(revid)
125
131
vbox.pack_start(self.paned, expand=True, fill=True)
126
132
vbox.set_focus_child(self.paned)
134
self.treeview.connect('revision-selected',
135
self._treeselection_changed_cb)
136
self.treeview.connect('revision-activated',
137
self._tree_revision_activated)
139
self.treeview.connect('tag-added', lambda w, t, r: self._update_tags())
130
142
def construct_menubar(self):
131
143
menubar = gtk.MenuBar()
137
149
file_menu_close = gtk.ImageMenuItem(gtk.STOCK_CLOSE, self.accel_group)
138
150
file_menu_close.connect('activate', lambda x: self.destroy())
140
152
file_menu_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accel_group)
141
153
file_menu_quit.connect('activate', lambda x: gtk.main_quit())
143
155
if self._parent is not None:
144
156
file_menu.add(file_menu_close)
145
157
file_menu.add(file_menu_quit)
177
189
view_menu_compact = gtk.CheckMenuItem("Show Compact Graph")
178
190
view_menu_compact.set_active(self.compact_view)
179
191
view_menu_compact.connect('activate', self._brokenlines_toggled_cb)
181
193
view_menu_diffs = gtk.CheckMenuItem("Show Diffs")
182
194
view_menu_diffs.set_active(False)
183
195
if self.config.get_user_option('viz-show-diffs') == 'True':
184
196
view_menu_diffs.set_active(True)
185
197
view_menu_diffs.connect('toggled', self._diff_visibility_changed)
187
199
view_menu_wide_diffs = gtk.CheckMenuItem("Wide Diffs")
188
200
view_menu_wide_diffs.set_active(False)
189
201
if self.config.get_user_option('viz-wide-diffs') == 'True':
190
202
view_menu_wide_diffs.set_active(True)
191
203
view_menu_wide_diffs.connect('toggled', self._diff_placement_changed)
193
205
view_menu_wrap_diffs = gtk.CheckMenuItem("Wrap _Long Lines in Diffs")
194
206
view_menu_wrap_diffs.set_active(False)
195
207
if self.config.get_user_option('viz-wrap-diffs') == 'True':
196
208
view_menu_wrap_diffs.set_active(True)
197
209
view_menu_wrap_diffs.connect('toggled', self._diff_wrap_changed)
199
211
view_menu.add(view_menu_toolbar)
200
212
view_menu.add(view_menu_compact)
201
213
view_menu.add(gtk.SeparatorMenuItem())
222
234
go_menu.set_accel_group(self.accel_group)
223
235
go_menuitem = gtk.MenuItem("_Go")
224
236
go_menuitem.set_submenu(go_menu)
226
238
go_menu_next = self.next_rev_action.create_menu_item()
227
239
go_menu_prev = self.prev_rev_action.create_menu_item()
230
242
tag_image.set_from_file(icon_path("tag-16.png"))
231
243
self.go_menu_tags = gtk.ImageMenuItem("_Tags")
232
244
self.go_menu_tags.set_image(tag_image)
245
self.treeview.connect('refreshed', lambda w: self._update_tags())
235
247
go_menu.add(go_menu_next)
236
248
go_menu.add(go_menu_prev)
290
302
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
304
for col in ["revno", "date"]:
300
305
option = self.config.get_user_option(col + '-column-visible')
301
306
if option is not None:
317
322
(width, height) = self.get_size()
318
323
align.set_size_request(width, int(height / 2.5))
319
align.connect('size-allocate', self._on_size_allocate, 'viz-graph-size')
324
self._save_size_on_destroy(align, 'viz-graph-size')
360
365
width, height = size
361
366
self.revisionview.set_size_request(width, height)
362
self.revisionview.connect('size-allocate', self._on_size_allocate, 'viz-revisionview-size')
367
self._save_size_on_destroy(self.revisionview, 'viz-revisionview-size')
363
368
self.revisionview.show()
364
369
self.revisionview.set_show_callback(self._show_clicked_cb)
365
370
self.revisionview.connect('notify::revision', self._go_clicked_cb)
407
412
self.prev_rev_action.set_sensitive(False)
410
self.prev_button.set_menu(prev_menu)
415
if getattr(self.prev_button, 'set_menu', None) is not None:
416
self.prev_button.set_menu(prev_menu)
412
418
next_menu = gtk.Menu()
413
419
if len(children) > 0:
427
433
self.next_rev_action.set_sensitive(False)
430
self.next_button.set_menu(next_menu)
436
if getattr(self.next_button, 'set_menu', None) is not None:
437
self.next_button.set_menu(next_menu)
432
439
self.revisionview.set_revision(revision)
433
440
self.revisionview.set_children(children)
440
447
parents = self.treeview.get_parents()
442
449
if len(parents) == 0:
450
parent_id = NULL_REVISION
445
452
parent_id = parents[0]
447
454
self.show_diff(revision.revision_id, parent_id)
448
455
self.treeview.grab_focus()
450
457
def _back_clicked_cb(self, *args):
451
458
"""Callback for when the back button is clicked."""
452
459
self.treeview.back()
454
461
def _fwd_clicked_cb(self, *args):
455
462
"""Callback for when the forward button is clicked."""
456
463
self.treeview.forward()
513
520
def _about_dialog_cb(self, w):
514
521
from bzrlib.plugins.gtk.about import AboutDialog
516
522
AboutDialog().run()
518
524
def _col_visibility_changed(self, col, property):
553
559
self._make_diff_nonzero_size()
555
561
self.treeview.emit('revision-selected')
557
563
def _diff_wrap_changed(self, widget):
558
564
"""Toggle word wrap in the diff widget."""
559
565
self.config.set_user_option('viz-wrap-diffs', widget.get_active())
560
566
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
568
def _refresh_clicked(self, w):
568
569
self.treeview.refresh()
573
574
if self.branch.supports_tags():
574
575
tags = self.branch.tags.get_tag_dict().items()
576
tags.sort(reverse=True)
577
577
for tag, revid in tags:
578
578
tag_image = gtk.Image()
579
579
tag_image.set_from_file(icon_path('tag-16.png'))
580
580
tag_item = gtk.ImageMenuItem(tag.replace('_', '__'))
581
581
tag_item.set_image(tag_image)
582
582
tag_item.connect('activate', self._tag_selected_cb, revid)
583
tag_item.set_sensitive(self.treeview.has_revision_id(revid))
583
584
menu.add(tag_item)
584
585
self.go_menu_tags.set_submenu(menu)
599
600
width, height = [int(num) for num in size.split('x')]
600
601
# avoid writing config every time we start
601
self._sizes[name] = (width, height)
602
602
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):
605
def show_diff(self, revid=None, parentid=NULL_REVISION):
621
606
"""Open a new window to show a diff between the given revisions."""
622
607
from bzrlib.plugins.gtk.diff import DiffWindow
623
608
window = DiffWindow(parent=self)
626
parentid = NULL_REVISION
628
610
rev_tree = self.branch.repository.revision_tree(revid)
629
611
parent_tree = self.branch.repository.revision_tree(parentid)
631
description = revid + " - " + self.branch.nick
613
description = revid + " - " + self.branch._get_nick(local=True)
632
614
window.set_diff(description, rev_tree, parent_tree)
640
622
if not revision: # default to selected row
641
623
revision = self.treeview.get_revision()
642
if (not revision) or (revision == NULL_REVISION):
624
if revision == NULL_REVISION:
645
627
if not parents: # default to selected row's parents
646
628
parents = self.treeview.get_parents()
647
629
if len(parents) == 0:
630
parent_id = NULL_REVISION
650
632
parent_id = parents[0]