36
34
from bzrlib.branch import Branch
37
35
import bzrlib.errors as bzrerrors
38
from bzrlib.lazy_import import lazy_import
39
from bzrlib.ui import ui_factory
40
36
from bzrlib.workingtree import WorkingTree
42
from bzrlib.plugins.gtk import _i18n
43
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
44
from bzrlib.plugins.gtk.errors import show_bzr_error
45
from bzrlib.plugins.gtk.olive.window import OliveGui
47
from bzrlib.plugins.gtk.diff import DiffWindow
48
lazy_import(globals(), """
49
from bzrlib.plugins.gtk.viz import branchwin
51
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
52
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
53
from bzrlib.plugins.gtk.commit import CommitDialog
54
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
55
from bzrlib.plugins.gtk.initialize import InitDialog
56
from bzrlib.plugins.gtk.push import PushDialog
57
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
60
""" Display the AboutDialog. """
61
from bzrlib.plugins.gtk import __version__, icon_path
63
iconpath = icon_path() + os.sep
65
dialog = gtk.AboutDialog()
66
dialog.set_name("Olive")
67
dialog.set_version(__version__)
68
dialog.set_copyright("Copyright (C) 2006 Szilveszter Farkas (Phanatic)")
69
dialog.set_website("https://launchpad.net/products/olive")
70
dialog.set_website_label("https://launchpad.net/products/olive")
71
dialog.set_icon_from_file(iconpath+"oliveicon2.png")
72
dialog.set_logo(gtk.gdk.pixbuf_new_from_file(iconpath+"oliveicon2.png"))
73
dialog.set_authors([ _i18n("Lead Developer:"),
74
"Szilveszter Farkas <szilveszter.farkas@gmail.com>",
75
_i18n("Contributors:"),
76
"Jelmer Vernooij <jelmer@samba.org>",
77
"Mateusz Korniak <mateusz.korniak@ant.gliwice.pl>",
78
"Gary van der Merwe <garyvdm@gmail.com>" ])
79
dialog.set_artists([ "Simon Pascal Klein <klepas@klepas.org>",
80
"Jakub Steiner <jimmac@novell.com>" ])
38
from dialog import error_dialog, info_dialog, warning_dialog
39
from errors import show_bzr_error
40
from guifiles import GLADEFILENAME
42
# import this classes only once
44
from bzrlib.plugins.gtk.viz.diffwin import DiffWindow
45
from bzrlib.plugins.gtk.viz.branchwin import BranchWindow
46
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
47
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
48
from bzrlib.plugins.gtk.commit import CommitDialog
49
from bzrlib.plugins.gtk.push import PushDialog
51
# olive+bzr-gtk not installed. try to import from sources
52
path = os.path.dirname(os.path.dirname(__file__))
53
if path not in sys.path:
55
from viz.diffwin import DiffWindow
56
from viz.branchwin import BranchWindow
57
from annotate.gannotate import GAnnotateWindow
58
from annotate.config import GAnnotateConfig
60
# History delimiter used in config files
87
64
""" The main Olive GTK frontend class. This is called when launching the
90
67
def __init__(self):
91
self.window = OliveGui(calling_app = self)
68
self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
70
self.window = self.toplevel.get_widget('window_main')
93
72
self.pref = Preferences()
96
76
# Initialize the statusbar
97
self.context_id = self.window.statusbar.get_context_id('olive')
100
self.treeview_left = self.window.treeview_left
101
self.treeview_right = self.window.treeview_right
77
self.statusbar = self.toplevel.get_widget('statusbar')
78
self.context_id = self.statusbar.get_context_id('olive')
81
self.window_main = self.toplevel.get_widget('window_main')
83
self.hpaned_main = self.toplevel.get_widget('hpaned_main')
85
self.treeview_left = self.toplevel.get_widget('treeview_left')
86
self.treeview_right = self.toplevel.get_widget('treeview_right')
87
# Get some important menu items
88
self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
89
self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
90
self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
91
self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
92
self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
93
self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
94
self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
95
self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
96
self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
97
self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
98
self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
99
self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
100
self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
101
self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
102
self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
103
self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
104
self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
105
self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
106
self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
107
self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
108
self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
109
# Get some toolbuttons
110
#self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
111
self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
112
self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
113
self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
114
self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
115
self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
103
116
# Get the drive selector
104
117
self.combobox_drive = gtk.combo_box_new_text()
105
118
self.combobox_drive.connect("changed", self._refresh_drives)
107
# Get the navigation widgets
108
self.hbox_location = self.window.locationbar
109
self.button_location_up = self.window.button_location_up
110
self.button_location_jump = self.window.button_location_jump
111
self.entry_location = self.window.entry_location
112
self.image_location_error = self.window.image_location_error
114
# Get the History widgets
115
self.check_history = self.window.checkbutton_history
116
self.entry_history = self.window.entry_history_revno
117
self.button_history = self.window.button_history_browse
120
self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
123
# Dictionary for signal_autoconnect
124
dic = { "on_window_main_destroy": gtk.main_quit,
125
"on_window_main_delete_event": self.on_window_main_delete_event,
126
"on_quit_activate": self.on_window_main_delete_event,
127
"on_about_activate": self.on_about_activate,
128
"on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
129
"on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
130
"on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
131
"on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
132
"on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
133
"on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
134
"on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
135
"on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
136
"on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
137
"on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
138
"on_menuitem_branch_checkout_activate": self.on_menuitem_branch_checkout_activate,
139
"on_menuitem_branch_revert_activate": self.on_menuitem_branch_revert_activate,
140
"on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
141
"on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
142
"on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
143
"on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
144
"on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
145
"on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
146
"on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
147
"on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
148
"on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
149
"on_toolbutton_refresh_clicked": self.on_menuitem_view_refresh_activate,
150
"on_toolbutton_log_clicked": self.on_menuitem_stats_log_activate,
151
#"on_menutoolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
152
"on_toolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
153
"on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
154
"on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
155
"on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
156
"on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
157
"on_treeview_right_row_activated": self.on_treeview_right_row_activated,
158
"on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
159
"on_treeview_left_row_activated": self.on_treeview_left_row_activated }
161
# Connect the signals to the handlers
162
self.toplevel.signal_autoconnect(dic)
119
164
self._just_started = True
127
172
self.window.move(x, y)
128
173
# Apply paned position
129
174
pos = self.pref.get_preference('paned_position', 'int')
130
self.window.hpaned_main.set_position(pos)
175
self.hpaned_main.set_position(pos)
177
# Apply menu to the toolbutton
178
#menubutton = self.toplevel.get_widget('menutoolbutton_diff')
179
#menubutton.set_menu(handler.menu.toolbar_diff)
132
181
# Now we can show the window
133
182
self.window.show()
135
184
# Show drive selector if under Win32
136
185
if sys.platform == 'win32':
137
self.hbox_location.pack_start(self.combobox_drive, False, False, 0)
138
self.hbox_location.reorder_child(self.combobox_drive, 1)
186
self.vbox_main_right.pack_start(self.combobox_drive, False, True, 0)
187
self.vbox_main_right.reorder_child(self.combobox_drive, 0)
139
188
self.combobox_drive.show()
140
189
self.gen_hard_selector()
142
# Acceptable errors when loading files/folders in the treeviews
143
self.acceptable_errors = (errno.ENOENT, errno.ELOOP)
145
191
self._load_left()
147
193
# Apply menu state
148
self.window.mb_view_showhidden.set_active(self.pref.get_preference('dotted_files', 'bool'))
149
self.window.mb_view_showignored.set_active(self.pref.get_preference('ignored_files', 'bool'))
194
self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
151
# We're starting local
153
self.remote_branch = None
154
self.remote_path = None
155
self.remote_revision = None
157
196
self.set_path(os.getcwd())
158
197
self._load_right()
160
199
self._just_started = False
162
def set_path(self, path, force_remote=False):
201
def set_path(self, path):
163
203
self.notbranch = False
166
# Forcing remote mode (reading data from inventory)
167
self._show_stock_image(gtk.STOCK_DISCONNECT)
169
br = Branch.open_containing(path)[0]
170
except bzrerrors.NotBranchError:
171
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
172
self.check_history.set_active(False)
173
self.check_history.set_sensitive(False)
175
except bzrerrors.UnsupportedProtocol:
176
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
177
self.check_history.set_active(False)
178
self.check_history.set_sensitive(False)
181
self._show_stock_image(gtk.STOCK_CONNECT)
186
self.remote_branch, self.remote_path = Branch.open_containing(path)
188
if self.remote_revision is None:
189
self.remote_revision = self.remote_branch.last_revision()
191
self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
193
if len(self.remote_path) == 0:
194
self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
196
for (name, type) in self.remote_entries:
197
if name == self.remote_path:
198
self.remote_parent = type.file_id
201
if not path.endswith('/'):
204
if self.remote_branch.base == path:
205
self.button_location_up.set_sensitive(False)
207
self.button_location_up.set_sensitive(True)
209
if os.path.isdir(path):
210
self.image_location_error.destroy()
215
self.wt, self.wtpath = WorkingTree.open_containing(path)
216
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
217
self.notbranch = True
219
# If we're in the root, we cannot go up anymore
220
if sys.platform == 'win32':
221
drive, tail = os.path.splitdrive(path)
222
if tail in ('', '/', '\\'):
223
self.button_location_up.set_sensitive(False)
225
self.button_location_up.set_sensitive(True)
228
self.button_location_up.set_sensitive(False)
230
self.button_location_up.set_sensitive(True)
231
elif not os.path.isfile(path):
232
# Doesn't seem to be a file nor a directory, trying to open a
234
self._show_stock_image(gtk.STOCK_DISCONNECT)
236
br = Branch.open_containing(path)[0]
237
except bzrerrors.NotBranchError:
238
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
239
self.check_history.set_active(False)
240
self.check_history.set_sensitive(False)
242
except bzrerrors.UnsupportedProtocol:
243
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
244
self.check_history.set_active(False)
245
self.check_history.set_sensitive(False)
248
self._show_stock_image(gtk.STOCK_CONNECT)
253
self.remote_branch, self.remote_path = Branch.open_containing(path)
255
if self.remote_revision is None:
256
self.remote_revision = self.remote_branch.last_revision()
258
self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
260
if len(self.remote_path) == 0:
261
self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
263
for (name, type) in self.remote_entries:
264
if name == self.remote_path:
265
self.remote_parent = type.file_id
268
if not path.endswith('/'):
271
if self.remote_branch.base == path:
272
self.button_location_up.set_sensitive(False)
274
self.button_location_up.set_sensitive(True)
277
self.check_history.set_active(False)
278
self.check_history.set_sensitive(False)
280
self.check_history.set_sensitive(True)
282
self.window.statusbar.push(self.context_id, path)
283
self.entry_location.set_text(path)
206
self.wt, self.wtpath = WorkingTree.open_containing(self.path)
207
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
208
self.notbranch = True
210
self.statusbar.push(self.context_id, path)
287
212
def get_path(self):
292
if len(self.remote_path) > 0:
293
return self.remote_branch.base + self.remote_path + '/'
295
return self.remote_branch.base
297
215
def on_about_activate(self, widget):
216
from dialog import about
300
def on_button_history_browse_clicked(self, widget):
301
""" Browse for revision button handler. """
303
br = self.remote_branch
307
revb = RevisionBrowser(br, self.window)
308
response = revb.run()
309
if response != gtk.RESPONSE_NONE:
312
if response == gtk.RESPONSE_OK:
313
if revb.selected_revno is not None:
314
self.entry_history.set_text(revb.selected_revno)
315
self.on_entry_history_revno_activate()
319
def on_button_location_jump_clicked(self, widget):
320
""" Location Jump button handler. """
321
location = self.entry_location.get_text()
323
if self.set_path(location):
326
def on_button_location_up_clicked(self, widget):
327
""" Location Up button handler. """
330
self.set_path(os.path.split(self.get_path())[0])
334
newpath = delim.join(self.get_path().split(delim)[:-2])
336
self.set_path(newpath)
340
def on_checkbutton_history_toggled(self, widget):
341
""" History Mode toggle handler. """
342
if self.check_history.get_active():
343
# History Mode activated
344
self.entry_history.set_sensitive(True)
345
self.button_history.set_sensitive(True)
346
if self.entry_history.get_text() != "":
347
self.on_entry_history_revno_activate()
349
# History Mode deactivated
350
self.entry_history.set_sensitive(False)
351
self.button_history.set_sensitive(False)
353
# Return right window to normal view by acting like we jump to it
354
self.on_button_location_jump_clicked(widget)
357
def on_entry_history_revno_activate(self, widget=None):
358
""" Key pressed handler for the history entry. """
359
path = self.get_path()
362
self.remote_branch = self.wt.branch
364
revno = int(self.entry_history.get_text())
365
self.remote_revision = self.remote_branch.get_rev_id(revno)
366
if self.set_path(path, True):
369
219
def on_menuitem_add_files_activate(self, widget):
370
220
""" Add file(s)... menu handler. """
371
from bzrlib.plugins.gtk.olive.add import AddDialog
372
add = AddDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
375
if response == gtk.RESPONSE_OK:
221
from add import OliveAdd
222
add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
378
225
def on_menuitem_branch_get_activate(self, widget):
379
226
""" Branch/Get... menu handler. """
380
from bzrlib.plugins.gtk.branch import BranchDialog
383
branch = BranchDialog(os.getcwd(), self.window, self.remote_branch.base)
385
branch = BranchDialog(self.get_path(), self.window)
227
from branch import BranchDialog
228
branch = BranchDialog(self.get_path(), self.window)
386
229
response = branch.run()
387
230
if response != gtk.RESPONSE_NONE:
390
233
if response == gtk.RESPONSE_OK:
391
234
self.refresh_right()
431
def on_menuitem_branch_conflicts_activate(self, widget):
432
""" Branch/Conflicts... menu handler. """
433
conflicts = ConflictsDialog(self.wt, self.window)
434
response = conflicts.run()
435
if response != gtk.RESPONSE_NONE:
438
263
def on_menuitem_branch_merge_activate(self, widget):
439
264
""" Branch/Merge... menu handler. """
440
from bzrlib.plugins.gtk.merge import MergeDialog
265
from merge import MergeDialog
442
267
if self.check_for_changes():
443
error_dialog(_i18n('There are local changes in the branch'),
444
_i18n('Please commit or revert the changes before merging.'))
268
error_dialog(_('There are local changes in the branch'),
269
_('Please commit or revert the changes before merging.'))
446
parent_branch_path = self.wt.branch.get_parent()
447
merge = MergeDialog(self.wt, self.wtpath, parent_branch_path, self.window)
448
response = merge.run()
450
if response == gtk.RESPONSE_OK:
271
merge = MergeDialog(self.wt, self.wtpath)
454
274
def on_menuitem_branch_missing_revisions_activate(self, widget):
455
275
""" Branch/Missing revisions menu handler. """
457
from bzrlib.missing import find_unmerged, iter_log_revisions
459
276
local_branch = self.wt.branch
460
parent_branch_path = local_branch.get_parent()
461
if parent_branch_path is None:
462
error_dialog(_i18n('Parent location is unknown'),
463
_i18n('Cannot determine missing revisions if no parent location is known.'))
278
other_branch = local_branch.get_parent()
279
if other_branch is None:
280
error_dialog(_('Parent location is unknown'),
281
_('Cannot determine missing revisions if no parent location is known.'))
466
parent_branch = Branch.open(parent_branch_path)
468
if parent_branch.base == local_branch.base:
469
parent_branch = local_branch
471
local_extra, remote_extra = find_unmerged(local_branch,parent_branch)
473
if local_extra or remote_extra:
475
## def log_revision_one_line_text(log_revision):
476
## """ Generates one line description of log_revison ended with end of line."""
477
## revision = log_revision.rev
478
## txt = "- %s (%s)\n" % (revision.get_summary(), revision.committer, )
479
## txt = txt.replace("<"," ") # Seems < > chars are expected to be xml tags ...
480
## txt = txt.replace(">"," ")
485
dlg_txt += _i18n('%d local extra revision(s). \n') % (len(local_extra),)
486
## NOTE: We do not want such ugly info about missing revisions
487
## Revision Browser should be used there
488
## max_revisions = 10
489
## for log_revision in iter_log_revisions(local_extra, local_branch.repository, verbose=1):
490
## dlg_txt += log_revision_one_line_text(log_revision)
491
## if max_revisions <= 0:
492
## dlg_txt += _i18n("more ... \n")
494
## max_revisions -= 1
497
dlg_txt += _i18n('%d local missing revision(s).\n') % (len(remote_extra),)
498
## max_revisions = 10
499
## for log_revision in iter_log_revisions(remote_extra, parent_branch.repository, verbose=1):
500
## dlg_txt += log_revision_one_line_text(log_revision)
501
## if max_revisions <= 0:
502
## dlg_txt += _i18n("more ... \n")
504
## max_revisions -= 1
506
info_dialog(_i18n('There are missing revisions'),
284
remote_branch = Branch.open(other_branch)
286
if remote_branch.base == local_branch.base:
287
remote_branch = local_branch
289
ret = len(local_branch.missing_revisions(remote_branch))
292
info_dialog(_('There are missing revisions'),
293
_('%d revision(s) missing.') % ret)
509
info_dialog(_i18n('Local branch up to date'),
510
_i18n('There are no missing revisions.'))
295
info_dialog(_('Local branch up to date'),
296
_('There are no missing revisions.'))
513
299
def on_menuitem_branch_pull_activate(self, widget):
551
331
def on_menuitem_branch_revert_activate(self, widget):
552
332
""" Branch/Revert all changes menu handler. """
553
ret = self.wt.revert(None)
333
ret = self.wt.revert([])
555
warning_dialog(_i18n('Conflicts detected'),
556
_i18n('Please have a look at the working tree before continuing.'))
335
warning_dialog(_('Conflicts detected'),
336
_('Please have a look at the working tree before continuing.'))
558
info_dialog(_i18n('Revert successful'),
559
_i18n('All files reverted to last revision.'))
338
info_dialog(_('Revert successful'),
339
_('All files reverted to last revision.'))
560
340
self.refresh_right()
562
342
def on_menuitem_branch_status_activate(self, widget):
563
343
""" Branch/Status... menu handler. """
564
from bzrlib.plugins.gtk.status import StatusDialog
565
status = StatusDialog(self.wt, self.wtpath)
566
response = status.run()
567
if response != gtk.RESPONSE_NONE:
344
from status import OliveStatus
345
status = OliveStatus(self.wt, self.wtpath)
570
349
def on_menuitem_branch_initialize_activate(self, widget):
571
350
""" Initialize current directory. """
572
init = InitDialog(self.path, self.window)
573
response = init.run()
574
if response != gtk.RESPONSE_NONE:
577
if response == gtk.RESPONSE_OK:
582
def on_menuitem_branch_tags_activate(self, widget):
583
""" Branch/Tags... menu handler. """
584
from bzrlib.plugins.gtk.tags import TagsWindow
586
window = TagsWindow(self.wt.branch, self.window)
351
import bzrlib.bzrdir as bzrdir
353
if not os.path.exists(self.path):
357
existing_bzrdir = bzrdir.BzrDir.open(self.path)
358
except bzrerrors.NotBranchError:
359
bzrdir.BzrDir.create_branch_convenience(self.path)
588
window = TagsWindow(self.remote_branch, self.window)
361
if existing_bzrdir.has_branch():
362
if existing_bzrdir.has_workingtree():
363
raise bzrerrors.AlreadyBranchError(self.path)
365
raise bzrerrors.BranchExistsWithoutWorkingTree(self.path)
367
existing_bzrdir.create_branch()
368
existing_bzrdir.create_workingtree()
369
info_dialog(_('Initialize successful'),
370
_('Directory successfully initialized.'))
591
373
def on_menuitem_file_annotate_activate(self, widget):
592
374
""" File/Annotate... menu handler. """
593
375
if self.get_selected_right() is None:
594
error_dialog(_i18n('No file was selected'),
595
_i18n('Please select a file from the list.'))
376
error_dialog(_('No file was selected'),
377
_('Please select a file from the list.'))
598
380
branch = self.wt.branch
599
381
file_id = self.wt.path2id(self.wt.relpath(os.path.join(self.path, self.get_selected_right())))
601
window = GAnnotateWindow(all=False, plain=False, parent=self.window)
383
window = GAnnotateWindow(all=False, plain=False)
602
384
window.set_title(os.path.join(self.path, self.get_selected_right()) + " - Annotate")
603
385
config = GAnnotateConfig(window)
611
def on_menuitem_file_bookmark_activate(self, widget):
612
""" File/Bookmark current directory menu handler. """
613
if self.pref.add_bookmark(self.path):
614
info_dialog(_i18n('Bookmark successfully added'),
615
_i18n('The current directory was bookmarked. You can reach\nit by selecting it from the left panel.'))
618
warning_dialog(_i18n('Location already bookmarked'),
619
_i18n('The current directory is already bookmarked.\nSee the left panel for reference.'))
623
393
def on_menuitem_file_make_directory_activate(self, widget):
624
394
""" File/Make directory... menu handler. """
625
from bzrlib.plugins.gtk.olive.mkdir import MkdirDialog
626
mkdir = MkdirDialog(self.wt, self.wtpath, self.window)
627
response = mkdir.run()
629
if response == gtk.RESPONSE_OK:
395
from mkdir import OliveMkdir
396
mkdir = OliveMkdir(self.wt, self.wtpath)
632
399
def on_menuitem_file_move_activate(self, widget):
633
400
""" File/Move... menu handler. """
634
from bzrlib.plugins.gtk.olive.move import MoveDialog
635
move = MoveDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
636
response = move.run()
638
if response == gtk.RESPONSE_OK:
401
from move import OliveMove
402
move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
641
405
def on_menuitem_file_rename_activate(self, widget):
642
406
""" File/Rename... menu handler. """
643
from bzrlib.plugins.gtk.olive.rename import RenameDialog
644
rename = RenameDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
645
response = rename.run()
647
if response == gtk.RESPONSE_OK:
407
from rename import OliveRename
408
rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
650
411
def on_menuitem_remove_file_activate(self, widget):
651
412
""" Remove (unversion) selected file. """
652
from bzrlib.plugins.gtk.olive.remove import RemoveDialog
653
remove = RemoveDialog(self.wt, self.wtpath,
413
from remove import OliveRemoveDialog
414
remove = OliveRemoveDialog(self.wt, self.wtpath,
654
415
selected=self.get_selected_right(),
655
416
parent=self.window)
656
417
response = remove.run()
705
457
if self.path is not None:
706
458
self.refresh_right()
708
def on_menuitem_view_show_ignored_files_activate(self, widget):
709
""" Hide/Show ignored files menu handler. """
710
self.pref.set_preference('ignored_files', widget.get_active())
711
if self.path is not None:
714
460
def on_treeview_left_button_press_event(self, widget, event):
715
""" Occurs when somebody clicks in the bookmark list. """
716
treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
717
treeselection = widget.get_selection()
718
if treepathpos is not None:
719
treeselection.select_path(treepathpos[0])
720
if event.button == 1:
721
newdir = self.get_selected_left()
725
if self.set_path(newdir):
727
elif event.button == 3:
728
# Don't show context with nothing selected
729
if self.get_selected_left() == None:
733
from menu import OliveMenu
734
menu = OliveMenu(path=self.get_path(),
735
selected=self.get_selected_left(),
738
menu.left_context_menu().popup(None, None, None, 0,
741
if treeselection is not None:
742
treeselection.unselect_all()
461
""" Occurs when somebody right-clicks in the bookmark list. """
462
if event.button == 3:
463
# Don't show context with nothing selected
464
if self.get_selected_left() == None:
468
from menu import OliveMenu
469
menu = OliveMenu(path=self.get_path(),
470
selected=self.get_selected_left(),
473
menu.left_context_menu().popup(None, None, None, 0,
744
476
def on_treeview_left_row_activated(self, treeview, path, view_column):
745
477
""" Occurs when somebody double-clicks or enters an item in the
749
481
if newdir == None:
752
if self.set_path(newdir):
484
self.set_path(newdir)
755
487
def on_treeview_right_button_press_event(self, widget, event):
756
""" Occurs when somebody clicks in the file list. """
757
treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
758
if event.button == 1:
759
if treepathpos is None and widget.get_selection is not None:
760
treeselection = widget.get_selection()
761
treeselection.unselect_all()
762
elif event.button == 3:
763
treeselection = widget.get_selection()
764
if treepathpos is not None:
765
treeselection.select_path(treepathpos[0])
767
if treeselection is not None:
768
treeselection.unselect_all()
488
""" Occurs when somebody right-clicks in the file list. """
489
if event.button == 3:
770
491
from menu import OliveMenu
771
492
menu = OliveMenu(path=self.get_path(),
772
493
selected=self.get_selected_right(),
774
495
# get the menu items
775
m_open = menu.ui.get_widget('/context_right/open')
776
496
m_add = menu.ui.get_widget('/context_right/add')
777
497
m_remove = menu.ui.get_widget('/context_right/remove')
778
m_remove_and_delete = menu.ui.get_widget('/context_right/remove_and_delete')
779
498
m_rename = menu.ui.get_widget('/context_right/rename')
780
499
m_revert = menu.ui.get_widget('/context_right/revert')
781
500
m_commit = menu.ui.get_widget('/context_right/commit')
782
m_annotate = menu.ui.get_widget('/context_right/annotate')
783
501
m_diff = menu.ui.get_widget('/context_right/diff')
784
502
# check if we're in a branch
786
504
from bzrlib.branch import Branch
787
505
Branch.open_containing(self.get_path())
789
m_open.set_sensitive(False)
790
m_add.set_sensitive(False)
791
m_remove.set_sensitive(False)
792
m_remove_and_delete.set_sensitive(False)
793
m_rename.set_sensitive(False)
794
m_revert.set_sensitive(False)
795
m_commit.set_sensitive(False)
796
m_annotate.set_sensitive(False)
797
m_diff.set_sensitive(False)
799
if treepathpos is None:
800
m_open.set_sensitive(False)
801
m_add.set_sensitive(False)
802
m_remove.set_sensitive(False)
803
m_remove_and_delete.set_sensitive(False)
804
m_rename.set_sensitive(False)
805
m_annotate.set_sensitive(False)
806
m_diff.set_sensitive(False)
807
m_revert.set_sensitive(False)
809
m_open.set_sensitive(True)
810
m_add.set_sensitive(True)
811
m_remove.set_sensitive(True)
812
m_remove_and_delete.set_sensitive(True)
813
m_rename.set_sensitive(True)
814
m_annotate.set_sensitive(True)
815
m_diff.set_sensitive(True)
816
m_revert.set_sensitive(True)
817
m_commit.set_sensitive(True)
506
m_add.set_sensitive(True)
507
m_remove.set_sensitive(True)
508
m_rename.set_sensitive(True)
509
m_revert.set_sensitive(True)
510
m_commit.set_sensitive(True)
511
m_diff.set_sensitive(True)
818
512
except bzrerrors.NotBranchError:
819
if treepathpos is None:
820
m_open.set_sensitive(False)
822
m_open.set_sensitive(True)
823
513
m_add.set_sensitive(False)
824
514
m_remove.set_sensitive(False)
825
m_remove_and_delete.set_sensitive(False)
826
515
m_rename.set_sensitive(False)
827
516
m_revert.set_sensitive(False)
828
517
m_commit.set_sensitive(False)
829
m_annotate.set_sensitive(False)
830
518
m_diff.set_sensitive(False)
833
menu.right_context_menu().popup(None, None, None, 0,
836
menu.remote_context_menu().popup(None, None, None, 0,
520
menu.right_context_menu().popup(None, None, None, 0,
839
523
def on_treeview_right_row_activated(self, treeview, path, view_column):
840
524
""" Occurs when somebody double-clicks or enters an item in the
940
633
delta = self.wt.changes_from(tree2, want_unchanged=True)
942
635
# Add'em to the ListStore
945
statinfo = os.stat(self.path + os.sep + item)
947
if e.errno in self.acceptable_errors:
951
liststore.append([ gtk.STOCK_DIRECTORY,
959
self._format_date(statinfo.st_mtime),
637
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
961
638
for item in files:
962
639
status = 'unknown'
964
640
if not self.notbranch:
965
641
filename = self.wt.relpath(self.path + os.sep + item)
970
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
971
if rpathnew == filename:
974
for rpath, id, kind in delta.added:
975
if rpath == filename:
978
for rpath, id, kind in delta.removed:
979
if rpath == filename:
982
for rpath, id, kind, text_modified, meta_modified in delta.modified:
983
if rpath == filename:
986
for rpath, id, kind in delta.unchanged:
987
if rpath == filename:
990
for rpath, file_class, kind, id, entry in self.wt.list_files():
991
if rpath == filename and file_class == 'I':
643
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
644
if rpathnew == filename:
646
for rpath, id, kind in delta.added:
647
if rpath == filename:
649
for rpath, id, kind in delta.removed:
650
if rpath == filename:
652
for rpath, id, kind, text_modified, meta_modified in delta.modified:
653
if rpath == filename:
655
for rpath, id, kind in delta.unchanged:
656
if rpath == filename:
658
for rpath, file_class, kind, id, entry in self.wt.list_files():
659
if rpath == filename and file_class == 'I':
663
# status = fileops.status(path + os.sep + item)
664
#except errors.PermissionDenied:
996
667
if status == 'renamed':
997
st = _i18n('renamed')
998
669
elif status == 'removed':
999
st = _i18n('removed')
1000
671
elif status == 'added':
1002
673
elif status == 'modified':
1003
st = _i18n('modified')
1004
675
elif status == 'unchanged':
1005
st = _i18n('unchanged')
1006
677
elif status == 'ignored':
1007
st = _i18n('ignored')
1009
st = _i18n('unknown')
1012
statinfo = os.stat(self.path + os.sep + item)
1014
if e.errno in self.acceptable_errors:
1018
liststore.append([gtk.STOCK_FILE,
1023
str(statinfo.st_size), # NOTE: if int used there it will fail for large files (size expressed as long int)
1024
self._format_size(statinfo.st_size),
1026
self._format_date(statinfo.st_mtime),
681
liststore.append([gtk.STOCK_FILE, item, st])
1029
683
# Create the columns and add them to the TreeView
1030
684
self.treeview_right.set_model(liststore)
1031
self._tvcolumn_filename = gtk.TreeViewColumn(_i18n('Filename'))
1032
self._tvcolumn_status = gtk.TreeViewColumn(_i18n('Status'))
1033
self._tvcolumn_size = gtk.TreeViewColumn(_i18n('Size'))
1034
self._tvcolumn_mtime = gtk.TreeViewColumn(_i18n('Last modified'))
1035
self.treeview_right.append_column(self._tvcolumn_filename)
1036
self.treeview_right.append_column(self._tvcolumn_status)
1037
self.treeview_right.append_column(self._tvcolumn_size)
1038
self.treeview_right.append_column(self._tvcolumn_mtime)
685
tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
686
tvcolumn_status = gtk.TreeViewColumn(_('Status'))
687
self.treeview_right.append_column(tvcolumn_filename)
688
self.treeview_right.append_column(tvcolumn_status)
1040
690
# Set up the cells
1041
691
cellpb = gtk.CellRendererPixbuf()
1042
692
cell = gtk.CellRendererText()
1043
self._tvcolumn_filename.pack_start(cellpb, False)
1044
self._tvcolumn_filename.pack_start(cell, True)
1045
self._tvcolumn_filename.set_attributes(cellpb, stock_id=0)
1046
self._tvcolumn_filename.add_attribute(cell, 'text', 2)
1047
self._tvcolumn_status.pack_start(cell, True)
1048
self._tvcolumn_status.add_attribute(cell, 'text', 3)
1049
self._tvcolumn_size.pack_start(cell, True)
1050
self._tvcolumn_size.add_attribute(cell, 'text', 6)
1051
self._tvcolumn_mtime.pack_start(cell, True)
1052
self._tvcolumn_mtime.add_attribute(cell, 'text', 8)
1054
# Set up the properties of the TreeView
1055
self.treeview_right.set_headers_visible(True)
1056
self.treeview_right.set_headers_clickable(True)
1057
self.treeview_right.set_search_column(1)
1058
self._tvcolumn_filename.set_resizable(True)
1059
self._tvcolumn_status.set_resizable(True)
1060
self._tvcolumn_size.set_resizable(True)
1061
self._tvcolumn_mtime.set_resizable(True)
1063
liststore.set_sort_func(13, self._sort_filelist_callback, None)
1064
liststore.set_sort_column_id(13, gtk.SORT_ASCENDING)
1065
self._tvcolumn_filename.set_sort_column_id(13)
1066
self._tvcolumn_status.set_sort_column_id(3)
1067
self._tvcolumn_size.set_sort_column_id(5)
1068
self._tvcolumn_mtime.set_sort_column_id(7)
693
tvcolumn_filename.pack_start(cellpb, False)
694
tvcolumn_filename.pack_start(cell, True)
695
tvcolumn_filename.set_attributes(cellpb, stock_id=0)
696
tvcolumn_filename.add_attribute(cell, 'text', 1)
697
tvcolumn_status.pack_start(cell, True)
698
tvcolumn_status.add_attribute(cell, 'text', 2)
1070
700
# Set sensitivity
1071
701
self.set_sensitivity()
1073
def get_selected_fileid(self):
1074
""" Get the file_id of the selected file. """
1075
treeselection = self.treeview_right.get_selection()
1076
(model, iter) = treeselection.get_selected()
1081
return model.get_value(iter, 9)
1083
703
def get_selected_right(self):
1084
704
""" Get the selected filename. """
1085
705
treeselection = self.treeview_right.get_selection()
1103
723
def set_statusbar(self, message):
1104
724
""" Set the statusbar message. """
1105
self.window.statusbar.push(self.context_id, message)
725
self.statusbar.push(self.context_id, message)
1107
727
def clear_statusbar(self):
1108
728
""" Clean the last message from the statusbar. """
1109
self.window.statusbar.pop(self.context_id)
729
self.statusbar.pop(self.context_id)
1111
731
def set_sensitivity(self):
1112
732
""" Set menu and toolbar sensitivity. """
1114
self.window.set_view_to_localbranch(self.notbranch)
1116
self.window.set_view_to_remotebranch()
733
self.menuitem_branch_init.set_sensitive(self.notbranch)
734
self.menuitem_branch_get.set_sensitive(self.notbranch)
735
self.menuitem_branch_checkout.set_sensitive(self.notbranch)
736
self.menuitem_branch_pull.set_sensitive(not self.notbranch)
737
self.menuitem_branch_push.set_sensitive(not self.notbranch)
738
self.menuitem_branch_revert.set_sensitive(not self.notbranch)
739
self.menuitem_branch_merge.set_sensitive(not self.notbranch)
740
self.menuitem_branch_commit.set_sensitive(not self.notbranch)
741
self.menuitem_branch_status.set_sensitive(not self.notbranch)
742
self.menuitem_branch_missing.set_sensitive(not self.notbranch)
743
self.menuitem_stats.set_sensitive(not self.notbranch)
744
self.menuitem_add_files.set_sensitive(not self.notbranch)
745
self.menuitem_remove_files.set_sensitive(not self.notbranch)
746
self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
747
self.menuitem_file_rename.set_sensitive(not self.notbranch)
748
self.menuitem_file_move.set_sensitive(not self.notbranch)
749
self.menuitem_file_annotate.set_sensitive(not self.notbranch)
750
#self.menutoolbutton_diff.set_sensitive(True)
751
self.toolbutton_diff.set_sensitive(not self.notbranch)
752
self.toolbutton_log.set_sensitive(not self.notbranch)
753
self.toolbutton_commit.set_sensitive(not self.notbranch)
754
self.toolbutton_pull.set_sensitive(not self.notbranch)
755
self.toolbutton_push.set_sensitive(not self.notbranch)
1118
757
def refresh_left(self):
1119
758
""" Refresh the bookmark list. """
1146
782
def refresh_right(self, path=None):
1147
783
""" Refresh the file list. """
1150
from bzrlib.workingtree import WorkingTree
1153
path = self.get_path()
1155
# A workaround for double-clicking Bookmarks
1156
if not os.path.exists(path):
1159
# Get ListStore and clear it
1160
liststore = self.treeview_right.get_model()
1163
# Show Status column
1164
self._tvcolumn_status.set_visible(True)
1169
# Fill the appropriate lists
1170
dotted_files = self.pref.get_preference('dotted_files', 'bool')
1171
ignored_files = self.pref.get_preference('ignored_files', 'bool')
1173
for item in os.listdir(path):
1174
if not dotted_files and item[0] == '.':
1176
if os.path.isdir(path + os.sep + item):
1181
# Try to open the working tree
1184
tree1 = WorkingTree.open_containing(path)[0]
1185
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
784
from bzrlib.workingtree import WorkingTree
787
path = self.get_path()
789
# A workaround for double-clicking Bookmarks
790
if not os.path.exists(path):
793
# Get ListStore and clear it
794
liststore = self.treeview_right.get_model()
800
# Fill the appropriate lists
801
dotted_files = self.pref.get_preference('dotted_files', 'bool')
802
for item in os.listdir(path):
803
if not dotted_files and item[0] == '.':
805
if os.path.isdir(path + os.sep + item):
814
# add updir link to dirs
815
self._add_updir_to_dirlist(dirs, path)
817
# Try to open the working tree
820
tree1 = WorkingTree.open_containing(path)[0]
821
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
825
branch = tree1.branch
826
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
828
delta = tree1.changes_from(tree2, want_unchanged=True)
830
# Add'em to the ListStore
832
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
1188
835
if not notbranch:
1189
branch = tree1.branch
1190
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
1192
delta = tree1.changes_from(tree2, want_unchanged=True)
1194
# Add'em to the ListStore
1197
statinfo = os.stat(self.path + os.sep + item)
1199
if e.errno in self.acceptable_errors:
1203
liststore.append([gtk.STOCK_DIRECTORY,
1211
self._format_date(statinfo.st_mtime),
1217
filename = tree1.relpath(path + os.sep + item)
1222
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1223
if rpathnew == filename:
1226
for rpath, id, kind in delta.added:
1227
if rpath == filename:
1230
for rpath, id, kind in delta.removed:
1231
if rpath == filename:
1234
for rpath, id, kind, text_modified, meta_modified in delta.modified:
1235
if rpath == filename:
1238
for rpath, id, kind in delta.unchanged:
1239
if rpath == filename:
1240
status = 'unchanged'
1242
for rpath, file_class, kind, id, entry in self.wt.list_files():
1243
if rpath == filename and file_class == 'I':
1248
if status == 'renamed':
1249
st = _i18n('renamed')
1250
elif status == 'removed':
1251
st = _i18n('removed')
1252
elif status == 'added':
1254
elif status == 'modified':
1255
st = _i18n('modified')
1256
elif status == 'unchanged':
1257
st = _i18n('unchanged')
1258
elif status == 'ignored':
1259
st = _i18n('ignored')
1260
if not ignored_files:
1263
st = _i18n('unknown')
1266
statinfo = os.stat(self.path + os.sep + item)
1268
if e.errno in self.acceptable_errors:
1272
liststore.append([gtk.STOCK_FILE,
1277
str(statinfo.st_size),
1278
self._format_size(statinfo.st_size),
1280
self._format_date(statinfo.st_mtime),
1285
# Get ListStore and clear it
1286
liststore = self.treeview_right.get_model()
1289
# Hide Status column
1290
self._tvcolumn_status.set_visible(False)
1295
self._show_stock_image(gtk.STOCK_REFRESH)
1297
for (name, type) in self.remote_entries:
1298
if type.kind == 'directory':
1300
elif type.kind == 'file':
1304
""" Cache based on revision history. """
1305
def __init__(self, history):
1306
self._history = history
1308
def _lookup_revision(self, revid):
1309
for r in self._history:
1310
if r.revision_id == revid:
1312
rev = repo.get_revision(revid)
1313
self._history.append(rev)
1316
repo = self.remote_branch.repository
1318
revhistory = self.remote_branch.revision_history()
1320
revs = repo.get_revisions(revhistory)
1321
cache = HistoryCache(revs)
1322
except bzrerrors.InvalidHttpResponse:
1323
# Fallback to dummy algorithm, because of LP: #115209
1324
cache = HistoryCache([])
1327
if item.parent_id == self.remote_parent:
1328
rev = cache._lookup_revision(item.revision)
1329
liststore.append([ gtk.STOCK_DIRECTORY,
1337
self._format_date(rev.timestamp),
1340
while gtk.events_pending():
1341
gtk.main_iteration()
1344
if item.parent_id == self.remote_parent:
1345
rev = cache._lookup_revision(item.revision)
1346
liststore.append([ gtk.STOCK_FILE,
1351
str(item.text_size),
1352
self._format_size(item.text_size),
1354
self._format_date(rev.timestamp),
1357
while gtk.events_pending():
1358
gtk.main_iteration()
1360
self.image_location_error.destroy()
1362
# Columns should auto-size
1363
self.treeview_right.columns_autosize()
836
filename = tree1.relpath(path + os.sep + item)
838
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
839
if rpathnew == filename:
841
for rpath, id, kind in delta.added:
842
if rpath == filename:
844
for rpath, id, kind in delta.removed:
845
if rpath == filename:
847
for rpath, id, kind, text_modified, meta_modified in delta.modified:
848
if rpath == filename:
850
for rpath, id, kind in delta.unchanged:
851
if rpath == filename:
853
for rpath, file_class, kind, id, entry in self.wt.list_files():
854
if rpath == filename and file_class == 'I':
858
# status = fileops.status(path + os.sep + item)
859
#except errors.PermissionDenied:
862
if status == 'renamed':
864
elif status == 'removed':
866
elif status == 'added':
868
elif status == 'modified':
870
elif status == 'unchanged':
872
elif status == 'ignored':
876
liststore.append([gtk.STOCK_FILE, item, st])
878
# Add the ListStore to the TreeView
879
self.treeview_right.set_model(liststore)
1365
881
# Set sensitivity
1366
882
self.set_sensitivity()
1414
def _sort_filelist_callback(self, model, iter1, iter2, data):
1415
""" The sort callback for the file list, return values:
1420
name1 = model.get_value(iter1, 2)
1421
name2 = model.get_value(iter2, 2)
1423
if model.get_value(iter1, 1):
1424
# item1 is a directory
1425
if not model.get_value(iter2, 1):
1429
# both of them are directories, we compare their names
1432
elif name1 == name2:
1437
# item1 is not a directory
1438
if model.get_value(iter2, 1):
1442
# both of them are files, compare them
1445
elif name1 == name2:
1450
def _format_size(self, size):
1451
""" Format size to a human readable format. """
1453
return "%d[B]" % (size,)
1454
size = size / 1000.0
1456
for metric in ["kB","MB","GB","TB"]:
1459
size = size / 1000.0
1460
return "%.1f[%s]" % (size,metric)
1462
def _format_date(self, timestamp):
1463
""" Format the time (given in secs) to a human readable format. """
1464
return time.ctime(timestamp)
1466
def _is_remote_dir(self, location):
1467
""" Determine whether the given location is a directory or not. """
1469
# We're in local mode
1472
branch, path = Branch.open_containing(location)
1473
for (name, type) in self.remote_entries:
1474
if name == path and type.kind == 'directory':
1477
# Either it's not a directory or not in the inventory
1480
def _show_stock_image(self, stock_id):
1481
""" Show a stock image next to the location entry. """
1482
self.image_location_error.destroy()
1483
self.image_location_error = gtk.image_new_from_stock(stock_id, gtk.ICON_SIZE_BUTTON)
1484
self.hbox_location.pack_start(self.image_location_error, False, False, 0)
1485
if sys.platform == 'win32':
1486
self.hbox_location.reorder_child(self.image_location_error, 2)
1488
self.hbox_location.reorder_child(self.image_location_error, 1)
1489
self.image_location_error.show()
1490
while gtk.events_pending():
1491
gtk.main_iteration()
1493
931
import ConfigParser
1495
933
class Preferences:
1496
934
""" A class which handles Olive's preferences. """
1497
def __init__(self, path=None):
1498
936
""" Initialize the Preferences class. """
1499
937
# Some default options
1500
938
self.defaults = { 'strict_commit' : False,
1501
939
'dotted_files' : False,
1502
'ignored_files' : True,
1503
940
'window_width' : 700,
1504
941
'window_height' : 400,
1505
942
'window_x' : 40,