16
16
from bzrlib.plugins.gtk.window import Window
17
from bzrlib.plugins.gtk import icon_path
18
17
from bzrlib.plugins.gtk.tags import AddTagDialog
19
18
from bzrlib.plugins.gtk.preferences import PreferencesWindow
20
from bzrlib.plugins.gtk.branchview import TreeView, treemodel
22
from bzrlib.config import BranchConfig, GlobalConfig
23
from bzrlib.revision import Revision, NULL_REVISION
24
from bzrlib.trace import mutter
19
from bzrlib.revision import Revision
20
from bzrlib.config import BranchConfig
21
from bzrlib.config import GlobalConfig
22
from treeview import TreeView
23
from about import AboutDialog
26
25
class BranchWindow(Window):
30
29
for a particular branch.
33
def __init__(self, branch, start_revs, maxnum, parent=None):
32
def __init__(self, branch, start, maxnum, parent=None):
34
33
"""Create a new BranchWindow.
36
35
:param branch: Branch object for branch to show.
37
:param start_revs: Revision ids of top revisions.
36
:param start: Revision id of top revision.
38
37
:param maxnum: Maximum number of revisions to display,
68
67
gtk.accel_map_add_entry("<viz>/Go/Next Revision", gtk.keysyms.Up, gtk.gdk.MOD1_MASK)
69
68
gtk.accel_map_add_entry("<viz>/Go/Previous Revision", gtk.keysyms.Down, gtk.gdk.MOD1_MASK)
70
gtk.accel_map_add_entry("<viz>/View/Refresh", gtk.keysyms.F5, 0)
72
70
self.accel_group = gtk.AccelGroup()
73
71
self.add_accel_group(self.accel_group)
86
84
self.next_rev_action.connect("activate", self._fwd_clicked_cb)
87
85
self.next_rev_action.connect_accelerator()
89
self.refresh_action = gtk.Action("refresh", "_Refresh", "Refresh view", gtk.STOCK_REFRESH)
90
self.refresh_action.set_accel_path("<viz>/View/Refresh")
91
self.refresh_action.set_accel_group(self.accel_group)
92
self.refresh_action.connect("activate", self._refresh_clicked)
93
self.refresh_action.connect_accelerator()
97
89
def set_revision(self, revid):
110
102
vbox.pack_start(self.construct_menubar(), expand=False, fill=True)
111
103
vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
104
vbox.pack_start(self.construct_loading_msg(), expand=False, fill=True)
113
106
vbox.pack_start(self.paned, expand=True, fill=True)
114
107
vbox.set_focus_child(self.paned)
128
121
file_menu_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accel_group)
129
122
file_menu_quit.connect('activate', lambda x: gtk.main_quit())
131
if self._parent is not None:
132
file_menu.add(file_menu_close)
124
file_menu.add(file_menu_close)
133
125
file_menu.add(file_menu_quit)
135
127
edit_menu = gtk.Menu()
141
133
edit_menu_branchopts = gtk.MenuItem("Branch Settings")
142
134
edit_menu_branchopts.connect('activate', lambda x: PreferencesWindow(self.branch.get_config()).show())
144
edit_menu_globopts = gtk.MenuItem("Global Settings")
145
edit_menu_globopts.connect('activate', lambda x: PreferencesWindow().show())
136
edit_menu_prefs = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
137
edit_menu_prefs.connect('activate', lambda x: PreferencesWindow().show())
147
139
edit_menu.add(edit_menu_find)
148
140
edit_menu.add(edit_menu_branchopts)
149
edit_menu.add(edit_menu_globopts)
141
edit_menu.add(edit_menu_prefs)
151
143
view_menu = gtk.Menu()
152
144
view_menuitem = gtk.MenuItem("_View")
153
145
view_menuitem.set_submenu(view_menu)
155
view_menu_refresh = self.refresh_action.create_menu_item()
156
view_menu_refresh.connect('activate', self._refresh_clicked)
158
view_menu.add(view_menu_refresh)
159
view_menu.add(gtk.SeparatorMenuItem())
161
147
view_menu_toolbar = gtk.CheckMenuItem("Show Toolbar")
162
148
view_menu_toolbar.set_active(True)
163
149
view_menu_toolbar.connect('toggled', self._toolbar_visibility_changed)
170
156
view_menu.add(view_menu_compact)
171
157
view_menu.add(gtk.SeparatorMenuItem())
173
self.mnu_show_revno_column = gtk.CheckMenuItem("Show Revision _Number Column")
174
self.mnu_show_date_column = gtk.CheckMenuItem("Show _Date Column")
176
# Revision numbers are pointless if there are multiple branches
177
if len(self.start_revs) > 1:
178
self.mnu_show_revno_column.set_sensitive(False)
179
self.treeview.set_property('revno-column-visible', False)
181
for (col, name) in [(self.mnu_show_revno_column, "revno"),
182
(self.mnu_show_date_column, "date")]:
159
for (label, name) in [("Revision _Number", "revno"), ("_Date", "date")]:
160
col = gtk.CheckMenuItem("Show " + label + " Column")
183
161
col.set_active(self.treeview.get_property(name + "-column-visible"))
184
162
col.connect('toggled', self._col_visibility_changed, name)
185
163
view_menu.add(col)
192
170
go_menu_next = self.next_rev_action.create_menu_item()
193
171
go_menu_prev = self.prev_rev_action.create_menu_item()
195
tag_image = gtk.Image()
196
tag_image.set_from_file(icon_path("tag-16.png"))
197
self.go_menu_tags = gtk.ImageMenuItem("_Tags")
198
self.go_menu_tags.set_image(tag_image)
173
tags_menu = gtk.Menu()
174
go_menu_tags = gtk.MenuItem("_Tags")
175
go_menu_tags.set_submenu(tags_menu)
177
if self.branch.supports_tags():
178
tags = self.branch.tags.get_tag_dict().items()
181
for tag, revid in tags:
182
tag_item = gtk.MenuItem(tag)
183
tag_item.connect('activate', self._tag_selected_cb, revid)
184
tags_menu.add(tag_item)
186
go_menu_tags.set_sensitive(len(tags) != 0)
188
go_menu_tags.set_sensitive(False)
201
190
go_menu.add(go_menu_next)
202
191
go_menu.add(go_menu_prev)
203
192
go_menu.add(gtk.SeparatorMenuItem())
204
go_menu.add(self.go_menu_tags)
193
go_menu.add(go_menu_tags)
206
195
revision_menu = gtk.Menu()
207
196
revision_menuitem = gtk.MenuItem("_Revision")
210
199
revision_menu_diff = gtk.MenuItem("View Changes")
211
200
revision_menu_diff.connect('activate',
214
revision_menu_compare = gtk.MenuItem("Compare with...")
215
revision_menu_compare.connect('activate',
216
self._compare_with_cb)
201
lambda w: self.treeview.show_diff())
218
203
revision_menu_tag = gtk.MenuItem("Tag Revision")
219
204
revision_menu_tag.connect('activate', self._tag_revision_cb)
221
206
revision_menu.add(revision_menu_tag)
222
207
revision_menu.add(revision_menu_diff)
223
revision_menu.add(revision_menu_compare)
225
209
branch_menu = gtk.Menu()
226
210
branch_menuitem = gtk.MenuItem("_Branch")
229
213
branch_menu.add(gtk.MenuItem("Pu_ll Revisions"))
230
214
branch_menu.add(gtk.MenuItem("Pu_sh Revisions"))
233
from bzrlib.plugins import search
235
mutter("Didn't find search plugin")
237
branch_index_menuitem = gtk.MenuItem("_Index")
238
branch_index_menuitem.connect('activate', self._branch_index_cb)
239
branch_menu.add(branch_index_menuitem)
241
216
help_menu = gtk.Menu()
242
217
help_menuitem = gtk.MenuItem("_Help")
243
218
help_menuitem.set_submenu(help_menu)
245
help_about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT, self.accel_group)
246
help_about_menuitem.connect('activate', self._about_dialog_cb)
248
help_menu.add(help_about_menuitem)
220
help_menu_about = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
221
help_menu_about.connect('activate', self._show_about_cb)
223
help_menu.add(help_menu_about)
250
225
menubar.add(file_menuitem)
251
226
menubar.add(edit_menuitem)
252
227
menubar.add(view_menuitem)
257
232
menubar.show_all()
236
def construct_loading_msg(self):
237
image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
238
gtk.ICON_SIZE_BUTTON)
241
label_loading = gtk.Label(_("Please wait, loading ancestral graph..."))
242
label_loading.set_alignment(0.0, 0.5)
245
self.loading_msg_box = gtk.HBox()
246
self.loading_msg_box.set_spacing(5)
247
self.loading_msg_box.set_border_width(5)
248
self.loading_msg_box.pack_start(image_loading, False, False)
249
self.loading_msg_box.pack_start(label_loading, True, True)
250
self.loading_msg_box.show()
252
return self.loading_msg_box
261
254
def construct_top(self):
262
255
"""Construct the top-half of the window."""
263
256
# FIXME: Make broken_line_length configurable
265
self.treeview = TreeView(self.branch, self.start_revs, self.maxnum, self.compact_view)
258
self.treeview = TreeView(self.branch, self.start, self.maxnum, self.compact_view)
267
260
self.treeview.connect('revision-selected',
268
261
self._treeselection_changed_cb)
269
self.treeview.connect('revision-activated',
270
self._tree_revision_activated)
272
self.treeview.connect('tag-added', lambda w, t, r: self._update_tags())
263
self.treeview.connect('revisions-loaded',
264
lambda x: self.loading_msg_box.hide())
274
266
for col in ["revno", "date"]:
275
267
option = self.config.get_user_option(col + '-column-visible')
276
268
if option is not None:
277
269
self.treeview.set_property(col + '-column-visible', option == 'True')
279
self.treeview.set_property(col + '-column-visible', False)
281
271
self.treeview.show()
311
301
def construct_bottom(self):
312
302
"""Construct the bottom half of the window."""
313
303
from bzrlib.plugins.gtk.revisionview import RevisionView
314
self.revisionview = RevisionView(branch=self.branch)
304
self.revisionview = RevisionView(None, tags=[], show_children=True, branch=self.branch)
315
305
(width, height) = self.get_size()
316
306
self.revisionview.set_size_request(width, int(height / 2.5))
317
307
self.revisionview.show()
318
308
self.revisionview.set_show_callback(self._show_clicked_cb)
319
self.revisionview.connect('notify::revision', self._go_clicked_cb)
320
self.treeview.connect('tag-added', lambda w, t, r: self.revisionview.update_tags())
309
self.revisionview.set_go_callback(self._go_clicked_cb)
321
310
return self.revisionview
323
312
def _tag_selected_cb(self, menuitem, revid):
329
318
parents = self.treeview.get_parents()
330
319
children = self.treeview.get_children()
332
if revision and revision != NULL_REVISION:
321
if revision is not None:
333
322
prev_menu = gtk.Menu()
334
323
if len(parents) > 0:
335
324
self.prev_rev_action.set_sensitive(True)
336
325
for parent_id in parents:
337
if parent_id and parent_id != NULL_REVISION:
338
parent = self.branch.repository.get_revision(parent_id)
340
str = ' (' + parent.properties['branch-nick'] + ')'
326
parent = self.branch.repository.get_revision(parent_id)
328
str = ' (' + parent.properties['branch-nick'] + ')'
344
item = gtk.MenuItem(parent.message.split("\n")[0] + str)
345
item.connect('activate', self._set_revision_cb, parent_id)
332
item = gtk.MenuItem(parent.message.split("\n")[0] + str)
333
item.connect('activate', self._set_revision_cb, parent_id)
347
335
prev_menu.show_all()
349
337
self.prev_rev_action.set_sensitive(False)
372
360
self.next_button.set_menu(next_menu)
374
self.revisionview.set_revision(revision)
375
self.revisionview.set_children(children)
377
def _tree_revision_activated(self, widget, path, col):
378
# TODO: more than one parent
379
"""Callback for when a treeview row gets activated."""
380
revision = self.treeview.get_revision()
381
parents = self.treeview.get_parents()
383
if len(parents) == 0:
386
parent_id = parents[0]
388
self.show_diff(revision.revision_id, parent_id)
389
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)
363
if self.branch.supports_tags():
364
tagdict = self.branch.tags.get_reverse_tag_dict()
365
if tagdict.has_key(revision.revision_id):
366
tags = tagdict[revision.revision_id]
367
self.revisionview.set_revision(revision, tags, children)
404
369
def _back_clicked_cb(self, *args):
405
370
"""Callback for when the back button is clicked."""
409
374
"""Callback for when the forward button is clicked."""
410
375
self.treeview.forward()
412
def _go_clicked_cb(self, w, p):
377
def _go_clicked_cb(self, revid):
413
378
"""Callback for when the go button for a parent is clicked."""
414
if self.revisionview.get_revision() is not None:
415
self.treeview.set_revision(self.revisionview.get_revision())
379
self.treeview.set_revision_id(revid)
417
381
def _show_clicked_cb(self, revid, parentid):
418
382
"""Callback for when the show button for a parent is clicked."""
419
self.show_diff(revid, parentid)
383
self.treeview.show_diff(revid, parentid)
420
384
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
386
def _set_revision_cb(self, w, revision_id):
439
387
self.treeview.set_revision_id(revision_id)
453
401
def _tag_revision_cb(self, w):
455
403
self.treeview.set_sensitive(False)
456
405
dialog = AddTagDialog(self.branch.repository, self.treeview.get_revision().revision_id, self.branch)
457
406
response = dialog.run()
458
407
if response != gtk.RESPONSE_NONE:
461
410
if response == gtk.RESPONSE_OK:
462
self.treeview.add_tag(dialog.tagname, dialog._revid)
412
self.branch.lock_write()
413
self.branch.tags.set_tag(dialog.tagname, dialog._revid)
420
self.branch.lock_read()
421
self.treeview.emit("revision-selected")
467
422
self.treeview.set_sensitive(True)
469
def _branch_index_cb(self, w):
470
from bzrlib.plugins.search import index as _mod_index
471
_mod_index.index_url(self.branch.base)
473
def _about_dialog_cb(self, w):
474
from bzrlib.plugins.gtk.about import AboutDialog
478
424
def _col_visibility_changed(self, col, property):
479
425
self.config.set_user_option(property + '-column-visible', col.get_active())
480
426
self.treeview.set_property(property + '-column-visible', col.get_active())
493
439
def _refresh_clicked(self, w):
494
self.treeview.refresh()
496
def _update_tags(self):
499
if self.branch.supports_tags():
500
tags = self.branch.tags.get_tag_dict().items()
503
for tag, revid in tags:
504
tag_image = gtk.Image()
505
tag_image.set_from_file(icon_path('tag-16.png'))
506
tag_item = gtk.ImageMenuItem(tag.replace('_', '__'))
507
tag_item.set_image(tag_image)
508
tag_item.connect('activate', self._tag_selected_cb, revid)
510
self.go_menu_tags.set_submenu(menu)
512
self.go_menu_tags.set_sensitive(len(tags) != 0)
514
self.go_menu_tags.set_sensitive(False)
516
self.go_menu_tags.show_all()
518
def show_diff(self, revid=None, parentid=None):
519
"""Open a new window to show a diff between the given revisions."""
520
from bzrlib.plugins.gtk.diff import DiffWindow
521
window = DiffWindow(parent=self)
524
parentid = NULL_REVISION
526
rev_tree = self.branch.repository.revision_tree(revid)
527
parent_tree = self.branch.repository.revision_tree(parentid)
529
description = revid + " - " + self.branch.nick
530
window.set_diff(description, rev_tree, parent_tree)
440
self.treeview.update()