1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
gettext.install('olive-gtk')
34
from bzrlib.branch import Branch
35
import bzrlib.errors as errors
36
from bzrlib.workingtree import WorkingTree
38
# Olive GTK UI version
39
__version__ = '0.12.0'
41
from dialog import error_dialog, info_dialog
42
from guifiles import GLADEFILENAME
44
# import this classes only once
46
from bzrlib.plugins.gtk.viz.diffwin import DiffWindow
47
from bzrlib.plugins.gtk.viz.branchwin import BranchWindow
49
# olive+bzr-gtk not installed. try to import from sources
50
path = os.path.dirname(os.path.dirname(__file__))
51
if path not in sys.path:
53
from viz.diffwin import DiffWindow
54
from viz.branchwin import BranchWindow
58
""" The main Olive GTK frontend class. This is called when launching the
62
self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
64
self.window = self.toplevel.get_widget('window_main')
66
self.pref = OlivePreferences()
70
# Initialize the statusbar
71
self.statusbar = self.toplevel.get_widget('statusbar')
72
self.context_id = self.statusbar.get_context_id('olive')
75
self.window_main = self.toplevel.get_widget('window_main')
77
self.hpaned_main = self.toplevel.get_widget('hpaned_main')
79
self.treeview_left = self.toplevel.get_widget('treeview_left')
80
self.treeview_right = self.toplevel.get_widget('treeview_right')
81
# Get some important menu items
82
self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
83
self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
84
self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
85
self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
86
self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
87
self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
88
self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
89
self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
90
self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
91
self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
92
self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
93
self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
94
self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
95
self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
96
self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
97
self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
98
self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
99
self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
100
self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
101
# Get some toolbuttons
102
#self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
103
self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
104
self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
105
self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
106
self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
107
self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
108
# Get the drive selector
109
self.combobox_drive = gtk.combo_box_new_text()
110
self.combobox_drive.connect("changed", self._refresh_drives)
112
self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
115
# Dictionary for signal_autoconnect
116
dic = { "on_window_main_destroy": gtk.main_quit,
117
"on_window_main_delete_event": self.on_window_main_delete_event,
118
"on_quit_activate": self.on_window_main_delete_event,
119
"on_about_activate": self.on_about_activate,
120
"on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
121
"on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
122
"on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
123
"on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
124
"on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
125
"on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
126
"on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
127
"on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
128
"on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
129
"on_menuitem_branch_checkout_activate": self.on_menuitem_branch_checkout_activate,
130
"on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
131
"on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
132
"on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
133
"on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
134
"on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
135
"on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
136
"on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
137
"on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
138
"on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
139
"on_toolbutton_refresh_clicked": self.on_menuitem_view_refresh_activate,
140
"on_toolbutton_log_clicked": self.on_menuitem_stats_log_activate,
141
#"on_menutoolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
142
"on_toolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
143
"on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
144
"on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
145
"on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
146
"on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
147
"on_treeview_right_row_activated": self.on_treeview_right_row_activated,
148
"on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
149
"on_treeview_left_row_activated": self.on_treeview_left_row_activated }
151
# Connect the signals to the handlers
152
self.toplevel.signal_autoconnect(dic)
154
# Apply window size and position
155
width = self.pref.get_preference('window_width', 'int')
156
height = self.pref.get_preference('window_height', 'int')
157
self.window.resize(width, height)
158
x = self.pref.get_preference('window_x', 'int')
159
y = self.pref.get_preference('window_y', 'int')
160
self.window.move(x, y)
161
# Apply paned position
162
pos = self.pref.get_preference('paned_position', 'int')
163
self.hpaned_main.set_position(pos)
165
# Apply menu to the toolbutton
166
#menubutton = self.toplevel.get_widget('menutoolbutton_diff')
167
#menubutton.set_menu(handler.menu.toolbar_diff)
169
# Now we can show the window
172
# Show drive selector if under Win32
173
if sys.platform == 'win32':
174
self.vbox_main_right.pack_start(self.combobox_drive, False, True, 0)
175
self.vbox_main_right.reorder_child(self.combobox_drive, 0)
176
self.combobox_drive.show()
177
self.gen_hard_selector()
182
self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
184
self.set_path(os.getcwd())
187
def set_path(self, path):
189
self.notbranch = False
192
self.wt, self.wtpath = WorkingTree.open_containing(self.path)
193
except (errors.NotBranchError, errors.NoWorkingTree):
194
self.notbranch = True
196
self.statusbar.push(self.context_id, path)
201
def on_about_activate(self, widget):
202
from dialog import about
205
def on_menuitem_add_files_activate(self, widget):
206
""" Add file(s)... menu handler. """
207
from add import OliveAdd
208
add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
211
def on_menuitem_branch_get_activate(self, widget):
212
""" Branch/Get... menu handler. """
213
from branch import BranchDialog
214
branch = BranchDialog(self.get_path())
217
def on_menuitem_branch_checkout_activate(self, widget):
218
""" Branch/Checkout... menu handler. """
219
from checkout import OliveCheckout
220
checkout = OliveCheckout(self.get_path())
223
def on_menuitem_branch_commit_activate(self, widget):
224
""" Branch/Commit... menu handler. """
225
from commit import CommitDialog
226
commit = CommitDialog(self.wt, self.wtpath, self.notbranch)
229
def on_menuitem_branch_merge_activate(self, widget):
230
""" Branch/Merge... menu handler. """
231
from merge import MergeDialog
232
merge = MergeDialog(self.wt, self.wtpath)
235
def on_menuitem_branch_missing_revisions_activate(self, widget):
236
""" Branch/Missing revisions menu handler. """
237
local_branch = self.wt.branch
239
other_branch = local_branch.get_parent()
240
if other_branch is None:
241
error_dialog(_('Parent location is unknown'),
242
_('Cannot determine missing revisions if no parent location is known.'))
245
remote_branch = Branch.open(other_branch)
247
if remote_branch.base == local_branch.base:
248
remote_branch = local_branch
250
ret = len(local_branch.missing_revisions(remote_branch))
253
info_dialog(_('There are missing revisions'),
254
_('%d revision(s) missing.') % ret)
256
info_dialog(_('Local branch up to date'),
257
_('There are no missing revisions.'))
259
def on_menuitem_branch_pull_activate(self, widget):
260
""" Branch/Pull menu handler. """
261
branch_to = self.wt.branch
263
location = branch_to.get_parent()
265
error_dialog(_('Parent location is unknown'),
266
_('Pulling is not possible until there is a parent location.'))
270
branch_from = Branch.open(location)
271
except errors.NotBranchError:
272
error_dialog(_('Directory is not a branch'),
273
_('You can perform this action only in a branch.'))
275
if branch_to.get_parent() is None:
276
branch_to.set_parent(branch_from.base)
278
#old_rh = branch_to.revision_history()
279
#if tree_to is not None:
280
# tree_to.pull(branch_from)
282
# branch_to.pull(branch_from)
283
ret = branch_to.pull(branch_from)
285
info_dialog(_('Pull successful'), _('%d revision(s) pulled.') % ret)
287
def on_menuitem_branch_push_activate(self, widget):
288
""" Branch/Push... menu handler. """
289
from push import OlivePush
290
push = OlivePush(self.wt.branch)
293
def on_menuitem_branch_status_activate(self, widget):
294
""" Branch/Status... menu handler. """
295
from status import OliveStatus
296
status = OliveStatus(self.wt, self.wtpath)
299
def on_menuitem_branch_initialize_activate(self, widget):
300
""" Initialize current directory. """
301
import bzrlib.bzrdir as bzrdir
304
if not os.path.exists(self.path):
308
existing_bzrdir = bzrdir.BzrDir.open(self.path)
309
except errors.NotBranchError:
310
bzrdir.BzrDir.create_branch_convenience(self.path)
312
if existing_bzrdir.has_branch():
313
if existing_bzrdir.has_workingtree():
314
raise errors.AlreadyBranchError(self.path)
316
raise errors.BranchExistsWithoutWorkingTree(self.path)
318
existing_bzrdir.create_branch()
319
existing_bzrdir.create_workingtree()
320
except errors.AlreadyBranchError, errmsg:
321
error_dialog(_('Directory is already a branch'),
322
_('The current directory (%s) is already a branch.\nYou can start using it, or initialize another directory.') % errmsg)
323
except errors.BranchExistsWithoutWorkingTree, errmsg:
324
error_dialog(_('Branch without a working tree'),
325
_('The current directory (%s)\nis a branch without a working tree.') % errmsg)
327
info_dialog(_('Initialize successful'),
328
_('Directory successfully initialized.'))
331
def on_menuitem_file_make_directory_activate(self, widget):
332
""" File/Make directory... menu handler. """
333
from mkdir import OliveMkdir
334
mkdir = OliveMkdir(self.wt, self.wtpath)
337
def on_menuitem_file_move_activate(self, widget):
338
""" File/Move... menu handler. """
339
from move import OliveMove
340
move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
343
def on_menuitem_file_rename_activate(self, widget):
344
""" File/Rename... menu handler. """
345
from rename import OliveRename
346
rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
349
def on_menuitem_remove_file_activate(self, widget):
350
""" Remove (unversion) selected file. """
351
from remove import OliveRemove
352
remove = OliveRemove(self.wt, self.wtpath, self.get_selected_right())
355
def on_menuitem_stats_diff_activate(self, widget):
356
""" Statistics/Differences... menu handler. """
357
window = DiffWindow()
358
parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
359
window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
362
def on_menuitem_stats_infos_activate(self, widget):
363
""" Statistics/Informations... menu handler. """
364
from info import OliveInfo
365
info = OliveInfo(self.wt)
368
def on_menuitem_stats_log_activate(self, widget):
369
""" Statistics/Log... menu handler. """
370
window = BranchWindow()
371
window.set_branch(self.wt.branch, self.wt.branch.last_revision(), None)
374
def on_menuitem_view_refresh_activate(self, widget):
375
""" View/Refresh menu handler. """
376
# Refresh the left pane
378
# Refresh the right pane
381
def on_menuitem_view_show_hidden_files_activate(self, widget):
382
""" View/Show hidden files menu handler. """
383
self.pref.set_preference('dotted_files', widget.get_active())
384
if self.path is not None:
387
def on_treeview_left_button_press_event(self, widget, event):
388
""" Occurs when somebody right-clicks in the bookmark list. """
389
if event.button == 3:
390
# Don't show context with nothing selected
391
if self.get_selected_left() == None:
395
from menu import OliveMenu
396
menu = OliveMenu(self.get_path(), self.get_selected_left())
398
menu.left_context_menu().popup(None, None, None, 0,
401
def on_treeview_left_row_activated(self, treeview, path, view_column):
402
""" Occurs when somebody double-clicks or enters an item in the
405
newdir = self.get_selected_left()
409
self.set_path(newdir)
412
def on_treeview_right_button_press_event(self, widget, event):
413
""" Occurs when somebody right-clicks in the file list. """
414
if event.button == 3:
416
from menu import OliveMenu
417
menu = OliveMenu(self.get_path(), self.get_selected_right())
419
m_add = menu.ui.get_widget('/context_right/add')
420
m_remove = menu.ui.get_widget('/context_right/remove')
421
m_commit = menu.ui.get_widget('/context_right/commit')
422
m_diff = menu.ui.get_widget('/context_right/diff')
423
# check if we're in a branch
425
from bzrlib.branch import Branch
426
Branch.open_containing(self.get_path())
427
m_add.set_sensitive(True)
428
m_remove.set_sensitive(True)
429
m_commit.set_sensitive(True)
430
m_diff.set_sensitive(True)
431
except errors.NotBranchError:
432
m_add.set_sensitive(False)
433
m_remove.set_sensitive(False)
434
m_commit.set_sensitive(False)
435
m_diff.set_sensitive(False)
437
menu.right_context_menu().popup(None, None, None, 0,
440
def on_treeview_right_row_activated(self, treeview, path, view_column):
441
""" Occurs when somebody double-clicks or enters an item in the
443
from launch import launch
445
newdir = self.get_selected_right()
448
self.set_path(os.path.split(self.get_path())[0])
450
fullpath = os.path.join(self.get_path(), newdir)
451
if os.path.isdir(fullpath):
452
# selected item is an existant directory
453
self.set_path(fullpath)
459
def on_window_main_delete_event(self, widget, event=None):
460
""" Do some stuff before exiting. """
461
width, height = self.window_main.get_size()
462
self.pref.set_preference('window_width', width)
463
self.pref.set_preference('window_height', height)
464
x, y = self.window_main.get_position()
465
self.pref.set_preference('window_x', x)
466
self.pref.set_preference('window_y', y)
467
self.pref.set_preference('paned_position',
468
self.hpaned_main.get_position())
471
self.window_main.destroy()
473
def _load_left(self):
474
""" Load data into the left panel. (Bookmarks) """
476
treestore = gtk.TreeStore(str, str)
479
bookmarks = self.pref.get_bookmarks()
481
# Add them to the TreeStore
482
titer = treestore.append(None, [_('Bookmarks'), None])
483
for item in bookmarks:
484
title = self.pref.get_bookmark_title(item)
485
treestore.append(titer, [title, item])
487
# Create the column and add it to the TreeView
488
self.treeview_left.set_model(treestore)
489
tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
490
self.treeview_left.append_column(tvcolumn_bookmark)
493
cell = gtk.CellRendererText()
494
tvcolumn_bookmark.pack_start(cell, True)
495
tvcolumn_bookmark.add_attribute(cell, 'text', 0)
498
self.treeview_left.expand_all()
500
def _add_updir_to_dirlist(self, dirlist, curdir):
501
"""Add .. to the top of directories list if we not in root directory
503
:param dirlist: list of directories (modified in place)
504
:param curdir: current directory
510
if sys.platform == 'win32':
511
drive, tail = os.path.splitdrive(curdir)
512
if tail in ('', '/', '\\'):
518
# insert always as first element
519
dirlist.insert(0, '..')
521
def _load_right(self):
522
""" Load data into the right panel. (Filelist) """
524
liststore = gtk.ListStore(str, str, str)
529
# Fill the appropriate lists
530
dotted_files = self.pref.get_preference('dotted_files', 'bool')
531
for item in os.listdir(self.path):
532
if not dotted_files and item[0] == '.':
534
if os.path.isdir(self.path + os.sep + item):
543
# add updir link to dirs
544
self._add_updir_to_dirlist(dirs, self.path)
546
if not self.notbranch:
547
branch = self.wt.branch
548
tree2 = self.wt.branch.repository.revision_tree(branch.last_revision())
550
delta = self.wt.changes_from(tree2, want_unchanged=True)
552
# Add'em to the ListStore
554
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
557
if not self.notbranch:
558
filename = self.wt.relpath(self.path + os.sep + item)
560
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
561
if rpathnew == filename:
563
for rpath, id, kind in delta.added:
564
if rpath == filename:
566
for rpath, id, kind in delta.removed:
567
if rpath == filename:
569
for rpath, id, kind, text_modified, meta_modified in delta.modified:
570
if rpath == filename:
572
for rpath, id, kind in delta.unchanged:
573
if rpath == filename:
577
# status = fileops.status(path + os.sep + item)
578
#except errors.PermissionDenied:
581
if status == 'renamed':
583
elif status == 'removed':
585
elif status == 'added':
587
elif status == 'modified':
589
elif status == 'unchanged':
593
liststore.append([gtk.STOCK_FILE, item, st])
595
# Create the columns and add them to the TreeView
596
self.treeview_right.set_model(liststore)
597
tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
598
tvcolumn_status = gtk.TreeViewColumn(_('Status'))
599
self.treeview_right.append_column(tvcolumn_filename)
600
self.treeview_right.append_column(tvcolumn_status)
603
cellpb = gtk.CellRendererPixbuf()
604
cell = gtk.CellRendererText()
605
tvcolumn_filename.pack_start(cellpb, False)
606
tvcolumn_filename.pack_start(cell, True)
607
tvcolumn_filename.set_attributes(cellpb, stock_id=0)
608
tvcolumn_filename.add_attribute(cell, 'text', 1)
609
tvcolumn_status.pack_start(cell, True)
610
tvcolumn_status.add_attribute(cell, 'text', 2)
613
self.set_sensitivity()
615
def get_selected_right(self):
616
""" Get the selected filename. """
617
treeselection = self.treeview_right.get_selection()
618
(model, iter) = treeselection.get_selected()
623
return model.get_value(iter, 1)
625
def get_selected_left(self):
626
""" Get the selected bookmark. """
627
treeselection = self.treeview_left.get_selection()
628
(model, iter) = treeselection.get_selected()
633
return model.get_value(iter, 1)
635
def set_statusbar(self, message):
636
""" Set the statusbar message. """
637
self.statusbar.push(self.context_id, message)
639
def clear_statusbar(self):
640
""" Clean the last message from the statusbar. """
641
self.statusbar.pop(self.context_id)
643
def set_sensitivity(self):
644
""" Set menu and toolbar sensitivity. """
645
self.menuitem_branch_init.set_sensitive(self.notbranch)
646
self.menuitem_branch_get.set_sensitive(self.notbranch)
647
self.menuitem_branch_checkout.set_sensitive(self.notbranch)
648
self.menuitem_branch_pull.set_sensitive(not self.notbranch)
649
self.menuitem_branch_push.set_sensitive(not self.notbranch)
650
self.menuitem_branch_merge.set_sensitive(not self.notbranch)
651
self.menuitem_branch_commit.set_sensitive(not self.notbranch)
652
self.menuitem_branch_status.set_sensitive(not self.notbranch)
653
self.menuitem_branch_missing.set_sensitive(not self.notbranch)
654
self.menuitem_stats.set_sensitive(not self.notbranch)
655
self.menuitem_add_files.set_sensitive(not self.notbranch)
656
self.menuitem_remove_files.set_sensitive(not self.notbranch)
657
self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
658
self.menuitem_file_rename.set_sensitive(not self.notbranch)
659
self.menuitem_file_move.set_sensitive(not self.notbranch)
660
#self.menutoolbutton_diff.set_sensitive(True)
661
self.toolbutton_diff.set_sensitive(not self.notbranch)
662
self.toolbutton_log.set_sensitive(not self.notbranch)
663
self.toolbutton_commit.set_sensitive(not self.notbranch)
664
self.toolbutton_pull.set_sensitive(not self.notbranch)
665
self.toolbutton_push.set_sensitive(not self.notbranch)
667
def refresh_left(self):
668
""" Refresh the bookmark list. """
670
# Get TreeStore and clear it
671
treestore = self.treeview_left.get_model()
674
# Re-read preferences
678
bookmarks = self.pref.get_bookmarks()
680
# Add them to the TreeStore
681
titer = treestore.append(None, [_('Bookmarks'), None])
682
for item in bookmarks:
683
title = self.pref.get_bookmark_title(item)
684
treestore.append(titer, [title, item])
686
# Add the TreeStore to the TreeView
687
self.treeview_left.set_model(treestore)
690
self.treeview_left.expand_all()
692
def refresh_right(self, path=None):
693
""" Refresh the file list. """
694
from bzrlib.workingtree import WorkingTree
697
path = self.get_path()
699
# A workaround for double-clicking Bookmarks
700
if not os.path.exists(path):
703
# Get ListStore and clear it
704
liststore = self.treeview_right.get_model()
710
# Fill the appropriate lists
711
dotted_files = self.pref.get_preference('dotted_files', 'bool')
712
for item in os.listdir(path):
713
if not dotted_files and item[0] == '.':
715
if os.path.isdir(path + os.sep + item):
724
# add updir link to dirs
725
self._add_updir_to_dirlist(dirs, path)
727
# Try to open the working tree
730
tree1 = WorkingTree.open_containing(path)[0]
731
except (errors.NotBranchError, errors.NoWorkingTree):
733
except errors.PermissionDenied:
734
print "DEBUG: permission denied."
737
branch = tree1.branch
738
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
740
delta = tree1.changes_from(tree2, want_unchanged=True)
742
# Add'em to the ListStore
744
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
748
filename = tree1.relpath(path + os.sep + item)
750
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
751
if rpathnew == filename:
753
for rpath, id, kind in delta.added:
754
if rpath == filename:
756
for rpath, id, kind in delta.removed:
757
if rpath == filename:
759
for rpath, id, kind, text_modified, meta_modified in delta.modified:
760
if rpath == filename:
762
for rpath, id, kind in delta.unchanged:
763
if rpath == filename:
767
# status = fileops.status(path + os.sep + item)
768
#except errors.PermissionDenied:
771
if status == 'renamed':
773
elif status == 'removed':
775
elif status == 'added':
777
elif status == 'modified':
779
elif status == 'unchanged':
783
liststore.append([gtk.STOCK_FILE, item, st])
785
# Add the ListStore to the TreeView
786
self.treeview_right.set_model(liststore)
789
self.set_sensitivity()
791
def _harddisks(self):
792
""" Returns hard drive letters under Win32. """
797
if sys.platform == 'win32':
798
print "pyWin32 modules needed to run Olive on Win32."
804
for drive in string.ascii_uppercase:
805
if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
806
driveletters.append(drive+':')
809
def gen_hard_selector(self):
810
""" Generate the hard drive selector under Win32. """
811
drives = self._harddisks()
813
self.combobox_drive.append_text(drive)
815
def _refresh_drives(self, combobox):
816
model = combobox.get_model()
817
active = combobox.get_active()
819
drive = model[active][0]
820
self.set_path(drive + '\\')
821
self.refresh_right(drive + '\\')
825
class OlivePreferences:
826
""" A class which handles Olive's preferences. """
828
""" Initialize the Preferences class. """
829
# Some default options
830
self.defaults = { 'strict_commit' : False,
831
'dotted_files' : False,
832
'window_width' : 700,
833
'window_height' : 400,
836
'paned_position': 200 }
838
# Create a config parser object
839
self.config = ConfigParser.RawConfigParser()
841
# Load the configuration
844
def _get_default(self, option):
845
""" Get the default option for a preference. """
847
ret = self.defaults[option]
854
""" Refresh the configuration. """
855
# First write out the changes
857
# Then load the configuration again
861
""" Just read the configuration. """
862
if sys.platform == 'win32':
863
# Windows - no dotted files
864
self.config.read([os.path.expanduser('~/olive.conf')])
866
self.config.read([os.path.expanduser('~/.olive.conf')])
869
""" Write the configuration to the appropriate files. """
870
if sys.platform == 'win32':
871
# Windows - no dotted files
872
fp = open(os.path.expanduser('~/olive.conf'), 'w')
873
self.config.write(fp)
876
fp = open(os.path.expanduser('~/.olive.conf'), 'w')
877
self.config.write(fp)
880
def get_bookmarks(self):
881
""" Return the list of bookmarks. """
882
bookmarks = self.config.sections()
883
if self.config.has_section('preferences'):
884
bookmarks.remove('preferences')
887
def add_bookmark(self, path):
888
""" Add bookmark. """
890
self.config.add_section(path)
891
except ConfigParser.DuplicateSectionError:
896
def get_bookmark_title(self, path):
897
""" Get bookmark title. """
899
ret = self.config.get(path, 'title')
900
except ConfigParser.NoOptionError:
905
def set_bookmark_title(self, path, title):
906
""" Set bookmark title. """
907
self.config.set(path, 'title', title)
909
def remove_bookmark(self, path):
910
""" Remove bookmark. """
911
return self.config.remove_section(path)
913
def set_preference(self, option, value):
914
""" Set the value of the given option. """
920
if self.config.has_section('preferences'):
921
self.config.set('preferences', option, value)
923
self.config.add_section('preferences')
924
self.config.set('preferences', option, value)
926
def get_preference(self, option, kind='str'):
927
""" Get the value of the given option.
929
:param kind: str/bool/int/float. default: str
931
if self.config.has_option('preferences', option):
933
return self.config.getboolean('preferences', option)
935
return self.config.getint('preferences', option)
936
elif kind == 'float':
937
return self.config.getfloat('preferences', option)
939
return self.config.get('preferences', option)
942
return self._get_default(option)