16
14
# along with this program; if not, write to the Free Software
17
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
gettext.install('olive-gtk')
29
24
pygtk.require("2.0")
38
from bzrlib.branch import Branch
39
import bzrlib.errors as bzrerrors
40
from bzrlib.lazy_import import lazy_import
41
from bzrlib.ui import ui_factory
42
from bzrlib.workingtree import WorkingTree
44
from bzrlib.plugins.gtk import _i18n
45
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
46
from bzrlib.plugins.gtk.errors import show_bzr_error
47
from guifiles import GLADEFILENAME
49
from bzrlib.plugins.gtk.diff import DiffWindow
50
lazy_import(globals(), """
51
from bzrlib.plugins.gtk.viz import branchwin
53
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
54
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
55
from bzrlib.plugins.gtk.commit import CommitDialog
56
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
57
from bzrlib.plugins.gtk.initialize import InitDialog
58
from bzrlib.plugins.gtk.push import PushDialog
59
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
62
""" Display the AboutDialog. """
63
from bzrlib.plugins.gtk import __version__
64
from bzrlib.plugins.gtk.olive.guifiles import GLADEFILENAME
66
# Load AboutDialog description
67
dglade = gtk.glade.XML(GLADEFILENAME, 'aboutdialog')
68
dialog = dglade.get_widget('aboutdialog')
71
dialog.set_version(__version__)
72
dialog.set_authors([ _i18n("Lead Developer:"),
73
"Szilveszter Farkas <szilveszter.farkas@gmail.com>",
74
_i18n("Contributors:"),
75
"Jelmer Vernooij <jelmer@samba.org>",
76
"Mateusz Korniak <mateusz.korniak@ant.gliwice.pl>",
77
"Gary van der Merwe <garyvdm@gmail.com>" ])
78
dialog.set_artists([ "Simon Pascal Klein <klepas@klepas.org>",
79
"Jakub Steiner <jimmac@novell.com>" ])
34
from handler import OliveHandler
35
import bzrlib.errors as errors
37
# Olive GTK UI version
38
__version__ = '0.11.0'
86
41
""" The main Olive GTK frontend class. This is called when launching the
89
44
def __init__(self):
90
self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
46
if sys.platform == 'win32':
47
self.gladefile = os.path.dirname(sys.executable) + "/share/olive/olive.glade"
49
self.gladefile = "/usr/share/olive/olive.glade"
51
if not os.path.exists(self.gladefile):
52
# Load from current directory if not installed
53
self.gladefile = "olive.glade"
55
if not os.path.exists(self.gladefile):
57
print _('Glade file cannot be found.')
60
self.toplevel = gtk.glade.XML(self.gladefile, 'window_main', 'olive-gtk')
91
62
self.window = self.toplevel.get_widget('window_main')
92
self.pref = Preferences()
64
self.pref = OlivePreferences()
65
self.comm = OliveCommunicator(self.toplevel, self.pref)
66
handler = OliveHandler(self.gladefile, self.comm)
68
# Dictionary for signal_autoconnect
69
dic = { "on_window_main_destroy": gtk.main_quit,
70
"on_window_main_delete_event": handler.on_window_main_delete_event,
71
"on_quit_activate": handler.on_window_main_delete_event,
72
"on_about_activate": handler.on_about_activate,
73
"on_menuitem_add_files_activate": handler.on_menuitem_add_files_activate,
74
"on_menuitem_remove_file_activate": handler.on_menuitem_remove_file_activate,
75
"on_menuitem_file_make_directory_activate": handler.on_menuitem_file_make_directory_activate,
76
"on_menuitem_file_move_activate": handler.on_menuitem_file_move_activate,
77
"on_menuitem_file_rename_activate": handler.on_menuitem_file_rename_activate,
78
"on_menuitem_view_show_hidden_files_activate": handler.on_menuitem_view_show_hidden_files_activate,
79
"on_menuitem_view_refresh_activate": handler.on_menuitem_view_refresh_activate,
80
"on_menuitem_branch_initialize_activate": handler.on_menuitem_branch_initialize_activate,
81
"on_menuitem_branch_get_activate": handler.on_menuitem_branch_get_activate,
82
"on_menuitem_branch_checkout_activate": handler.on_menuitem_branch_checkout_activate,
83
"on_menuitem_branch_commit_activate": handler.on_menuitem_branch_commit_activate,
84
"on_menuitem_branch_push_activate": handler.on_menuitem_branch_push_activate,
85
"on_menuitem_branch_pull_activate": handler.on_menuitem_branch_pull_activate,
86
"on_menuitem_branch_status_activate": handler.on_menuitem_branch_status_activate,
87
"on_menuitem_branch_missing_revisions_activate": handler.on_menuitem_branch_missing_revisions_activate,
88
"on_menuitem_stats_diff_activate": handler.on_menuitem_stats_diff_activate,
89
"on_menuitem_stats_log_activate": handler.on_menuitem_stats_log_activate,
90
"on_menuitem_stats_infos_activate": handler.on_menuitem_stats_infos_activate,
91
"on_toolbutton_refresh_clicked": handler.on_menuitem_view_refresh_activate,
92
"on_toolbutton_log_clicked": handler.on_menuitem_stats_log_activate,
93
#"on_menutoolbutton_diff_clicked": handler.on_menuitem_stats_diff_activate,
94
"on_toolbutton_diff_clicked": handler.on_menuitem_stats_diff_activate,
95
"on_toolbutton_commit_clicked": handler.on_menuitem_branch_commit_activate,
96
"on_toolbutton_pull_clicked": handler.on_menuitem_branch_pull_activate,
97
"on_toolbutton_push_clicked": handler.on_menuitem_branch_push_activate,
98
"on_treeview_right_button_press_event": handler.on_treeview_right_button_press_event,
99
"on_treeview_right_row_activated": handler.on_treeview_right_row_activated,
100
"on_treeview_left_button_press_event": handler.on_treeview_left_button_press_event,
101
"on_treeview_left_row_activated": handler.on_treeview_left_row_activated }
103
# Connect the signals to the handlers
104
self.toplevel.signal_autoconnect(dic)
106
# Apply window size and position
107
width = self.pref.get_preference('window_width', 'int')
108
height = self.pref.get_preference('window_height', 'int')
109
self.window.resize(width, height)
110
x = self.pref.get_preference('window_x', 'int')
111
y = self.pref.get_preference('window_y', 'int')
112
self.window.move(x, y)
113
# Apply paned position
114
pos = self.pref.get_preference('paned_position', 'int')
115
self.comm.hpaned_main.set_position(pos)
117
# Apply menu to the toolbutton
118
#menubutton = self.toplevel.get_widget('menutoolbutton_diff')
119
#menubutton.set_menu(handler.menu.toolbar_diff)
121
# Now we can show the window
124
# Show drive selector if under Win32
125
if sys.platform == 'win32':
126
self.comm.vbox_main_right.pack_start(self.comm.combobox_drive, False, True, 0)
127
self.comm.vbox_main_right.reorder_child(self.comm.combobox_drive, 0)
128
self.comm.combobox_drive.show()
129
self.comm.gen_hard_selector()
131
# Load default data into the panels
132
self.treeview_left = self.toplevel.get_widget('treeview_left')
133
self.treeview_right = self.toplevel.get_widget('treeview_right')
138
self.comm.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
140
def _load_left(self):
141
""" Load data into the left panel. (Bookmarks) """
143
self.comm.set_busy(self.treeview_left)
146
treestore = gtk.TreeStore(str, str)
149
bookmarks = self.comm.pref.get_bookmarks()
151
# Add them to the TreeStore
152
titer = treestore.append(None, [_('Bookmarks'), None])
153
for item in bookmarks:
154
title = self.comm.pref.get_bookmark_title(item)
155
treestore.append(titer, [title, item])
157
# Create the column and add it to the TreeView
158
self.treeview_left.set_model(treestore)
159
tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
160
self.treeview_left.append_column(tvcolumn_bookmark)
163
cell = gtk.CellRendererText()
164
tvcolumn_bookmark.pack_start(cell, True)
165
tvcolumn_bookmark.add_attribute(cell, 'text', 0)
168
self.treeview_left.expand_all()
170
self.comm.set_busy(self.treeview_left, False)
172
def _load_right(self):
173
""" Load data into the right panel. (Filelist) """
174
from bzrlib.workingtree import WorkingTree
177
self.comm.set_busy(self.treeview_right)
180
liststore = gtk.ListStore(str, str, str)
185
# Fill the appropriate lists
186
path = self.comm.get_path()
187
dotted_files = self.pref.get_preference('dotted_files', 'bool')
188
for item in os.listdir(path):
189
if not dotted_files and item[0] == '.':
191
if os.path.isdir(path + os.sep + item):
200
# Try to open the working tree
203
tree1 = WorkingTree.open_containing(path)[0]
204
except errors.NotBranchError:
206
except errors.PermissionDenied:
207
print "DEBUG: permission denied."
210
branch = tree1.branch
211
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
213
delta = tree1.changes_from(tree2, want_unchanged=True)
215
# Add'em to the ListStore
217
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
221
filename = tree1.relpath(path + os.sep + item)
223
for rpath, id, kind, text_modified, meta_modified in delta.renamed:
224
if rpath == filename:
226
for rpath, id, kind in delta.added:
227
if rpath == filename:
229
for rpath, id, kind, text_modified, meta_modified in delta.removed:
230
if rpath == filename:
232
for rpath, id, kind, text_modified, meta_modified in delta.modified:
233
if rpath == filename:
235
for rpath, id, kind in delta.unchanged:
236
if rpath == filename:
240
# status = fileops.status(path + os.sep + item)
241
#except errors.PermissionDenied:
244
if status == 'renamed':
246
elif status == 'removed':
248
elif status == 'added':
250
elif status == 'modified':
252
elif status == 'unchanged':
256
liststore.append([gtk.STOCK_FILE, item, st])
258
# Create the columns and add them to the TreeView
259
self.treeview_right.set_model(liststore)
260
tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
261
tvcolumn_status = gtk.TreeViewColumn(_('Status'))
262
self.treeview_right.append_column(tvcolumn_filename)
263
self.treeview_right.append_column(tvcolumn_status)
266
cellpb = gtk.CellRendererPixbuf()
267
cell = gtk.CellRendererText()
268
tvcolumn_filename.pack_start(cellpb, False)
269
tvcolumn_filename.pack_start(cell, True)
270
tvcolumn_filename.set_attributes(cellpb, stock_id=0)
271
tvcolumn_filename.add_attribute(cell, 'text', 1)
272
tvcolumn_status.pack_start(cell, True)
273
tvcolumn_status.add_attribute(cell, 'text', 2)
275
# Check if current directory is a branch
277
# Activate some items
278
self.comm.menuitem_branch_init.set_sensitive(False)
279
self.comm.menuitem_branch_get.set_sensitive(True)
280
self.comm.menuitem_branch_checkout.set_sensitive(True)
281
self.comm.menuitem_branch_pull.set_sensitive(True)
282
self.comm.menuitem_branch_push.set_sensitive(True)
283
self.comm.menuitem_branch_commit.set_sensitive(True)
284
self.comm.menuitem_branch_status.set_sensitive(True)
285
self.comm.menuitem_branch_missing.set_sensitive(True)
286
self.comm.menuitem_stats.set_sensitive(True)
287
self.comm.menuitem_add_files.set_sensitive(True)
288
self.comm.menuitem_remove_files.set_sensitive(True)
289
self.comm.menuitem_file_make_directory.set_sensitive(True)
290
self.comm.menuitem_file_rename.set_sensitive(True)
291
self.comm.menuitem_file_move.set_sensitive(True)
292
#self.comm.menutoolbutton_diff.set_sensitive(True)
293
self.comm.toolbutton_diff.set_sensitive(True)
294
self.comm.toolbutton_log.set_sensitive(True)
295
self.comm.toolbutton_commit.set_sensitive(True)
296
self.comm.toolbutton_pull.set_sensitive(True)
297
self.comm.toolbutton_push.set_sensitive(True)
299
# Deactivate some items
300
self.comm.menuitem_branch_init.set_sensitive(True)
301
self.comm.menuitem_branch_get.set_sensitive(False)
302
self.comm.menuitem_branch_checkout.set_sensitive(False)
303
self.comm.menuitem_branch_pull.set_sensitive(False)
304
self.comm.menuitem_branch_push.set_sensitive(False)
305
self.comm.menuitem_branch_commit.set_sensitive(False)
306
self.comm.menuitem_branch_status.set_sensitive(False)
307
self.comm.menuitem_branch_missing.set_sensitive(False)
308
self.comm.menuitem_stats.set_sensitive(False)
309
self.comm.menuitem_add_files.set_sensitive(False)
310
self.comm.menuitem_remove_files.set_sensitive(False)
311
self.comm.menuitem_file_make_directory.set_sensitive(False)
312
self.comm.menuitem_file_rename.set_sensitive(False)
313
self.comm.menuitem_file_move.set_sensitive(False)
314
#self.comm.menutoolbutton_diff.set_sensitive(False)
315
self.comm.toolbutton_diff.set_sensitive(False)
316
self.comm.toolbutton_log.set_sensitive(False)
317
self.comm.toolbutton_commit.set_sensitive(False)
318
self.comm.toolbutton_pull.set_sensitive(False)
319
self.comm.toolbutton_push.set_sensitive(False)
321
# set cursor to default
322
self.comm.set_busy(self.treeview_right, False)
324
class OliveCommunicator:
325
""" This class is responsible for the communication between the different
327
def __init__(self, toplevel, pref):
328
# Get glade main component
329
self.toplevel = toplevel
333
self._path = os.getcwd()
95
335
# Initialize the statusbar
96
336
self.statusbar = self.toplevel.get_widget('statusbar')
137
369
self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
138
370
self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
139
371
self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
140
self.toolbutton_update = self.toplevel.get_widget('toolbutton_update')
141
372
# Get the drive selector
142
373
self.combobox_drive = gtk.combo_box_new_text()
143
374
self.combobox_drive.connect("changed", self._refresh_drives)
145
# Get the navigation widgets
146
self.hbox_location = self.toplevel.get_widget('hbox_location')
147
self.button_location_up = self.toplevel.get_widget('button_location_up')
148
self.button_location_jump = self.toplevel.get_widget('button_location_jump')
149
self.entry_location = self.toplevel.get_widget('entry_location')
150
self.image_location_error = self.toplevel.get_widget('image_location_error')
152
# Get the History widgets
153
self.check_history = self.toplevel.get_widget('checkbutton_history')
154
self.entry_history = self.toplevel.get_widget('entry_history_revno')
155
self.button_history = self.toplevel.get_widget('button_history_browse')
157
376
self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
159
# Dictionary for signal_autoconnect
160
dic = { "on_window_main_destroy": gtk.main_quit,
161
"on_window_main_delete_event": self.on_window_main_delete_event,
162
"on_quit_activate": self.on_window_main_delete_event,
163
"on_about_activate": self.on_about_activate,
164
"on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
165
"on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
166
"on_menuitem_file_bookmark_activate": self.on_menuitem_file_bookmark_activate,
167
"on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
168
"on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
169
"on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
170
"on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
171
"on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
172
"on_menuitem_view_show_ignored_files_activate": self.on_menuitem_view_show_ignored_files_activate,
173
"on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
174
"on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
175
"on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
176
"on_menuitem_branch_checkout_activate": self.on_menuitem_branch_checkout_activate,
177
"on_menuitem_branch_revert_activate": self.on_menuitem_branch_revert_activate,
178
"on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
179
"on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
180
"on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
181
"on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
182
"on_menuitem_branch_update_activate": self.on_menuitem_branch_update_activate,
183
"on_menuitem_branch_tags_activate": self.on_menuitem_branch_tags_activate,
184
"on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
185
"on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
186
"on_menuitem_branch_conflicts_activate": self.on_menuitem_branch_conflicts_activate,
187
"on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
188
"on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
189
"on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
190
"on_toolbutton_refresh_clicked": self.on_menuitem_view_refresh_activate,
191
"on_toolbutton_log_clicked": self.on_menuitem_stats_log_activate,
192
#"on_menutoolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
193
"on_toolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
194
"on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
195
"on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
196
"on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
197
"on_toolbutton_update_clicked": self.on_menuitem_branch_update_activate,
198
"on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
199
"on_treeview_right_row_activated": self.on_treeview_right_row_activated,
200
"on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
201
"on_treeview_left_button_release_event": self.on_treeview_left_button_release_event,
202
"on_treeview_left_row_activated": self.on_treeview_left_row_activated,
203
"on_button_location_up_clicked": self.on_button_location_up_clicked,
204
"on_button_location_jump_clicked": self.on_button_location_jump_clicked,
205
"on_entry_location_key_press_event": self.on_entry_location_key_press_event,
206
"on_checkbutton_history_toggled": self.on_checkbutton_history_toggled,
207
"on_entry_history_revno_key_press_event": self.on_entry_history_revno_key_press_event,
208
"on_button_history_browse_clicked": self.on_button_history_browse_clicked
211
# Connect the signals to the handlers
212
self.toplevel.signal_autoconnect(dic)
214
self._just_started = True
216
# Apply window size and position
217
width = self.pref.get_preference('window_width', 'int')
218
height = self.pref.get_preference('window_height', 'int')
219
self.window.resize(width, height)
220
x = self.pref.get_preference('window_x', 'int')
221
y = self.pref.get_preference('window_y', 'int')
222
self.window.move(x, y)
223
# Apply paned position
224
pos = self.pref.get_preference('paned_position', 'int')
225
self.hpaned_main.set_position(pos)
227
# Apply menu to the toolbutton
228
#menubutton = self.toplevel.get_widget('menutoolbutton_diff')
229
#menubutton.set_menu(handler.menu.toolbar_diff)
231
# Now we can show the window
234
# Show drive selector if under Win32
235
if sys.platform == 'win32':
236
self.hbox_location.pack_start(self.combobox_drive, False, False, 0)
237
self.hbox_location.reorder_child(self.combobox_drive, 1)
238
self.combobox_drive.show()
239
self.gen_hard_selector()
244
self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
245
self.menuitem_view_show_ignored_files.set_active(self.pref.get_preference('ignored_files', 'bool'))
247
# We're starting local
249
self.remote_branch = None
250
self.remote_path = None
251
self.remote_revision = None
253
self.set_path(os.getcwd())
256
self._just_started = False
258
def set_path(self, path, force_remote=False):
259
self.notbranch = False
262
# Forcing remote mode (reading data from inventory)
263
self._show_stock_image(gtk.STOCK_DISCONNECT)
265
br = Branch.open_containing(path)[0]
266
except bzrerrors.NotBranchError:
267
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
268
self.check_history.set_active(False)
269
self.check_history.set_sensitive(False)
271
except bzrerrors.UnsupportedProtocol:
272
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
273
self.check_history.set_active(False)
274
self.check_history.set_sensitive(False)
277
self._show_stock_image(gtk.STOCK_CONNECT)
282
self.remote_branch, self.remote_path = Branch.open_containing(path)
284
if self.remote_revision is None:
285
self.remote_revision = self.remote_branch.last_revision()
287
self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
289
if len(self.remote_path) == 0:
290
self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
292
for (name, type) in self.remote_entries:
293
if name == self.remote_path:
294
self.remote_parent = type.file_id
297
if not path.endswith('/'):
300
if self.remote_branch.base == path:
301
self.button_location_up.set_sensitive(False)
303
self.button_location_up.set_sensitive(True)
305
if os.path.isdir(path):
306
self.image_location_error.destroy()
311
self.wt, self.wtpath = WorkingTree.open_containing(path)
312
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
313
self.notbranch = True
315
# If we're in the root, we cannot go up anymore
316
if sys.platform == 'win32':
317
drive, tail = os.path.splitdrive(path)
318
if tail in ('', '/', '\\'):
319
self.button_location_up.set_sensitive(False)
321
self.button_location_up.set_sensitive(True)
324
self.button_location_up.set_sensitive(False)
326
self.button_location_up.set_sensitive(True)
327
elif not os.path.isfile(path):
328
# Doesn't seem to be a file nor a directory, trying to open a
330
self._show_stock_image(gtk.STOCK_DISCONNECT)
332
br = Branch.open_containing(path)[0]
333
except bzrerrors.NotBranchError:
334
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
335
self.check_history.set_active(False)
336
self.check_history.set_sensitive(False)
338
except bzrerrors.UnsupportedProtocol:
339
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
340
self.check_history.set_active(False)
341
self.check_history.set_sensitive(False)
344
self._show_stock_image(gtk.STOCK_CONNECT)
349
self.remote_branch, self.remote_path = Branch.open_containing(path)
351
if self.remote_revision is None:
352
self.remote_revision = self.remote_branch.last_revision()
354
self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
356
if len(self.remote_path) == 0:
357
self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
359
for (name, type) in self.remote_entries:
360
if name == self.remote_path:
361
self.remote_parent = type.file_id
364
if not path.endswith('/'):
367
if self.remote_branch.base == path:
368
self.button_location_up.set_sensitive(False)
370
self.button_location_up.set_sensitive(True)
373
self.check_history.set_active(False)
374
self.check_history.set_sensitive(False)
376
self.check_history.set_sensitive(True)
378
self.statusbar.push(self.context_id, path)
379
self.entry_location.set_text(path)
378
def set_path(self, path):
379
""" Set the current path while browsing the directories. """
383
382
def get_path(self):
388
if len(self.remote_path) > 0:
389
return self.remote_branch.base + self.remote_path + '/'
391
return self.remote_branch.base
393
def on_about_activate(self, widget):
396
def on_button_history_browse_clicked(self, widget):
397
""" Browse for revision button handler. """
399
br = self.remote_branch
403
revb = RevisionBrowser(br, self.window)
404
response = revb.run()
405
if response != gtk.RESPONSE_NONE:
408
if response == gtk.RESPONSE_OK:
409
if revb.selected_revno is not None:
410
self.entry_history.set_text(revb.selected_revno)
414
def on_button_location_jump_clicked(self, widget):
415
""" Location Jump button handler. """
416
location = self.entry_location.get_text()
418
if self.set_path(location):
421
def on_button_location_up_clicked(self, widget):
422
""" Location Up button handler. """
425
self.set_path(os.path.split(self.get_path())[0])
429
newpath = delim.join(self.get_path().split(delim)[:-2])
431
self.set_path(newpath)
435
def on_checkbutton_history_toggled(self, widget):
436
""" History Mode toggle handler. """
437
if self.check_history.get_active():
438
# History Mode activated
439
self.entry_history.set_sensitive(True)
440
self.button_history.set_sensitive(True)
442
# History Mode deactivated
443
self.entry_history.set_sensitive(False)
444
self.button_history.set_sensitive(False)
447
def on_entry_history_revno_key_press_event(self, widget, event):
448
""" Key pressed handler for the history entry. """
449
if event.keyval == gtk.gdk.keyval_from_name('Return') or event.keyval == gtk.gdk.keyval_from_name('KP_Enter'):
450
# Return was hit, so we have to load that specific revision
451
# Emulate being remote, so inventory should be used
452
path = self.get_path()
455
self.remote_branch = self.wt.branch
457
revno = int(self.entry_history.get_text())
458
self.remote_revision = self.remote_branch.get_rev_id(revno)
459
if self.set_path(path, True):
462
def on_entry_location_key_press_event(self, widget, event):
463
""" Key pressed handler for the location entry. """
464
if event.keyval == gtk.gdk.keyval_from_name('Return') or event.keyval == gtk.gdk.keyval_from_name('KP_Enter'):
465
# Return was hit, so we have to jump
466
self.on_button_location_jump_clicked(widget)
468
def on_menuitem_add_files_activate(self, widget):
469
""" Add file(s)... menu handler. """
470
from add import OliveAdd
471
add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
474
def on_menuitem_branch_get_activate(self, widget):
475
""" Branch/Get... menu handler. """
476
from bzrlib.plugins.gtk.branch import BranchDialog
479
branch = BranchDialog(os.getcwd(), self.window, self.remote_branch.base)
481
branch = BranchDialog(self.get_path(), self.window)
482
response = branch.run()
483
if response != gtk.RESPONSE_NONE:
486
if response == gtk.RESPONSE_OK:
491
def on_menuitem_branch_checkout_activate(self, widget):
492
""" Branch/Checkout... menu handler. """
493
from bzrlib.plugins.gtk.checkout import CheckoutDialog
496
checkout = CheckoutDialog(os.getcwd(), self.window, self.remote_branch.base)
498
checkout = CheckoutDialog(self.get_path(), self.window)
499
response = checkout.run()
500
if response != gtk.RESPONSE_NONE:
503
if response == gtk.RESPONSE_OK:
509
def on_menuitem_branch_commit_activate(self, widget):
510
""" Branch/Commit... menu handler. """
511
# def __init__(self, wt, wtpath, notbranch, selected=None, parent=None):
512
selected = self.get_selected_right()
514
selected = os.path.join(self.wtpath, selected)
515
commit = CommitDialog(wt=self.wt,
519
response = commit.run()
520
if response != gtk.RESPONSE_NONE:
523
if response == gtk.RESPONSE_OK:
528
def on_menuitem_branch_conflicts_activate(self, widget):
529
""" Branch/Conflicts... menu handler. """
530
conflicts = ConflictsDialog(self.wt, self.window)
531
response = conflicts.run()
532
if response != gtk.RESPONSE_NONE:
535
def on_menuitem_branch_merge_activate(self, widget):
536
""" Branch/Merge... menu handler. """
537
from bzrlib.plugins.gtk.merge import MergeDialog
539
if self.check_for_changes():
540
error_dialog(_i18n('There are local changes in the branch'),
541
_i18n('Please commit or revert the changes before merging.'))
543
parent_branch_path = self.wt.branch.get_parent()
544
merge = MergeDialog(self.wt, self.wtpath,default_branch_path=parent_branch_path )
548
def on_menuitem_branch_missing_revisions_activate(self, widget):
549
""" Branch/Missing revisions menu handler. """
551
from bzrlib.missing import find_unmerged, iter_log_revisions
553
local_branch = self.wt.branch
554
parent_branch_path = local_branch.get_parent()
555
if parent_branch_path is None:
556
error_dialog(_i18n('Parent location is unknown'),
557
_i18n('Cannot determine missing revisions if no parent location is known.'))
560
parent_branch = Branch.open(parent_branch_path)
562
if parent_branch.base == local_branch.base:
563
parent_branch = local_branch
565
local_extra, remote_extra = find_unmerged(local_branch,parent_branch)
567
if local_extra or remote_extra:
569
## def log_revision_one_line_text(log_revision):
570
## """ Generates one line description of log_revison ended with end of line."""
571
## revision = log_revision.rev
572
## txt = "- %s (%s)\n" % (revision.get_summary(), revision.committer, )
573
## txt = txt.replace("<"," ") # Seems < > chars are expected to be xml tags ...
574
## txt = txt.replace(">"," ")
579
dlg_txt += _i18n('%d local extra revision(s). \n') % (len(local_extra),)
580
## NOTE: We do not want such ugly info about missing revisions
581
## Revision Browser should be used there
582
## max_revisions = 10
583
## for log_revision in iter_log_revisions(local_extra, local_branch.repository, verbose=1):
584
## dlg_txt += log_revision_one_line_text(log_revision)
585
## if max_revisions <= 0:
586
## dlg_txt += _i18n("more ... \n")
588
## max_revisions -= 1
591
dlg_txt += _i18n('%d local missing revision(s).\n') % (len(remote_extra),)
592
## max_revisions = 10
593
## for log_revision in iter_log_revisions(remote_extra, parent_branch.repository, verbose=1):
594
## dlg_txt += log_revision_one_line_text(log_revision)
595
## if max_revisions <= 0:
596
## dlg_txt += _i18n("more ... \n")
598
## max_revisions -= 1
600
info_dialog(_i18n('There are missing revisions'),
603
info_dialog(_i18n('Local branch up to date'),
604
_i18n('There are no missing revisions.'))
607
def on_menuitem_branch_pull_activate(self, widget):
608
""" Branch/Pull menu handler. """
609
branch_to = self.wt.branch
611
location = branch_to.get_parent()
613
error_dialog(_i18n('Parent location is unknown'),
614
_i18n('Pulling is not possible until there is a parent location.'))
617
branch_from = Branch.open(location)
619
if branch_to.get_parent() is None:
620
branch_to.set_parent(branch_from.base)
622
ret = branch_to.pull(branch_from)
624
info_dialog(_i18n('Pull successful'), _i18n('%d revision(s) pulled.') % ret)
627
def on_menuitem_branch_update_activate(self, widget):
628
""" Brranch/checkout update menu handler. """
630
ret = self.wt.update()
631
conflicts = self.wt.conflicts()
633
info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
635
info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
637
def on_menuitem_branch_push_activate(self, widget):
638
""" Branch/Push... menu handler. """
639
push = PushDialog(repository=None,revid=None,branch=self.wt.branch, parent=self.window)
640
response = push.run()
641
if response != gtk.RESPONSE_NONE:
645
def on_menuitem_branch_revert_activate(self, widget):
646
""" Branch/Revert all changes menu handler. """
647
ret = self.wt.revert([])
649
warning_dialog(_i18n('Conflicts detected'),
650
_i18n('Please have a look at the working tree before continuing.'))
652
info_dialog(_i18n('Revert successful'),
653
_i18n('All files reverted to last revision.'))
656
def on_menuitem_branch_status_activate(self, widget):
657
""" Branch/Status... menu handler. """
658
from bzrlib.plugins.gtk.status import StatusDialog
659
status = StatusDialog(self.wt, self.wtpath)
660
response = status.run()
661
if response != gtk.RESPONSE_NONE:
664
def on_menuitem_branch_initialize_activate(self, widget):
665
""" Initialize current directory. """
666
init = InitDialog(self.path, self.window)
667
response = init.run()
668
if response != gtk.RESPONSE_NONE:
671
if response == gtk.RESPONSE_OK:
676
def on_menuitem_branch_tags_activate(self, widget):
677
""" Branch/Tags... menu handler. """
678
from bzrlib.plugins.gtk.tags import TagsWindow
680
window = TagsWindow(self.wt.branch, self.window)
682
window = TagsWindow(self.remote_branch, self.window)
685
def on_menuitem_file_annotate_activate(self, widget):
686
""" File/Annotate... menu handler. """
687
if self.get_selected_right() is None:
688
error_dialog(_i18n('No file was selected'),
689
_i18n('Please select a file from the list.'))
692
branch = self.wt.branch
693
file_id = self.wt.path2id(self.wt.relpath(os.path.join(self.path, self.get_selected_right())))
695
window = GAnnotateWindow(all=False, plain=False, parent=self.window)
696
window.set_title(os.path.join(self.path, self.get_selected_right()) + " - Annotate")
697
config = GAnnotateConfig(window)
701
window.annotate(self.wt, branch, file_id)
705
def on_menuitem_file_bookmark_activate(self, widget):
706
""" File/Bookmark current directory menu handler. """
707
if self.pref.add_bookmark(self.path):
708
info_dialog(_i18n('Bookmark successfully added'),
709
_i18n('The current directory was bookmarked. You can reach\nit by selecting it from the left panel.'))
712
warning_dialog(_i18n('Location already bookmarked'),
713
_i18n('The current directory is already bookmarked.\nSee the left panel for reference.'))
717
def on_menuitem_file_make_directory_activate(self, widget):
718
""" File/Make directory... menu handler. """
719
from mkdir import OliveMkdir
720
mkdir = OliveMkdir(self.wt, self.wtpath)
723
def on_menuitem_file_move_activate(self, widget):
724
""" File/Move... menu handler. """
725
from move import OliveMove
726
move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
729
def on_menuitem_file_rename_activate(self, widget):
730
""" File/Rename... menu handler. """
731
from rename import OliveRename
732
rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
735
def on_menuitem_remove_file_activate(self, widget):
736
""" Remove (unversion) selected file. """
737
from remove import OliveRemoveDialog
738
remove = OliveRemoveDialog(self.wt, self.wtpath,
739
selected=self.get_selected_right(),
741
response = remove.run()
743
if response != gtk.RESPONSE_NONE:
746
if response == gtk.RESPONSE_OK:
747
self.set_path(self.path)
752
def on_menuitem_stats_diff_activate(self, widget):
753
""" Statistics/Differences... menu handler. """
754
window = DiffWindow(parent=self.window)
755
parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
756
window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
759
def on_menuitem_stats_infos_activate(self, widget):
760
""" Statistics/Informations... menu handler. """
761
from info import OliveInfo
763
info = OliveInfo(self.remote_branch)
765
info = OliveInfo(self.wt.branch)
768
def on_menuitem_stats_log_activate(self, widget):
769
""" Statistics/Log... menu handler. """
772
branch = self.wt.branch
774
branch = self.remote_branch
776
window = branchwin.BranchWindow(branch, branch.last_revision(), None, parent=self.window)
779
def on_menuitem_view_refresh_activate(self, widget):
780
""" View/Refresh menu handler. """
781
# Refresh the left pane
783
# Refresh the right pane
786
def on_menuitem_view_show_hidden_files_activate(self, widget):
787
""" View/Show hidden files menu handler. """
788
self.pref.set_preference('dotted_files', widget.get_active())
789
if self.path is not None:
792
def on_menuitem_view_show_ignored_files_activate(self, widget):
793
""" Hide/Show ignored files menu handler. """
794
self.pref.set_preference('ignored_files', widget.get_active())
795
if self.path is not None:
798
def on_treeview_left_button_press_event(self, widget, event):
799
""" Occurs when somebody right-clicks in the bookmark list. """
800
if event.button == 3:
801
# Don't show context with nothing selected
802
if self.get_selected_left() == None:
806
from menu import OliveMenu
807
menu = OliveMenu(path=self.get_path(),
808
selected=self.get_selected_left(),
811
menu.left_context_menu().popup(None, None, None, 0,
814
def on_treeview_left_button_release_event(self, widget, event):
815
""" Occurs when somebody just clicks a bookmark. """
816
if event.button != 3:
817
# Allow one-click bookmark opening
818
if self.get_selected_left() == None:
821
newdir = self.get_selected_left()
825
if self.set_path(newdir):
828
def on_treeview_left_row_activated(self, treeview, path, view_column):
829
""" Occurs when somebody double-clicks or enters an item in the
832
newdir = self.get_selected_left()
836
if self.set_path(newdir):
839
def on_treeview_right_button_press_event(self, widget, event):
840
""" Occurs when somebody right-clicks in the file list. """
841
if event.button == 3:
843
from menu import OliveMenu
844
menu = OliveMenu(path=self.get_path(),
845
selected=self.get_selected_right(),
848
m_open = menu.ui.get_widget('/context_right/open')
849
m_add = menu.ui.get_widget('/context_right/add')
850
m_remove = menu.ui.get_widget('/context_right/remove')
851
m_rename = menu.ui.get_widget('/context_right/rename')
852
m_revert = menu.ui.get_widget('/context_right/revert')
853
m_commit = menu.ui.get_widget('/context_right/commit')
854
m_annotate = menu.ui.get_widget('/context_right/annotate')
855
m_diff = menu.ui.get_widget('/context_right/diff')
856
# check if we're in a branch
858
from bzrlib.branch import Branch
859
Branch.open_containing(self.get_path())
861
m_open.set_sensitive(False)
862
m_add.set_sensitive(False)
863
m_remove.set_sensitive(False)
864
m_rename.set_sensitive(False)
865
m_revert.set_sensitive(False)
866
m_commit.set_sensitive(False)
867
m_annotate.set_sensitive(False)
868
m_diff.set_sensitive(False)
870
m_open.set_sensitive(True)
871
m_add.set_sensitive(True)
872
m_remove.set_sensitive(True)
873
m_rename.set_sensitive(True)
874
m_revert.set_sensitive(True)
875
m_commit.set_sensitive(True)
876
m_annotate.set_sensitive(True)
877
m_diff.set_sensitive(True)
878
except bzrerrors.NotBranchError:
879
m_open.set_sensitive(True)
880
m_add.set_sensitive(False)
881
m_remove.set_sensitive(False)
882
m_rename.set_sensitive(False)
883
m_revert.set_sensitive(False)
884
m_commit.set_sensitive(False)
885
m_annotate.set_sensitive(False)
886
m_diff.set_sensitive(False)
889
menu.right_context_menu().popup(None, None, None, 0,
892
menu.remote_context_menu().popup(None, None, None, 0,
895
def on_treeview_right_row_activated(self, treeview, path, view_column):
896
""" Occurs when somebody double-clicks or enters an item in the
898
from launch import launch
900
newdir = self.get_selected_right()
905
self.set_path(os.path.split(self.get_path())[0])
907
fullpath = os.path.join(self.get_path(), newdir)
908
if os.path.isdir(fullpath):
909
# selected item is an existant directory
910
self.set_path(fullpath)
915
if self._is_remote_dir(self.get_path() + newdir):
916
self.set_path(self.get_path() + newdir)
920
def on_window_main_delete_event(self, widget, event=None):
921
""" Do some stuff before exiting. """
922
width, height = self.window_main.get_size()
923
self.pref.set_preference('window_width', width)
924
self.pref.set_preference('window_height', height)
925
x, y = self.window_main.get_position()
926
self.pref.set_preference('window_x', x)
927
self.pref.set_preference('window_y', y)
928
self.pref.set_preference('paned_position',
929
self.hpaned_main.get_position())
932
self.window_main.destroy()
934
def _load_left(self):
935
""" Load data into the left panel. (Bookmarks) """
937
treestore = gtk.TreeStore(str, str)
940
bookmarks = self.pref.get_bookmarks()
942
# Add them to the TreeStore
943
titer = treestore.append(None, [_i18n('Bookmarks'), None])
944
for item in bookmarks:
945
title = self.pref.get_bookmark_title(item)
946
treestore.append(titer, [title, item])
948
# Create the column and add it to the TreeView
949
self.treeview_left.set_model(treestore)
950
tvcolumn_bookmark = gtk.TreeViewColumn(_i18n('Bookmark'))
951
self.treeview_left.append_column(tvcolumn_bookmark)
954
cell = gtk.CellRendererText()
955
tvcolumn_bookmark.pack_start(cell, True)
956
tvcolumn_bookmark.add_attribute(cell, 'text', 0)
959
self.treeview_left.expand_all()
961
def _load_right(self):
962
""" Load data into the right panel. (Filelist) """
964
# Model: [ icon, dir, name, status text, status, size (int), size (human), mtime (int), mtime (local), fileid ]
965
liststore = gtk.ListStore(gobject.TYPE_STRING,
966
gobject.TYPE_BOOLEAN,
979
# Fill the appropriate lists
980
dotted_files = self.pref.get_preference('dotted_files', 'bool')
981
for item in os.listdir(self.path):
982
if not dotted_files and item[0] == '.':
984
if os.path.isdir(self.path + os.sep + item):
989
if not self.notbranch:
990
branch = self.wt.branch
991
tree2 = self.wt.branch.repository.revision_tree(branch.last_revision())
993
delta = self.wt.changes_from(tree2, want_unchanged=True)
995
# Add'em to the ListStore
998
statinfo = os.stat(self.path + os.sep + item)
1004
liststore.append([ gtk.STOCK_DIRECTORY,
1012
self._format_date(statinfo.st_mtime),
1017
if not self.notbranch:
1018
filename = self.wt.relpath(self.path + os.sep + item)
1023
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1024
if rpathnew == filename:
1027
for rpath, id, kind in delta.added:
1028
if rpath == filename:
1031
for rpath, id, kind in delta.removed:
1032
if rpath == filename:
1035
for rpath, id, kind, text_modified, meta_modified in delta.modified:
1036
if rpath == filename:
1039
for rpath, id, kind in delta.unchanged:
1040
if rpath == filename:
1041
status = 'unchanged'
1043
for rpath, file_class, kind, id, entry in self.wt.list_files():
1044
if rpath == filename and file_class == 'I':
1049
if status == 'renamed':
1050
st = _i18n('renamed')
1051
elif status == 'removed':
1052
st = _i18n('removed')
1053
elif status == 'added':
1055
elif status == 'modified':
1056
st = _i18n('modified')
1057
elif status == 'unchanged':
1058
st = _i18n('unchanged')
1059
elif status == 'ignored':
1060
st = _i18n('ignored')
1062
st = _i18n('unknown')
1065
statinfo = os.stat(self.path + os.sep + item)
1071
liststore.append([gtk.STOCK_FILE,
1076
str(statinfo.st_size), # NOTE: if int used there it will fail for large files (size expressed as long int)
1077
self._format_size(statinfo.st_size),
1079
self._format_date(statinfo.st_mtime),
1082
# Create the columns and add them to the TreeView
1083
self.treeview_right.set_model(liststore)
1084
self._tvcolumn_filename = gtk.TreeViewColumn(_i18n('Filename'))
1085
self._tvcolumn_status = gtk.TreeViewColumn(_i18n('Status'))
1086
self._tvcolumn_size = gtk.TreeViewColumn(_i18n('Size'))
1087
self._tvcolumn_mtime = gtk.TreeViewColumn(_i18n('Last modified'))
1088
self.treeview_right.append_column(self._tvcolumn_filename)
1089
self.treeview_right.append_column(self._tvcolumn_status)
1090
self.treeview_right.append_column(self._tvcolumn_size)
1091
self.treeview_right.append_column(self._tvcolumn_mtime)
1094
cellpb = gtk.CellRendererPixbuf()
1095
cell = gtk.CellRendererText()
1096
self._tvcolumn_filename.pack_start(cellpb, False)
1097
self._tvcolumn_filename.pack_start(cell, True)
1098
self._tvcolumn_filename.set_attributes(cellpb, stock_id=0)
1099
self._tvcolumn_filename.add_attribute(cell, 'text', 2)
1100
self._tvcolumn_status.pack_start(cell, True)
1101
self._tvcolumn_status.add_attribute(cell, 'text', 3)
1102
self._tvcolumn_size.pack_start(cell, True)
1103
self._tvcolumn_size.add_attribute(cell, 'text', 6)
1104
self._tvcolumn_mtime.pack_start(cell, True)
1105
self._tvcolumn_mtime.add_attribute(cell, 'text', 8)
1107
# Set up the properties of the TreeView
1108
self.treeview_right.set_headers_visible(True)
1109
self.treeview_right.set_headers_clickable(True)
1110
self.treeview_right.set_search_column(1)
1111
self._tvcolumn_filename.set_resizable(True)
1112
self._tvcolumn_status.set_resizable(True)
1113
self._tvcolumn_size.set_resizable(True)
1114
self._tvcolumn_mtime.set_resizable(True)
1116
liststore.set_sort_func(13, self._sort_filelist_callback, None)
1117
liststore.set_sort_column_id(13, gtk.SORT_ASCENDING)
1118
self._tvcolumn_filename.set_sort_column_id(13)
1119
self._tvcolumn_status.set_sort_column_id(3)
1120
self._tvcolumn_size.set_sort_column_id(5)
1121
self._tvcolumn_mtime.set_sort_column_id(7)
1124
self.set_sensitivity()
1126
def get_selected_fileid(self):
1127
""" Get the file_id of the selected file. """
1128
treeselection = self.treeview_right.get_selection()
1129
(model, iter) = treeselection.get_selected()
1134
return model.get_value(iter, 9)
383
""" Get the current path. """
1136
386
def get_selected_right(self):
1137
387
""" Get the selected filename. """
1161
411
""" Clean the last message from the statusbar. """
1162
412
self.statusbar.pop(self.context_id)
1164
def set_sensitivity(self):
1165
""" Set menu and toolbar sensitivity. """
1168
self.menuitem_branch_init.set_sensitive(self.notbranch)
1169
self.menuitem_branch_get.set_sensitive(self.notbranch)
1170
self.menuitem_branch_checkout.set_sensitive(self.notbranch)
1171
self.menuitem_branch_pull.set_sensitive(not self.notbranch)
1172
self.menuitem_branch_push.set_sensitive(not self.notbranch)
1173
self.menuitem_branch_update.set_sensitive(not self.notbranch)
1174
self.menuitem_branch_revert.set_sensitive(not self.notbranch)
1175
self.menuitem_branch_merge.set_sensitive(not self.notbranch)
1176
self.menuitem_branch_commit.set_sensitive(not self.notbranch)
1177
self.menuitem_branch_tags.set_sensitive(not self.notbranch)
1178
self.menuitem_branch_status.set_sensitive(not self.notbranch)
1179
self.menuitem_branch_missing.set_sensitive(not self.notbranch)
1180
self.menuitem_branch_conflicts.set_sensitive(not self.notbranch)
1181
self.menuitem_stats.set_sensitive(not self.notbranch)
1182
self.menuitem_stats_diff.set_sensitive(not self.notbranch)
1183
self.menuitem_add_files.set_sensitive(not self.notbranch)
1184
self.menuitem_remove_files.set_sensitive(not self.notbranch)
1185
self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
1186
self.menuitem_file_rename.set_sensitive(not self.notbranch)
1187
self.menuitem_file_move.set_sensitive(not self.notbranch)
1188
self.menuitem_file_annotate.set_sensitive(not self.notbranch)
1189
#self.menutoolbutton_diff.set_sensitive(True)
1190
self.toolbutton_diff.set_sensitive(not self.notbranch)
1191
self.toolbutton_log.set_sensitive(not self.notbranch)
1192
self.toolbutton_commit.set_sensitive(not self.notbranch)
1193
self.toolbutton_pull.set_sensitive(not self.notbranch)
1194
self.toolbutton_push.set_sensitive(not self.notbranch)
1195
self.toolbutton_update.set_sensitive(not self.notbranch)
414
def refresh_left(self):
415
""" Refresh the bookmark list. """
417
self.set_busy(self.treeview_left)
419
# Get TreeStore and clear it
420
treestore = self.treeview_left.get_model()
424
bookmarks = self.pref.get_bookmarks()
426
# Add them to the TreeStore
427
titer = treestore.append(None, [_('Bookmarks'), None])
428
for item in bookmarks:
429
title = self.pref.get_bookmark_title(item)
430
treestore.append(titer, [title, item])
432
# Add the TreeStore to the TreeView
433
self.treeview_left.set_model(treestore)
436
self.treeview_left.expand_all()
438
self.set_busy(self.treeview_left, False)
440
def refresh_right(self, path=None):
441
""" Refresh the file list. """
442
from bzrlib.workingtree import WorkingTree
444
self.set_busy(self.treeview_right)
447
path = self.get_path()
449
# A workaround for double-clicking Bookmarks
450
if not os.path.exists(path):
451
self.set_busy(self.treeview_right, False)
454
# Get ListStore and clear it
455
liststore = self.treeview_right.get_model()
461
# Fill the appropriate lists
462
dotted_files = self.pref.get_preference('dotted_files', 'bool')
463
for item in os.listdir(path):
464
if not dotted_files and item[0] == '.':
466
if os.path.isdir(path + os.sep + item):
475
# Try to open the working tree
478
tree1 = WorkingTree.open_containing(path)[0]
479
except errors.NotBranchError:
481
except errors.PermissionDenied:
482
print "DEBUG: permission denied."
485
branch = tree1.branch
486
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
488
delta = tree1.changes_from(tree2, want_unchanged=True)
490
# Add'em to the ListStore
492
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
496
filename = tree1.relpath(path + os.sep + item)
498
for rpath, id, kind, text_modified, meta_modified in delta.renamed:
499
if rpath == filename:
501
for rpath, id, kind in delta.added:
502
if rpath == filename:
504
for rpath, id, kind, text_modified, meta_modified in delta.removed:
505
if rpath == filename:
507
for rpath, id, kind, text_modified, meta_modified in delta.modified:
508
if rpath == filename:
510
for rpath, id, kind in delta.unchanged:
511
if rpath == filename:
515
# status = fileops.status(path + os.sep + item)
516
#except errors.PermissionDenied:
519
if status == 'renamed':
521
elif status == 'removed':
523
elif status == 'added':
525
elif status == 'modified':
527
elif status == 'unchanged':
531
liststore.append([gtk.STOCK_FILE, item, st])
533
# Add the ListStore to the TreeView
534
self.treeview_right.set_model(liststore)
536
# Check if current directory is a branch
538
# Activate some items
1198
539
self.menuitem_branch_init.set_sensitive(False)
1199
540
self.menuitem_branch_get.set_sensitive(True)
1200
541
self.menuitem_branch_checkout.set_sensitive(True)
542
self.menuitem_branch_pull.set_sensitive(True)
543
self.menuitem_branch_push.set_sensitive(True)
544
self.menuitem_branch_commit.set_sensitive(True)
545
self.menuitem_branch_status.set_sensitive(True)
546
self.menuitem_branch_missing.set_sensitive(True)
547
self.menuitem_stats.set_sensitive(True)
548
self.menuitem_add_files.set_sensitive(True)
549
self.menuitem_remove_files.set_sensitive(True)
550
self.menuitem_file_make_directory.set_sensitive(True)
551
self.menuitem_file_rename.set_sensitive(True)
552
self.menuitem_file_move.set_sensitive(True)
553
#self.menutoolbutton_diff.set_sensitive(True)
554
self.toolbutton_diff.set_sensitive(True)
555
self.toolbutton_log.set_sensitive(True)
556
self.toolbutton_commit.set_sensitive(True)
557
self.toolbutton_pull.set_sensitive(True)
558
self.toolbutton_push.set_sensitive(True)
560
# Deactivate some items
561
self.menuitem_branch_init.set_sensitive(True)
562
self.menuitem_branch_get.set_sensitive(False)
563
self.menuitem_branch_checkout.set_sensitive(False)
1201
564
self.menuitem_branch_pull.set_sensitive(False)
1202
565
self.menuitem_branch_push.set_sensitive(False)
1203
self.menuitem_branch_update.set_sensitive(False)
1204
self.menuitem_branch_revert.set_sensitive(False)
1205
self.menuitem_branch_merge.set_sensitive(False)
1206
566
self.menuitem_branch_commit.set_sensitive(False)
1207
self.menuitem_branch_tags.set_sensitive(True)
1208
567
self.menuitem_branch_status.set_sensitive(False)
1209
568
self.menuitem_branch_missing.set_sensitive(False)
1210
self.menuitem_branch_conflicts.set_sensitive(False)
1211
self.menuitem_stats.set_sensitive(True)
1212
self.menuitem_stats_diff.set_sensitive(False)
569
self.menuitem_stats.set_sensitive(False)
1213
570
self.menuitem_add_files.set_sensitive(False)
1214
571
self.menuitem_remove_files.set_sensitive(False)
1215
572
self.menuitem_file_make_directory.set_sensitive(False)
1216
573
self.menuitem_file_rename.set_sensitive(False)
1217
574
self.menuitem_file_move.set_sensitive(False)
1218
self.menuitem_file_annotate.set_sensitive(False)
1219
#self.menutoolbutton_diff.set_sensitive(True)
575
#self.menutoolbutton_diff.set_sensitive(False)
1220
576
self.toolbutton_diff.set_sensitive(False)
1221
self.toolbutton_log.set_sensitive(True)
577
self.toolbutton_log.set_sensitive(False)
1222
578
self.toolbutton_commit.set_sensitive(False)
1223
579
self.toolbutton_pull.set_sensitive(False)
1224
580
self.toolbutton_push.set_sensitive(False)
1225
self.toolbutton_update.set_sensitive(False)
1227
def refresh_left(self):
1228
""" Refresh the bookmark list. """
1230
# Get TreeStore and clear it
1231
treestore = self.treeview_left.get_model()
1234
# Re-read preferences
1238
bookmarks = self.pref.get_bookmarks()
1240
# Add them to the TreeStore
1241
titer = treestore.append(None, [_i18n('Bookmarks'), None])
1242
for item in bookmarks:
1243
title = self.pref.get_bookmark_title(item)
1244
treestore.append(titer, [title, item])
1246
# Add the TreeStore to the TreeView
1247
self.treeview_left.set_model(treestore)
1250
self.treeview_left.expand_all()
1252
def refresh_right(self, path=None):
1253
""" Refresh the file list. """
1256
from bzrlib.workingtree import WorkingTree
1259
path = self.get_path()
1261
# A workaround for double-clicking Bookmarks
1262
if not os.path.exists(path):
1265
# Get ListStore and clear it
1266
liststore = self.treeview_right.get_model()
1269
# Show Status column
1270
self._tvcolumn_status.set_visible(True)
1275
# Fill the appropriate lists
1276
dotted_files = self.pref.get_preference('dotted_files', 'bool')
1277
ignored_files = self.pref.get_preference('ignored_files', 'bool')
1279
for item in os.listdir(path):
1280
if not dotted_files and item[0] == '.':
1282
if os.path.isdir(path + os.sep + item):
1287
# Try to open the working tree
1290
tree1 = WorkingTree.open_containing(path)[0]
1291
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
1295
branch = tree1.branch
1296
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
1298
delta = tree1.changes_from(tree2, want_unchanged=True)
1300
# Add'em to the ListStore
1303
statinfo = os.stat(self.path + os.sep + item)
1309
liststore.append([gtk.STOCK_DIRECTORY,
1317
self._format_date(statinfo.st_mtime),
1323
filename = tree1.relpath(path + os.sep + item)
1328
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1329
if rpathnew == filename:
1332
for rpath, id, kind in delta.added:
1333
if rpath == filename:
1336
for rpath, id, kind in delta.removed:
1337
if rpath == filename:
1340
for rpath, id, kind, text_modified, meta_modified in delta.modified:
1341
if rpath == filename:
1344
for rpath, id, kind in delta.unchanged:
1345
if rpath == filename:
1346
status = 'unchanged'
1348
for rpath, file_class, kind, id, entry in self.wt.list_files():
1349
if rpath == filename and file_class == 'I':
1354
if status == 'renamed':
1355
st = _i18n('renamed')
1356
elif status == 'removed':
1357
st = _i18n('removed')
1358
elif status == 'added':
1360
elif status == 'modified':
1361
st = _i18n('modified')
1362
elif status == 'unchanged':
1363
st = _i18n('unchanged')
1364
elif status == 'ignored':
1365
st = _i18n('ignored')
1366
if not ignored_files:
1369
st = _i18n('unknown')
1372
statinfo = os.stat(self.path + os.sep + item)
1378
liststore.append([gtk.STOCK_FILE,
1383
str(statinfo.st_size),
1384
self._format_size(statinfo.st_size),
1386
self._format_date(statinfo.st_mtime),
582
self.set_busy(self.treeview_right, False)
584
def set_busy(self, widget, busy=True):
586
widget.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
1391
# Get ListStore and clear it
1392
liststore = self.treeview_right.get_model()
1395
# Hide Status column
1396
self._tvcolumn_status.set_visible(False)
1401
self._show_stock_image(gtk.STOCK_REFRESH)
1403
for (name, type) in self.remote_entries:
1404
if type.kind == 'directory':
1406
elif type.kind == 'file':
1410
""" Cache based on revision history. """
1411
def __init__(self, history):
1412
self._history = history
1414
def _lookup_revision(self, revid):
1415
for r in self._history:
1416
if r.revision_id == revid:
1418
rev = repo.get_revision(revid)
1419
self._history.append(rev)
1422
repo = self.remote_branch.repository
1424
revhistory = self.remote_branch.revision_history()
1426
revs = repo.get_revisions(revhistory)
1427
cache = HistoryCache(revs)
1428
except bzrerrors.InvalidHttpResponse:
1429
# Fallback to dummy algorithm, because of LP: #115209
1430
cache = HistoryCache([])
1433
if item.parent_id == self.remote_parent:
1434
rev = cache._lookup_revision(item.revision)
1435
liststore.append([ gtk.STOCK_DIRECTORY,
1443
self._format_date(rev.timestamp),
1446
while gtk.events_pending():
1447
gtk.main_iteration()
1450
if item.parent_id == self.remote_parent:
1451
rev = cache._lookup_revision(item.revision)
1452
liststore.append([ gtk.STOCK_FILE,
1457
str(item.text_size),
1458
self._format_size(item.text_size),
1460
self._format_date(rev.timestamp),
1463
while gtk.events_pending():
1464
gtk.main_iteration()
1466
self.image_location_error.destroy()
588
widget.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
1468
# Columns should auto-size
1469
self.treeview_right.columns_autosize()
1472
self.set_sensitivity()
590
gtk.main_iteration(0)
1474
592
def _harddisks(self):
1475
593
""" Returns hard drive letters under Win32. """