1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
# Some parts of the code are:
3
# Copyright (C) 2005, 2006 by Canonical Ltd
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
from bzrlib.plugins.gtk import _i18n, icon_path
26
class OliveGui(gtk.Window):
27
""" Olive main window """
29
def __init__(self, calling_app):
30
# Pointer to calling instance for signal connection
31
self.signal = calling_app
32
self.iconpath = icon_path()+os.sep
35
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
36
self.set_title(_i18n("Olive - Bazaar GUI"))
37
self.set_icon_list(gtk.gdk.pixbuf_new_from_file(self.iconpath+"oliveicon2.png"),
38
gtk.gdk.pixbuf_new_from_file(self.iconpath+"olive-gtk.png"),
39
# Who has the svg version of the icon? Would be nice to include
40
#gtk.gdk.pixbuf_new_from_file(self.iconpath+"olive.svg")
42
self.set_property("width-request", 700)
43
self.set_property("height-request", 400)
45
self.connect("destroy", self.destroy)
46
self.connect("delete_event", self.signal.on_window_main_delete_event)
48
# Accelerator group to Quit program
49
accelgroup = gtk.AccelGroup()
50
self.add_accel_group(accelgroup)
51
self.quit_action = gtk.Action(_i18n("Quit"), None, None, gtk.STOCK_QUIT)
52
self.quit_action.connect('activate', self.signal.on_window_main_delete_event)
53
actiongroup = gtk.ActionGroup('QuitAction')
54
actiongroup.add_action_with_accel(self.quit_action, None)
55
self.quit_action.set_accel_group(accelgroup)
56
self.quit_action.connect_accelerator()
58
# High level build up of window
59
self.vbox = gtk.VBox(False, 0)
63
self._create_menubar()
64
self.vbox.pack_start(self.mb, False, False, 0)
67
self._create_toolbar()
68
self.vbox.pack_start(self.tb, False, False, 0)
71
self._create_locationbar()
72
self.vbox.pack_start(self.locationbar, False, False, 0)
75
self.hpaned_main = gtk.HPaned()
76
self._create_bookmarklist()
77
self.hpaned_main.add(self.scrolledwindow_left)
78
self._create_filelist()
79
self.hpaned_main.add(self.scrolledwindow_right)
80
self.vbox.pack_start(self.hpaned_main, True, True, 0)
83
self.statusbar = gtk.Statusbar()
84
self.vbox.pack_end(self.statusbar, False, False, 0)
89
def destroy(self, widget=None, data=None):
90
""" Ends the program """
93
def _create_menubar(self):
94
self.mb = gtk.MenuBar()
97
self.mb_file = gtk.MenuItem(_i18n("_File"))
98
self.mb_file_menu = gtk.Menu()
100
self.mb_file_add = gtk.ImageMenuItem(gtk.STOCK_ADD, _i18n("_Add file(s)"))
101
self.mb_file_add.connect('activate', self.signal.on_menuitem_add_files_activate)
102
self.mb_file_menu.append(self.mb_file_add)
104
self.mb_file_remove = gtk.ImageMenuItem(gtk.STOCK_REMOVE, _i18n("_Remove file(s)"))
105
self.mb_file_remove.connect('activate', self.signal.on_menuitem_remove_file_activate)
106
self.mb_file_menu.append(self.mb_file_remove)
108
self.mb_file_menu.append(gtk.SeparatorMenuItem())
110
self.mb_file_bookmark = gtk.MenuItem(_i18n("_Bookmark current directory"))
111
self.mb_file_bookmark.connect('activate', self.signal.on_menuitem_file_bookmark_activate)
112
self.mb_file_menu.append(self.mb_file_bookmark)
114
self.mb_file_mkdir = gtk.MenuItem(_i18n("_Make directory"))
115
self.mb_file_mkdir.connect('activate', self.signal.on_menuitem_file_make_directory_activate)
116
self.mb_file_menu.append(self.mb_file_mkdir)
118
self.mb_file_menu.append(gtk.SeparatorMenuItem())
120
self.mb_file_rename = gtk.MenuItem(_i18n("_Rename"))
121
self.mb_file_rename.connect('activate', self.signal.on_menuitem_file_rename_activate)
122
self.mb_file_menu.append(self.mb_file_rename)
124
self.mb_file_move = gtk.MenuItem(_i18n("_Move"))
125
self.mb_file_move.connect('activate', self.signal.on_menuitem_file_move_activate)
126
self.mb_file_menu.append(self.mb_file_move)
128
self.mb_file_annotate = gtk.MenuItem(_i18n("_Annotate"))
129
self.mb_file_annotate.connect('activate', self.signal.on_menuitem_file_annotate_activate)
130
self.mb_file_menu.append(self.mb_file_annotate)
132
self.mb_file_menu.append(gtk.SeparatorMenuItem())
134
self.mb_file_quit = self.quit_action.create_menu_item()
135
self.mb_file_menu.append(self.mb_file_quit)
137
self.mb_file.set_submenu(self.mb_file_menu)
138
self.mb.append(self.mb_file)
141
self.mb_view = gtk.MenuItem(_i18n("_View"))
142
self.mb_view_menu = gtk.Menu()
144
self.mb_view_showhidden = gtk.CheckMenuItem(_i18n("Show _hidden files"))
145
self.mb_view_showhidden.connect('activate', self.signal.on_menuitem_view_show_hidden_files_activate)
146
self.mb_view_menu.append(self.mb_view_showhidden)
148
self.mb_view_showignored = gtk.CheckMenuItem(_i18n("Show _ignored files"))
149
self.mb_view_showignored.connect('activate', self.signal.on_menuitem_view_show_ignored_files_activate)
150
self.mb_view_menu.append(self.mb_view_showignored)
152
self.mb_view_menu.append(gtk.SeparatorMenuItem())
154
self.mb_view_refresh = gtk.ImageMenuItem(gtk.STOCK_REFRESH, _i18n("_Refresh"))
155
self.mb_view_refresh.connect('activate', self.signal.on_menuitem_view_refresh_activate)
156
self.mb_view_menu.append(self.mb_view_refresh)
158
self.mb_view.set_submenu(self.mb_view_menu)
159
self.mb.append(self.mb_view)
162
self.mb_branch = gtk.MenuItem(_i18n("_Branch"))
163
self.mb_branch_menu = gtk.Menu()
165
self.mb_branch_initialize = gtk.MenuItem(_i18n("_Initialize"))
166
self.mb_branch_initialize.connect('activate', self.signal.on_menuitem_branch_initialize_activate)
167
self.mb_branch_menu.append(self.mb_branch_initialize)
169
self.mb_branch_get = gtk.MenuItem(_i18n("_Get"))
170
self.mb_branch_get.connect('activate', self.signal.on_menuitem_branch_get_activate)
171
self.mb_branch_menu.append(self.mb_branch_get)
173
self.mb_branch_checkout = gtk.MenuItem(_i18n("C_heckout"))
174
self.mb_branch_checkout.connect('activate', self.signal.on_menuitem_branch_checkout_activate)
175
self.mb_branch_menu.append(self.mb_branch_checkout)
177
self.mb_branch_menu.append(gtk.SeparatorMenuItem())
179
self.mb_branch_pull = gtk.ImageMenuItem(_i18n("Pu_ll"))
180
pullimage = gtk.Image()
181
pullimage.set_from_file(self.iconpath+"pull16.png")
182
self.mb_branch_pull.set_image(pullimage)
183
self.mb_branch_pull.connect('activate', self.signal.on_menuitem_branch_pull_activate)
184
self.mb_branch_menu.append(self.mb_branch_pull)
186
self.mb_branch_push = gtk.ImageMenuItem(_i18n("Pu_sh"))
187
pushimage = gtk.Image()
188
pushimage.set_from_file(self.iconpath+"push16.png")
189
self.mb_branch_push.set_image(pushimage)
190
self.mb_branch_push.connect('activate', self.signal.on_menuitem_branch_push_activate)
191
self.mb_branch_menu.append(self.mb_branch_push)
193
self.mb_branch_update = gtk.MenuItem(_i18n("_Update"))
194
self.mb_branch_update.connect('activate', self.signal.on_menuitem_branch_update_activate)
195
self.mb_branch_menu.append(self.mb_branch_update)
197
self.mb_branch_menu.append(gtk.SeparatorMenuItem())
199
self.mb_branch_revert = gtk.ImageMenuItem(_i18n("_Revert all changes"))
200
revertimage = gtk.Image()
201
revertimage.set_from_stock(gtk.STOCK_REVERT_TO_SAVED, gtk.ICON_SIZE_MENU)
202
self.mb_branch_revert.set_image(revertimage)
203
self.mb_branch_revert.connect('activate', self.signal.on_menuitem_branch_revert_activate)
204
self.mb_branch_menu.append(self.mb_branch_revert)
206
self.mb_branch_merge = gtk.MenuItem(_i18n("_Merge"))
207
self.mb_branch_merge.connect('activate', self.signal.on_menuitem_branch_merge_activate)
208
self.mb_branch_menu.append(self.mb_branch_merge)
210
self.mb_branch_commit = gtk.ImageMenuItem(_i18n("_Commit"))
211
commitimage = gtk.Image()
212
commitimage.set_from_file(self.iconpath+"commit16.png")
213
self.mb_branch_commit.set_image(commitimage)
214
self.mb_branch_commit.connect('activate', self.signal.on_menuitem_branch_commit_activate)
215
self.mb_branch_menu.append(self.mb_branch_commit)
217
self.mb_branch_menu.append(gtk.SeparatorMenuItem())
219
self.mb_branch_tags = gtk.ImageMenuItem(_i18n("Ta_gs"))
220
tagsimage = gtk.Image()
221
tagsimage.set_from_file(self.iconpath+"tag-16.png")
222
self.mb_branch_tags.set_image(tagsimage)
223
self.mb_branch_tags.connect('activate', self.signal.on_menuitem_branch_tags_activate)
224
self.mb_branch_menu.append(self.mb_branch_tags)
226
self.mb_branch_status = gtk.MenuItem(_i18n("S_tatus"))
227
self.mb_branch_status.connect('activate', self.signal.on_menuitem_branch_status_activate)
228
self.mb_branch_menu.append(self.mb_branch_status)
230
self.mb_branch_missingrevisions = gtk.MenuItem(_i18n("Missing _revisions"))
231
self.mb_branch_missingrevisions.connect('activate', self.signal.on_menuitem_branch_missing_revisions_activate)
232
self.mb_branch_menu.append(self.mb_branch_missingrevisions)
234
self.mb_branch_conflicts = gtk.MenuItem(_i18n("Con_flicts"))
235
self.mb_branch_conflicts.connect('activate', self.signal.on_menuitem_branch_conflicts_activate)
236
self.mb_branch_menu.append(self.mb_branch_conflicts)
238
self.mb_branch.set_submenu(self.mb_branch_menu)
239
self.mb.append(self.mb_branch)
242
self.mb_statistics = gtk.MenuItem(_i18n("_Statistics"))
243
self.mb_statistics_menu = gtk.Menu()
245
self.mb_statistics_differences = gtk.ImageMenuItem(_i18n("_Differences"))
246
diffimage = gtk.Image()
247
diffimage.set_from_file(self.iconpath+"diff16.png")
248
self.mb_statistics_differences.set_image(diffimage)
249
self.mb_statistics_differences.connect('activate', self.signal.on_menuitem_stats_diff_activate)
250
self.mb_statistics_menu.append(self.mb_statistics_differences)
252
self.mb_statistics_log = gtk.ImageMenuItem(_i18n("_Log"))
253
logimage = gtk.Image()
254
logimage.set_from_file(self.iconpath+"log16.png")
255
self.mb_statistics_log.set_image(logimage)
256
self.mb_statistics_log.connect('activate', self.signal.on_menuitem_stats_log_activate)
257
self.mb_statistics_menu.append(self.mb_statistics_log)
259
self.mb_statistics_information = gtk.MenuItem(_i18n("_Information"))
260
self.mb_statistics_information.connect('activate', self.signal.on_menuitem_stats_infos_activate)
261
self.mb_statistics_menu.append(self.mb_statistics_information)
263
self.mb_statistics.set_submenu(self.mb_statistics_menu)
264
self.mb.append(self.mb_statistics)
267
self.mb_help = gtk.MenuItem(_i18n("Help"))
268
self.mb_help_menu = gtk.Menu()
270
self.mb_help_about = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
271
self.mb_help_about.connect('activate', self.signal.on_about_activate)
272
self.mb_help_menu.append(self.mb_help_about)
274
self.mb_help.set_submenu(self.mb_help_menu)
275
self.mb.append(self.mb_help)
277
def _create_toolbar(self):
278
self.tb = gtk.Toolbar()
280
self.tb_refresh_icon = gtk.Image()
281
self.tb_refresh_icon.set_from_file(self.iconpath+"refresh.png")
282
self.tb_refresh = gtk.ToolButton(self.tb_refresh_icon, _i18n("Refresh"))
283
self.tb_refresh.connect('clicked', self.signal.on_menuitem_view_refresh_activate)
284
self.tb.add(self.tb_refresh)
286
self.tb_diff_icon = gtk.Image()
287
self.tb_diff_icon.set_from_file(self.iconpath+"diff.png")
288
self.tb_diff = gtk.ToolButton(self.tb_diff_icon, _i18n("Diff"))
289
self.tb_diff.connect('clicked', self.signal.on_menuitem_stats_diff_activate)
290
self.tb.add(self.tb_diff)
292
self.tb_log_icon = gtk.Image()
293
self.tb_log_icon.set_from_file(self.iconpath+"log.png")
294
self.tb_log = gtk.ToolButton(self.tb_log_icon, _i18n("Log"))
295
self.tb_log.connect('clicked', self.signal.on_menuitem_stats_log_activate)
296
self.tb.add(self.tb_log)
298
self.tb_commit_icon = gtk.Image()
299
self.tb_commit_icon.set_from_file(self.iconpath+"commit.png")
300
self.tb_commit = gtk.ToolButton(self.tb_commit_icon, _i18n("Commit"))
301
self.tb_commit.connect('clicked', self.signal.on_menuitem_branch_commit_activate)
302
self.tb.add(self.tb_commit)
304
self.tb_pull_icon = gtk.Image()
305
self.tb_pull_icon.set_from_file(self.iconpath+"pull.png")
306
self.tb_pull = gtk.ToolButton(self.tb_pull_icon, _i18n("Pull"))
307
self.tb_pull.connect('clicked', self.signal.on_menuitem_branch_pull_activate)
308
self.tb.add(self.tb_pull)
310
self.tb_push_icon = gtk.Image()
311
self.tb_push_icon.set_from_file(self.iconpath+"push.png")
312
self.tb_push = gtk.ToolButton(self.tb_push_icon, _i18n("Push"))
313
self.tb_push.connect('clicked', self.signal.on_menuitem_branch_push_activate)
314
self.tb.add(self.tb_push)
316
self.tb_update_icon = gtk.Image()
317
self.tb_update_icon.set_from_file(self.iconpath+"pull.png")
318
self.tb_update = gtk.ToolButton(self.tb_update_icon, _i18n("Update"))
319
self.tb_update.connect('clicked', self.signal.on_menuitem_branch_update_activate)
320
self.tb.add(self.tb_update)
322
def _create_locationbar(self):
323
""" Creates the location bar, including the history widgets """
324
self.locationbar = gtk.HBox()
326
self.button_location_up = gtk.Button()
327
self.button_location_up.set_relief(gtk.RELIEF_NONE)
328
image_location_up = gtk.Image()
329
image_location_up.set_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_BUTTON)
330
self.button_location_up.add(image_location_up)
331
self.button_location_up.connect("clicked", self.signal.on_button_location_up_clicked)
332
self.locationbar.pack_start(self.button_location_up, False, False, 0)
334
self.entry_location = gtk.Entry()
335
self.entry_location.connect("key-press-event", self.signal.on_entry_location_key_press_event)
336
self.locationbar.pack_start(self.entry_location, True, True, 0)
338
self.image_location_error = gtk.Image()
339
self.image_location_error.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_BUTTON)
340
self.locationbar.pack_start(self.image_location_error, False, False, 0)
342
self.button_location_jump = gtk.Button(stock=gtk.STOCK_JUMP_TO)
343
self.button_location_jump.set_relief(gtk.RELIEF_NONE)
344
self.button_location_jump.connect("clicked", self.signal.on_button_location_jump_clicked)
345
self.locationbar.pack_start(self.button_location_jump, False, False, 0)
347
self.locationbar.pack_start(gtk.VSeparator(), False, False, 0)
349
self.checkbutton_history = gtk.CheckButton(_i18n("H_istory Mode"))
350
self.checkbutton_history.connect("toggled", self.signal.on_checkbutton_history_toggled)
351
self.locationbar.pack_start(self.checkbutton_history, False, False, 0)
353
self.entry_history_revno = gtk.Entry()
354
self.entry_history_revno.set_property("width-request", 75)
355
self.entry_history_revno.set_sensitive(False)
356
self.entry_history_revno.connect("key-press-event", self.signal.on_entry_history_revno_key_press_event)
357
self.locationbar.pack_start(self.entry_history_revno, False, False, 0)
359
self.button_history_browse = gtk.Button()
360
self.button_history_browse.set_sensitive(False)
361
self.image_history_browse = gtk.Image()
362
self.image_history_browse.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
363
self.button_history_browse.add(self.image_history_browse)
364
self.button_history_browse.connect("clicked", self.signal.on_button_history_browse_clicked)
365
self.locationbar.pack_start(self.button_history_browse, False, False, 0)
367
def _create_bookmarklist(self):
368
""" Creates the bookmark list (a ListStore in a TreeView in a ScrolledWindow)"""
369
self.scrolledwindow_left = gtk.ScrolledWindow()
370
self.scrolledwindow_left.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
372
self.treeview_left = gtk.TreeView()
373
self.treeview_left.set_headers_visible(False)
374
self.treeview_left.connect("button-press-event", self.signal.on_treeview_left_button_press_event)
375
self.treeview_left.connect("button-release-event", self.signal.on_treeview_left_button_release_event)
376
self.treeview_left.connect("row-activated", self.signal.on_treeview_left_row_activated)
377
self.scrolledwindow_left.add(self.treeview_left)
379
# Move olive/__init__.py _load_left List creation here
381
def _create_filelist(self):
382
""" Creates the file list (a ListStore in a TreeView in a ScrolledWindow)"""
383
# Model: [ icon, dir, name, status text, status, size (int), size (human), mtime (int), mtime (local), fileid ]
384
self.scrolledwindow_right = gtk.ScrolledWindow()
385
self.scrolledwindow_right.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
387
self.treeview_right = gtk.TreeView()
388
self.treeview_right.connect("button-press-event", self.signal.on_treeview_right_button_press_event)
389
self.treeview_right.connect("row-activated", self.signal.on_treeview_right_row_activated)
390
self.scrolledwindow_right.add(self.treeview_right)
392
# Move olive/__init__.py _load_right List creation here
394
def set_view_to_localbranch(self, notbranch=False):
395
""" Change the sensitivity of gui items to reflect the fact that the path is a branch or not"""
396
self.mb_branch_initialize.set_sensitive(notbranch)
397
self.mb_branch_get.set_sensitive(notbranch)
398
self.mb_branch_checkout.set_sensitive(notbranch)
399
self.mb_branch_pull.set_sensitive(not notbranch)
400
self.mb_branch_push.set_sensitive(not notbranch)
401
self.mb_branch_update.set_sensitive(not notbranch)
402
self.mb_branch_revert.set_sensitive(not notbranch)
403
self.mb_branch_merge.set_sensitive(not notbranch)
404
self.mb_branch_commit.set_sensitive(not notbranch)
405
self.mb_branch_tags.set_sensitive(not notbranch)
406
self.mb_branch_status.set_sensitive(not notbranch)
407
self.mb_branch_missingrevisions.set_sensitive(not notbranch)
408
self.mb_branch_conflicts.set_sensitive(not notbranch)
409
self.mb_statistics.set_sensitive(not notbranch)
410
self.mb_statistics_differences.set_sensitive(not notbranch)
411
self.mb_file_add.set_sensitive(not notbranch)
412
self.mb_file_remove.set_sensitive(not notbranch)
413
self.mb_file_mkdir.set_sensitive(not notbranch)
414
self.mb_file_rename.set_sensitive(not notbranch)
415
self.mb_file_move.set_sensitive(not notbranch)
416
self.mb_file_annotate.set_sensitive(not notbranch)
417
self.tb_diff.set_sensitive(not notbranch)
418
self.tb_log.set_sensitive(not notbranch)
419
self.tb_commit.set_sensitive(not notbranch)
420
self.tb_pull.set_sensitive(not notbranch)
421
self.tb_push.set_sensitive(not notbranch)
422
self.tb_update.set_sensitive(not notbranch)
424
def set_view_to_remotebranch(self):
425
""" Change the sensitivity of gui items to reflect the fact that the branch is remote"""
426
self.mb_file_add.set_sensitive(False)
427
self.mb_file_remove.set_sensitive(False)
428
self.mb_file_mkdir.set_sensitive(False)
429
self.mb_file_rename.set_sensitive(False)
430
self.mb_file_move.set_sensitive(False)
431
self.mb_file_annotate.set_sensitive(False)
432
self.mb_branch_initialize.set_sensitive(False)
433
self.mb_branch_get.set_sensitive(True)
434
self.mb_branch_checkout.set_sensitive(True)
435
self.mb_branch_pull.set_sensitive(False)
436
self.mb_branch_push.set_sensitive(False)
437
self.mb_branch_update.set_sensitive(False)
438
self.mb_branch_revert.set_sensitive(False)
439
self.mb_branch_merge.set_sensitive(False)
440
self.mb_branch_commit.set_sensitive(False)
441
self.mb_branch_tags.set_sensitive(True)
442
self.mb_branch_status.set_sensitive(False)
443
self.mb_branch_missingrevisions.set_sensitive(False)
444
self.mb_branch_conflicts.set_sensitive(False)
445
self.mb_statistics.set_sensitive(True)
446
self.mb_statistics_differences.set_sensitive(False)
447
self.tb_diff.set_sensitive(False)
448
self.tb_log.set_sensitive(True)
449
self.tb_commit.set_sensitive(False)
450
self.tb_pull.set_sensitive(False)
451
self.tb_push.set_sensitive(False)
452
self.tb_update.set_sensitive(False)