/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to olive/__init__.py

  • Committer: Jasper Groenewegen
  • Date: 2008-08-04 21:39:55 UTC
  • mfrom: (592.4.1 ginfo)
  • Revision ID: colbrac@xs4all.nl-20080804213955-61wkontqs0ae3lvy
Merge addition of ginfo command

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 #!/usr/bin/python
2
 
 
3
1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
4
2
#
5
3
# This program is free software; you can redistribute it and/or modify
19
17
import os
20
18
import sys
21
19
import time
 
20
import errno
22
21
 
23
22
# gettext support
24
23
import gettext
33
32
import gobject
34
33
import gtk
35
34
import gtk.gdk
36
 
import gtk.glade
37
35
 
38
36
from bzrlib.branch import Branch
39
37
import bzrlib.errors as bzrerrors
44
42
from bzrlib.plugins.gtk import _i18n
45
43
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
46
44
from bzrlib.plugins.gtk.errors import show_bzr_error
47
 
from guifiles import GLADEFILENAME
 
45
from bzrlib.plugins.gtk.olive.window import OliveGui
48
46
 
49
47
from bzrlib.plugins.gtk.diff import DiffWindow
50
48
lazy_import(globals(), """
60
58
 
61
59
def about():
62
60
    """ Display the AboutDialog. """
63
 
    from bzrlib.plugins.gtk import __version__
64
 
    from bzrlib.plugins.gtk.olive.guifiles import GLADEFILENAME
65
 
 
66
 
    # Load AboutDialog description
67
 
    dglade = gtk.glade.XML(GLADEFILENAME, 'aboutdialog')
68
 
    dialog = dglade.get_widget('aboutdialog')
69
 
 
70
 
    # Set version
 
61
    from bzrlib.plugins.gtk import __version__, icon_path
 
62
    
 
63
    iconpath = icon_path() + os.sep
 
64
    
 
65
    dialog = gtk.AboutDialog()
 
66
    dialog.set_name("Olive")
71
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"))
72
73
    dialog.set_authors([ _i18n("Lead Developer:"),
73
74
                         "Szilveszter Farkas <szilveszter.farkas@gmail.com>",
74
75
                         _i18n("Contributors:"),
87
88
    program. """
88
89
    
89
90
    def __init__(self):
90
 
        self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
91
 
        self.window = self.toplevel.get_widget('window_main')
 
91
        self.window = OliveGui(calling_app = self)
 
92
        
92
93
        self.pref = Preferences()
93
94
        self.path = None
94
95
 
95
96
        # Initialize the statusbar
96
 
        self.statusbar = self.toplevel.get_widget('statusbar')
97
 
        self.context_id = self.statusbar.get_context_id('olive')
 
97
        self.context_id = self.window.statusbar.get_context_id('olive')
98
98
        
99
 
        # Get the main window
100
 
        self.window_main = self.toplevel.get_widget('window_main')
101
 
        # Get the HPaned
102
 
        self.hpaned_main = self.toplevel.get_widget('hpaned_main')
103
 
        # Get the TreeViews
104
 
        self.treeview_left = self.toplevel.get_widget('treeview_left')
105
 
        self.treeview_right = self.toplevel.get_widget('treeview_right')
106
 
        # Get some important menu items
107
 
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
108
 
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
109
 
        self.menuitem_file_bookmark = self.toplevel.get_widget('menuitem_file_bookmark')
110
 
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
111
 
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
112
 
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
113
 
        self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
114
 
        self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
115
 
        self.menuitem_view_show_ignored_files = self.toplevel.get_widget('menuitem_view_show_ignored_files')
116
 
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
117
 
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
118
 
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
119
 
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
120
 
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
121
 
        self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
122
 
        self.menuitem_branch_update = self.toplevel.get_widget('menuitem_branch_update')
123
 
        self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
124
 
        self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
125
 
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
126
 
        self.menuitem_branch_tags = self.toplevel.get_widget('menuitem_branch_tags')
127
 
        self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
128
 
        self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
129
 
        self.menuitem_branch_conflicts = self.toplevel.get_widget('menuitem_branch_conflicts')
130
 
        self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
131
 
        self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
132
 
        self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
133
 
        # Get some toolbuttons
134
 
        #self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
135
 
        self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
136
 
        self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
137
 
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
138
 
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
139
 
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
140
 
        self.toolbutton_update = self.toplevel.get_widget('toolbutton_update')
141
99
        # Get the drive selector
142
100
        self.combobox_drive = gtk.combo_box_new_text()
143
101
        self.combobox_drive.connect("changed", self._refresh_drives)
144
102
        
145
103
        # 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')
 
104
        self.hbox_location = self.window.locationbar
 
105
        self.button_location_up = self.window.button_location_up
 
106
        self.button_location_jump = self.window.button_location_jump
 
107
        self.entry_location = self.window.entry_location
151
108
        
152
109
        # 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')
156
 
        
157
 
        self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
158
 
        
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
209
 
            }
210
 
        
211
 
        # Connect the signals to the handlers
212
 
        self.toplevel.signal_autoconnect(dic)
 
110
        self.check_history = self.window.checkbutton_history
 
111
        self.entry_history = self.window.entry_history_revno
 
112
        self.button_history = self.window.button_history_browse
213
113
        
214
114
        self._just_started = True
215
115
        
222
122
        self.window.move(x, y)
223
123
        # Apply paned position
224
124
        pos = self.pref.get_preference('paned_position', 'int')
225
 
        self.hpaned_main.set_position(pos)
226
 
        
227
 
        # Apply menu to the toolbutton
228
 
        #menubutton = self.toplevel.get_widget('menutoolbutton_diff')
229
 
        #menubutton.set_menu(handler.menu.toolbar_diff)
 
125
        self.window.hpaned_main.set_position(pos)
230
126
        
231
127
        # Now we can show the window
232
128
        self.window.show()
238
134
            self.combobox_drive.show()
239
135
            self.gen_hard_selector()
240
136
        
241
 
        self._load_left()
 
137
        # Acceptable errors when loading files/folders in the treeviews
 
138
        self.acceptable_errors = (errno.ENOENT, errno.ELOOP)
 
139
        
 
140
        self.refresh_left()
242
141
 
243
142
        # Apply menu state
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'))
 
143
        self.window.mb_view_showhidden.set_active(self.pref.get_preference('dotted_files', 'bool'))
 
144
        self.window.mb_view_showignored.set_active(self.pref.get_preference('ignored_files', 'bool'))
246
145
 
247
146
        # We're starting local
248
147
        self.remote = False
251
150
        self.remote_revision = None
252
151
        
253
152
        self.set_path(os.getcwd())
254
 
        self._load_right()
 
153
        self.refresh_right()
255
154
        
256
155
        self._just_started = False
257
156
 
258
157
    def set_path(self, path, force_remote=False):
 
158
        self.window.location_status.destroy()
259
159
        self.notbranch = False
260
160
        
261
161
        if force_remote:
262
162
            # Forcing remote mode (reading data from inventory)
263
 
            self._show_stock_image(gtk.STOCK_DISCONNECT)
 
163
            self.window.set_location_status(gtk.STOCK_DISCONNECT)
264
164
            try:
265
165
                br = Branch.open_containing(path)[0]
266
166
            except bzrerrors.NotBranchError:
267
 
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
167
                self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
268
168
                self.check_history.set_active(False)
269
169
                self.check_history.set_sensitive(False)
270
170
                return False
271
171
            except bzrerrors.UnsupportedProtocol:
272
 
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
172
                self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
273
173
                self.check_history.set_active(False)
274
174
                self.check_history.set_sensitive(False)
275
175
                return False
276
176
            
277
 
            self._show_stock_image(gtk.STOCK_CONNECT)
 
177
            self.window.set_location_status(gtk.STOCK_CONNECT)
278
178
            
279
179
            self.remote = True
280
180
           
303
203
                self.button_location_up.set_sensitive(True)
304
204
        else:
305
205
            if os.path.isdir(path):
306
 
                self.image_location_error.destroy()
307
206
                self.remote = False
308
207
                
309
208
                # We're local
310
209
                try:
311
 
                    self.wt, self.wtpath = WorkingTree.open_containing(path)
 
210
                    self.wt, self.wtpath = WorkingTree.open_containing(os.path.realpath(path))
312
211
                except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
313
212
                    self.notbranch = True
 
213
                except bzrerrors.PermissionDenied:
 
214
                    self.window.set_location_status(gtk.STOCK_DIALOG_WARNING, allowPopup=True)
 
215
                    self.window.location_status.connect_object('clicked', warning_dialog, 
 
216
                                       *(_i18n('Branch information unreadable'),
 
217
                                                _i18n('The current folder is a branch but the .bzr folder is not readable')))
 
218
                    self.notbranch = True
314
219
                
315
220
                # If we're in the root, we cannot go up anymore
316
221
                if sys.platform == 'win32':
327
232
            elif not os.path.isfile(path):
328
233
                # Doesn't seem to be a file nor a directory, trying to open a
329
234
                # remote location
330
 
                self._show_stock_image(gtk.STOCK_DISCONNECT)
 
235
                self.window.set_location_status(gtk.STOCK_DISCONNECT)
331
236
                try:
332
237
                    br = Branch.open_containing(path)[0]
333
238
                except bzrerrors.NotBranchError:
334
 
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
239
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
335
240
                    self.check_history.set_active(False)
336
241
                    self.check_history.set_sensitive(False)
337
242
                    return False
338
243
                except bzrerrors.UnsupportedProtocol:
339
 
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
244
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
340
245
                    self.check_history.set_active(False)
341
246
                    self.check_history.set_sensitive(False)
342
247
                    return False
343
248
                
344
 
                self._show_stock_image(gtk.STOCK_CONNECT)
 
249
                self.window.set_location_status(gtk.STOCK_CONNECT)
345
250
                
346
251
                self.remote = True
347
252
               
375
280
        else:
376
281
            self.check_history.set_sensitive(True)
377
282
        
378
 
        self.statusbar.push(self.context_id, path)
 
283
        self.window.statusbar.push(self.context_id, path)
379
284
        self.entry_location.set_text(path)
380
285
        self.path = path
381
286
        return True
408
313
            if response == gtk.RESPONSE_OK:
409
314
                if revb.selected_revno is not None:
410
315
                    self.entry_history.set_text(revb.selected_revno)
 
316
                    self.on_entry_history_revno_activate()
411
317
            
412
318
            revb.destroy()
413
319
    
438
344
            # History Mode activated
439
345
            self.entry_history.set_sensitive(True)
440
346
            self.button_history.set_sensitive(True)
 
347
            if self.entry_history.get_text() != "":
 
348
                self.on_entry_history_revno_activate()
441
349
        else:
442
350
            # History Mode deactivated
443
351
            self.entry_history.set_sensitive(False)
444
352
            self.button_history.set_sensitive(False)
 
353
            
 
354
            # Return right window to normal view by acting like we jump to it
 
355
            self.on_button_location_jump_clicked(widget)
445
356
    
446
357
    @show_bzr_error
447
 
    def on_entry_history_revno_key_press_event(self, widget, event):
 
358
    def on_entry_history_revno_activate(self, widget=None):
448
359
        """ 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()
453
 
            if not self.remote:
454
 
                self.remote = True
455
 
                self.remote_branch = self.wt.branch
456
 
            
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):
460
 
                self.refresh_right()
461
 
    
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)
467
 
    
 
360
        path = self.get_path()
 
361
        if not self.remote:
 
362
            self.remote = True
 
363
            self.remote_branch = self.wt.branch
 
364
        
 
365
        revno = int(self.entry_history.get_text())
 
366
        self.remote_revision = self.remote_branch.get_rev_id(revno)
 
367
        if self.set_path(path, True):
 
368
            self.refresh_right()
 
369
 
468
370
    def on_menuitem_add_files_activate(self, widget):
469
371
        """ Add file(s)... menu handler. """
470
 
        from add import OliveAdd
471
 
        add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
472
 
        add.display()
473
 
    
 
372
        from bzrlib.plugins.gtk.olive.add import AddDialog
 
373
        add = AddDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
374
        response = add.run()
 
375
        add.destroy()
 
376
        if response == gtk.RESPONSE_OK:
 
377
            self.refresh_right()
 
378
 
474
379
    def on_menuitem_branch_get_activate(self, widget):
475
380
        """ Branch/Get... menu handler. """
476
381
        from bzrlib.plugins.gtk.branch import BranchDialog
508
413
    @show_bzr_error
509
414
    def on_menuitem_branch_commit_activate(self, widget):
510
415
        """ Branch/Commit... menu handler. """
511
 
#     def __init__(self, wt, wtpath, notbranch, selected=None, parent=None):
512
416
        selected = self.get_selected_right()
513
417
        if selected:
514
418
            selected = os.path.join(self.wtpath, selected)
541
445
                         _i18n('Please commit or revert the changes before merging.'))
542
446
        else:
543
447
            parent_branch_path = self.wt.branch.get_parent()
544
 
            merge = MergeDialog(self.wt, self.wtpath,default_branch_path=parent_branch_path )
545
 
            merge.display()
 
448
            merge = MergeDialog(self.wt, self.wtpath, parent_branch_path, self.window)
 
449
            response = merge.run()
 
450
            merge.destroy()
 
451
            if response == gtk.RESPONSE_OK:
 
452
                self.refresh_right()
546
453
 
547
454
    @show_bzr_error
548
455
    def on_menuitem_branch_missing_revisions_activate(self, widget):
625
532
        
626
533
    @show_bzr_error
627
534
    def on_menuitem_branch_update_activate(self, widget):
628
 
        """ Brranch/checkout update menu handler. """
 
535
        """ Branch/checkout update menu handler. """
629
536
        
630
537
        ret = self.wt.update()
631
538
        conflicts = self.wt.conflicts()
633
540
            info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
634
541
        else:
635
542
            info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
 
543
        self.refresh_right()
636
544
    
637
545
    def on_menuitem_branch_push_activate(self, widget):
638
546
        """ Branch/Push... menu handler. """
644
552
    @show_bzr_error
645
553
    def on_menuitem_branch_revert_activate(self, widget):
646
554
        """ Branch/Revert all changes menu handler. """
647
 
        ret = self.wt.revert([])
 
555
        ret = self.wt.revert(None)
648
556
        if ret:
649
557
            warning_dialog(_i18n('Conflicts detected'),
650
558
                           _i18n('Please have a look at the working tree before continuing.'))
716
624
    
717
625
    def on_menuitem_file_make_directory_activate(self, widget):
718
626
        """ File/Make directory... menu handler. """
719
 
        from mkdir import OliveMkdir
720
 
        mkdir = OliveMkdir(self.wt, self.wtpath)
721
 
        mkdir.display()
 
627
        from bzrlib.plugins.gtk.olive.mkdir import MkdirDialog
 
628
        mkdir = MkdirDialog(self.wt, self.wtpath, self.window)
 
629
        response = mkdir.run()
 
630
        mkdir.destroy()
 
631
        if response == gtk.RESPONSE_OK:
 
632
            self.refresh_right()
722
633
    
723
634
    def on_menuitem_file_move_activate(self, widget):
724
635
        """ File/Move... menu handler. """
725
 
        from move import OliveMove
726
 
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
727
 
        move.display()
 
636
        from bzrlib.plugins.gtk.olive.move import MoveDialog
 
637
        move = MoveDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
638
        response = move.run()
 
639
        move.destroy()
 
640
        if response == gtk.RESPONSE_OK:
 
641
            self.refresh_right()
728
642
    
729
643
    def on_menuitem_file_rename_activate(self, widget):
730
644
        """ File/Rename... menu handler. """
731
 
        from rename import OliveRename
732
 
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
733
 
        rename.display()
 
645
        from bzrlib.plugins.gtk.olive.rename import RenameDialog
 
646
        rename = RenameDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
647
        response = rename.run()
 
648
        rename.destroy()
 
649
        if response == gtk.RESPONSE_OK:
 
650
            self.refresh_right()
734
651
 
735
652
    def on_menuitem_remove_file_activate(self, widget):
736
653
        """ Remove (unversion) selected file. """
737
 
        from remove import OliveRemoveDialog
738
 
        remove = OliveRemoveDialog(self.wt, self.wtpath,
 
654
        from bzrlib.plugins.gtk.olive.remove import RemoveDialog
 
655
        remove = RemoveDialog(self.wt, self.wtpath,
739
656
                                   selected=self.get_selected_right(),
740
657
                                   parent=self.window)
741
658
        response = remove.run()
758
675
    
759
676
    def on_menuitem_stats_infos_activate(self, widget):
760
677
        """ Statistics/Informations... menu handler. """
761
 
        from info import OliveInfo
 
678
        from bzrlib.plugins.gtk.olive.info import InfoDialog
762
679
        if self.remote:
763
 
            info = OliveInfo(self.remote_branch)
 
680
            info = InfoDialog(self.remote_branch)
764
681
        else:
765
 
            info = OliveInfo(self.wt.branch)
 
682
            info = InfoDialog(self.wt.branch)
766
683
        info.display()
767
684
    
768
685
    def on_menuitem_stats_log_activate(self, widget):
773
690
        else:
774
691
            branch = self.remote_branch
775
692
 
776
 
        window = branchwin.BranchWindow(branch, branch.last_revision(), None, parent=self.window)
 
693
        window = branchwin.BranchWindow(branch, [branch.last_revision()], None, 
 
694
                                        parent=self.window)
777
695
        window.show()
778
696
    
779
697
    def on_menuitem_view_refresh_activate(self, widget):
796
714
            self.refresh_right()
797
715
            
798
716
    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:
803
 
                return
804
 
 
805
 
            # Create a menu
806
 
            from menu import OliveMenu
807
 
            menu = OliveMenu(path=self.get_path(),
808
 
                             selected=self.get_selected_left(),
809
 
                             app=self)
810
 
            
811
 
            menu.left_context_menu().popup(None, None, None, 0,
812
 
                                           event.time)
813
 
 
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:
819
 
                return
820
 
            
821
 
            newdir = self.get_selected_left()
822
 
            if newdir == None:
823
 
                return
824
 
 
825
 
            if self.set_path(newdir):
826
 
                self.refresh_right()
 
717
        """ Occurs when somebody clicks in the bookmark list. """
 
718
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
 
719
        treeselection = widget.get_selection()
 
720
        if treepathpos is not None:
 
721
            treeselection.select_path(treepathpos[0])
 
722
            if event.button == 1:
 
723
                newdir = self.get_selected_left()
 
724
                if newdir == None:
 
725
                    return
 
726
 
 
727
                if self.set_path(newdir):
 
728
                    self.refresh_right()
 
729
            elif event.button == 3:
 
730
                # Don't show context with nothing selected
 
731
                if self.get_selected_left() == None:
 
732
                    return
 
733
 
 
734
                # Create a menu
 
735
                from menu import OliveMenu
 
736
                menu = OliveMenu(path=self.get_path(),
 
737
                                 selected=self.get_selected_left(),
 
738
                                 app=self)
 
739
                
 
740
                menu.left_context_menu().popup(None, None, None, 0,
 
741
                                               event.time)
 
742
        else:
 
743
            if treeselection is not None:
 
744
                treeselection.unselect_all()
827
745
 
828
746
    def on_treeview_left_row_activated(self, treeview, path, view_column):
829
747
        """ Occurs when somebody double-clicks or enters an item in the
837
755
            self.refresh_right()
838
756
 
839
757
    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:
 
758
        """ Occurs when somebody clicks in the file list. """
 
759
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
 
760
        if event.button == 1:
 
761
            if treepathpos is None and widget.get_selection is not None:
 
762
                treeselection = widget.get_selection()
 
763
                treeselection.unselect_all()
 
764
        elif event.button == 3:
 
765
            treeselection = widget.get_selection()
 
766
            if treepathpos is not None:
 
767
                treeselection.select_path(treepathpos[0])
 
768
            else:
 
769
                if treeselection is not None:
 
770
                    treeselection.unselect_all()
842
771
            # Create a menu
843
772
            from menu import OliveMenu
844
773
            menu = OliveMenu(path=self.get_path(),
848
777
            m_open = menu.ui.get_widget('/context_right/open')
849
778
            m_add = menu.ui.get_widget('/context_right/add')
850
779
            m_remove = menu.ui.get_widget('/context_right/remove')
 
780
            m_remove_and_delete = menu.ui.get_widget('/context_right/remove_and_delete')
851
781
            m_rename = menu.ui.get_widget('/context_right/rename')
852
782
            m_revert = menu.ui.get_widget('/context_right/revert')
853
783
            m_commit = menu.ui.get_widget('/context_right/commit')
861
791
                    m_open.set_sensitive(False)
862
792
                    m_add.set_sensitive(False)
863
793
                    m_remove.set_sensitive(False)
 
794
                    m_remove_and_delete.set_sensitive(False)
864
795
                    m_rename.set_sensitive(False)
865
796
                    m_revert.set_sensitive(False)
866
797
                    m_commit.set_sensitive(False)
867
798
                    m_annotate.set_sensitive(False)
868
799
                    m_diff.set_sensitive(False)
869
800
                else:
 
801
                    if treepathpos is None:
 
802
                        m_open.set_sensitive(False)
 
803
                        m_add.set_sensitive(False)
 
804
                        m_remove.set_sensitive(False)
 
805
                        m_remove_and_delete.set_sensitive(False)
 
806
                        m_rename.set_sensitive(False)
 
807
                        m_annotate.set_sensitive(False)
 
808
                        m_diff.set_sensitive(False)
 
809
                        m_revert.set_sensitive(False)
 
810
                    else:
 
811
                        m_open.set_sensitive(True)
 
812
                        m_add.set_sensitive(True)
 
813
                        m_remove.set_sensitive(True)
 
814
                        m_remove_and_delete.set_sensitive(True)
 
815
                        m_rename.set_sensitive(True)
 
816
                        m_annotate.set_sensitive(True)
 
817
                        m_diff.set_sensitive(True)
 
818
                        m_revert.set_sensitive(True)
 
819
                    m_commit.set_sensitive(True)
 
820
            except bzrerrors.NotBranchError:
 
821
                if treepathpos is None:
 
822
                    m_open.set_sensitive(False)
 
823
                else:
870
824
                    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
825
                m_add.set_sensitive(False)
881
826
                m_remove.set_sensitive(False)
 
827
                m_remove_and_delete.set_sensitive(False)
882
828
                m_rename.set_sensitive(False)
883
829
                m_revert.set_sensitive(False)
884
830
                m_commit.set_sensitive(False)
919
865
    
920
866
    def on_window_main_delete_event(self, widget, event=None):
921
867
        """ Do some stuff before exiting. """
922
 
        width, height = self.window_main.get_size()
 
868
        width, height = self.window.get_size()
923
869
        self.pref.set_preference('window_width', width)
924
870
        self.pref.set_preference('window_height', height)
925
 
        x, y = self.window_main.get_position()
 
871
        x, y = self.window.get_position()
926
872
        self.pref.set_preference('window_x', x)
927
873
        self.pref.set_preference('window_y', y)
928
874
        self.pref.set_preference('paned_position',
929
 
                                 self.hpaned_main.get_position())
 
875
                                 self.window.hpaned_main.get_position())
930
876
        
931
877
        self.pref.write()
932
 
        self.window_main.destroy()
933
 
        
934
 
    def _load_left(self):
935
 
        """ Load data into the left panel. (Bookmarks) """
936
 
        # Create TreeStore
937
 
        treestore = gtk.TreeStore(str, str)
938
 
        
939
 
        # Get bookmarks
940
 
        bookmarks = self.pref.get_bookmarks()
941
 
        
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])
947
 
        
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)
952
 
        
953
 
        # Set up the cells
954
 
        cell = gtk.CellRendererText()
955
 
        tvcolumn_bookmark.pack_start(cell, True)
956
 
        tvcolumn_bookmark.add_attribute(cell, 'text', 0)
957
 
        
958
 
        # Expand the tree
959
 
        self.treeview_left.expand_all()
960
 
 
961
 
    def _load_right(self):
962
 
        """ Load data into the right panel. (Filelist) """
963
 
        # Create ListStore
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,
967
 
                                  gobject.TYPE_STRING,
968
 
                                  gobject.TYPE_STRING,
969
 
                                  gobject.TYPE_STRING,
970
 
                                  gobject.TYPE_STRING,
971
 
                                  gobject.TYPE_STRING,
972
 
                                  gobject.TYPE_INT,
973
 
                                  gobject.TYPE_STRING,
974
 
                                  gobject.TYPE_STRING)
975
 
        
976
 
        dirs = []
977
 
        files = []
978
 
        
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] == '.':
983
 
                continue
984
 
            if os.path.isdir(self.path + os.sep + item):
985
 
                dirs.append(item)
986
 
            else:
987
 
                files.append(item)
988
 
        
989
 
        if not self.notbranch:
990
 
            branch = self.wt.branch
991
 
            tree2 = self.wt.branch.repository.revision_tree(branch.last_revision())
992
 
        
993
 
            delta = self.wt.changes_from(tree2, want_unchanged=True)
994
 
        
995
 
        # Add'em to the ListStore
996
 
        for item in dirs:
997
 
            try:
998
 
                statinfo = os.stat(self.path + os.sep + item)
999
 
            except OSError, e:
1000
 
                if e.errno == 40:
1001
 
                    continue
1002
 
                else:
1003
 
                    raise
1004
 
            liststore.append([ gtk.STOCK_DIRECTORY,
1005
 
                               True,
1006
 
                               item,
1007
 
                               '',
1008
 
                               '',
1009
 
                               "<DIR>",
1010
 
                               "<DIR>",
1011
 
                               statinfo.st_mtime,
1012
 
                               self._format_date(statinfo.st_mtime),
1013
 
                               ''])
1014
 
        for item in files:
1015
 
            status = 'unknown'
1016
 
            fileid = ''
1017
 
            if not self.notbranch:
1018
 
                filename = self.wt.relpath(self.path + os.sep + item)
1019
 
                
1020
 
                try:
1021
 
                    self.wt.lock_read()
1022
 
                    
1023
 
                    for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1024
 
                        if rpathnew == filename:
1025
 
                            status = 'renamed'
1026
 
                            fileid = id
1027
 
                    for rpath, id, kind in delta.added:
1028
 
                        if rpath == filename:
1029
 
                            status = 'added'
1030
 
                            fileid = id
1031
 
                    for rpath, id, kind in delta.removed:
1032
 
                        if rpath == filename:
1033
 
                            status = 'removed'
1034
 
                            fileid = id
1035
 
                    for rpath, id, kind, text_modified, meta_modified in delta.modified:
1036
 
                        if rpath == filename:
1037
 
                            status = 'modified'
1038
 
                            fileid = id
1039
 
                    for rpath, id, kind in delta.unchanged:
1040
 
                        if rpath == filename:
1041
 
                            status = 'unchanged'
1042
 
                            fileid = id
1043
 
                    for rpath, file_class, kind, id, entry in self.wt.list_files():
1044
 
                        if rpath == filename and file_class == 'I':
1045
 
                            status = 'ignored'
1046
 
                finally:
1047
 
                    self.wt.unlock()
1048
 
            
1049
 
            if status == 'renamed':
1050
 
                st = _i18n('renamed')
1051
 
            elif status == 'removed':
1052
 
                st = _i18n('removed')
1053
 
            elif status == 'added':
1054
 
                st = _i18n('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')
1061
 
            else:
1062
 
                st = _i18n('unknown')
1063
 
            
1064
 
            try:
1065
 
                statinfo = os.stat(self.path + os.sep + item)
1066
 
            except OSError, e:
1067
 
                if e.errno == 40:
1068
 
                    continue
1069
 
                else:
1070
 
                    raise
1071
 
            liststore.append([gtk.STOCK_FILE,
1072
 
                              False,
1073
 
                              item,
1074
 
                              st,
1075
 
                              status,
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),
1078
 
                              statinfo.st_mtime,
1079
 
                              self._format_date(statinfo.st_mtime),
1080
 
                              fileid])
1081
 
        
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)
1092
 
        
1093
 
        # Set up the cells
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)
1106
 
        
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)
1115
 
        # Set up sorting
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)
1122
 
        
1123
 
        # Set sensitivity
1124
 
        self.set_sensitivity()
1125
 
        
 
878
        self.window.destroy()
 
879
    
1126
880
    def get_selected_fileid(self):
1127
881
        """ Get the file_id of the selected file. """
1128
 
        treeselection = self.treeview_right.get_selection()
 
882
        treeselection = self.window.treeview_right.get_selection()
1129
883
        (model, iter) = treeselection.get_selected()
1130
884
        
1131
885
        if iter is None:
1135
889
    
1136
890
    def get_selected_right(self):
1137
891
        """ Get the selected filename. """
1138
 
        treeselection = self.treeview_right.get_selection()
 
892
        treeselection = self.window.treeview_right.get_selection()
1139
893
        (model, iter) = treeselection.get_selected()
1140
894
        
1141
895
        if iter is None:
1145
899
    
1146
900
    def get_selected_left(self):
1147
901
        """ Get the selected bookmark. """
1148
 
        treeselection = self.treeview_left.get_selection()
 
902
        treeselection = self.window.treeview_left.get_selection()
1149
903
        (model, iter) = treeselection.get_selected()
1150
904
        
1151
905
        if iter is None:
1155
909
 
1156
910
    def set_statusbar(self, message):
1157
911
        """ Set the statusbar message. """
1158
 
        self.statusbar.push(self.context_id, message)
 
912
        self.window.statusbar.push(self.context_id, message)
1159
913
    
1160
914
    def clear_statusbar(self):
1161
915
        """ Clean the last message from the statusbar. """
1162
 
        self.statusbar.pop(self.context_id)
 
916
        self.window.statusbar.pop(self.context_id)
1163
917
    
1164
918
    def set_sensitivity(self):
1165
919
        """ Set menu and toolbar sensitivity. """
1166
920
        if not self.remote:
1167
 
            # We're local
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)
 
921
            self.window.set_view_to_localbranch(self.notbranch)
1196
922
        else:
1197
 
            # We're remote
1198
 
            self.menuitem_branch_init.set_sensitive(False)
1199
 
            self.menuitem_branch_get.set_sensitive(True)
1200
 
            self.menuitem_branch_checkout.set_sensitive(True)
1201
 
            self.menuitem_branch_pull.set_sensitive(False)
1202
 
            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
 
            self.menuitem_branch_commit.set_sensitive(False)
1207
 
            self.menuitem_branch_tags.set_sensitive(True)
1208
 
            self.menuitem_branch_status.set_sensitive(False)
1209
 
            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)
1213
 
            self.menuitem_add_files.set_sensitive(False)
1214
 
            self.menuitem_remove_files.set_sensitive(False)
1215
 
            self.menuitem_file_make_directory.set_sensitive(False)
1216
 
            self.menuitem_file_rename.set_sensitive(False)
1217
 
            self.menuitem_file_move.set_sensitive(False)
1218
 
            self.menuitem_file_annotate.set_sensitive(False)
1219
 
            #self.menutoolbutton_diff.set_sensitive(True)
1220
 
            self.toolbutton_diff.set_sensitive(False)
1221
 
            self.toolbutton_log.set_sensitive(True)
1222
 
            self.toolbutton_commit.set_sensitive(False)
1223
 
            self.toolbutton_pull.set_sensitive(False)
1224
 
            self.toolbutton_push.set_sensitive(False)
1225
 
            self.toolbutton_update.set_sensitive(False)
 
923
            self.window.set_view_to_remotebranch()
1226
924
    
1227
925
    def refresh_left(self):
1228
926
        """ Refresh the bookmark list. """
1229
927
        
1230
 
        # Get TreeStore and clear it
1231
 
        treestore = self.treeview_left.get_model()
1232
 
        treestore.clear()
 
928
        # Get ListStore and clear it
 
929
        liststore = self.window.bookmarklist
 
930
        liststore.clear()
1233
931
 
1234
932
        # Re-read preferences
1235
933
        self.pref.read()
1237
935
        # Get bookmarks
1238
936
        bookmarks = self.pref.get_bookmarks()
1239
937
 
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])
1245
 
 
1246
 
        # Add the TreeStore to the TreeView
1247
 
        self.treeview_left.set_model(treestore)
1248
 
 
1249
 
        # Expand the tree
1250
 
        self.treeview_left.expand_all()
1251
 
 
1252
 
    def refresh_right(self, path=None):
 
938
        # Get titles and sort by title
 
939
        bookmarks = [[self.pref.get_bookmark_title(item), item, gtk.STOCK_DIRECTORY] for item in bookmarks]
 
940
        bookmarks.sort()
 
941
        for title_item in bookmarks:
 
942
            liststore.append(title_item)
 
943
        
 
944
        # Add the ListStore to the TreeView and refresh column width
 
945
        self.window.treeview_left.set_model(liststore)
 
946
        self.window.treeview_left.columns_autosize()
 
947
 
 
948
    def refresh_right(self):
1253
949
        """ Refresh the file list. """
1254
950
        if not self.remote:
1255
951
            # We're local
1256
952
            from bzrlib.workingtree import WorkingTree
1257
953
    
1258
 
            if path is None:
1259
 
                path = self.get_path()
1260
 
    
1261
 
            # A workaround for double-clicking Bookmarks
1262
 
            if not os.path.exists(path):
1263
 
                return
1264
 
    
 
954
            path = self.get_path()
 
955
            
1265
956
            # Get ListStore and clear it
1266
 
            liststore = self.treeview_right.get_model()
 
957
            liststore = self.window.filelist
1267
958
            liststore.clear()
1268
 
            
1269
 
            # Show Status column
1270
 
            self._tvcolumn_status.set_visible(True)
1271
959
    
1272
960
            dirs = []
1273
961
            files = []
1284
972
                else:
1285
973
                    files.append(item)
1286
974
            
1287
 
            # Try to open the working tree
1288
 
            notbranch = False
1289
 
            try:
1290
 
                tree1 = WorkingTree.open_containing(path)[0]
1291
 
            except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
1292
 
                notbranch = True
1293
 
            
1294
 
            if not notbranch:
1295
 
                branch = tree1.branch
1296
 
                tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
1297
 
            
1298
 
                delta = tree1.changes_from(tree2, want_unchanged=True)
 
975
            self.window.col_status.set_visible(False)
 
976
            if not self.notbranch:
 
977
                try:
 
978
                    tree1 = WorkingTree.open_containing(os.path.realpath(path))[0]
 
979
                    branch = tree1.branch
 
980
                    tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
1299
981
                
 
982
                    delta = tree1.changes_from(tree2, want_unchanged=True)
 
983
                    
 
984
                    # Show Status column
 
985
                    self.window.col_status.set_visible(True)
 
986
                except bzrerrors.LockContention:
 
987
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR, allowPopup=True)
 
988
                    self.window.location_status.connect_object('clicked', error_dialog, 
 
989
                                       *(_i18n('Branch is locked'),
 
990
                                                _i18n('The branch in the current folder is locked by another Bazaar program')))
 
991
                    self.notbranch = True
 
992
                    self.window.set_view_to_localbranch(False) 
 
993
            
1300
994
            # Add'em to the ListStore
1301
995
            for item in dirs:
 
996
                status = ''
 
997
                st = ''
 
998
                fileid = ''
 
999
                if not self.notbranch:
 
1000
                    filename = tree1.relpath(os.path.join(os.path.realpath(path), item))
 
1001
                    
 
1002
                    st, status = self.statusmapper(filename, delta)
 
1003
                    if not ignored_files and status == 'ignored':
 
1004
                        continue
 
1005
                
1302
1006
                try:
1303
1007
                    statinfo = os.stat(self.path + os.sep + item)
1304
1008
                except OSError, e:
1305
 
                    if e.errno == 40:
 
1009
                    if e.errno in self.acceptable_errors:
1306
1010
                        continue
1307
1011
                    else:
1308
1012
                        raise
1309
 
                liststore.append([gtk.STOCK_DIRECTORY,
1310
 
                                  True,
1311
 
                                  item,
1312
 
                                  '',
1313
 
                                  '',
1314
 
                                  "<DIR>",
1315
 
                                  "<DIR>",
1316
 
                                  statinfo.st_mtime,
1317
 
                                  self._format_date(statinfo.st_mtime),
1318
 
                                  ''])
 
1013
                liststore.append([ gtk.STOCK_DIRECTORY,
 
1014
                                   True,
 
1015
                                   item,
 
1016
                                   st,
 
1017
                                   status,
 
1018
                                   "<DIR>",
 
1019
                                   "<DIR>",
 
1020
                                   statinfo.st_mtime,
 
1021
                                   self._format_date(statinfo.st_mtime),
 
1022
                                   ''])
1319
1023
            for item in files:
1320
 
                status = 'unknown'
 
1024
                status = ''
 
1025
                st = ''
1321
1026
                fileid = ''
1322
 
                if not notbranch:
1323
 
                    filename = tree1.relpath(path + os.sep + item)
 
1027
                if not self.notbranch:
 
1028
                    filename = tree1.relpath(os.path.join(os.path.realpath(path), item))
1324
1029
                    
1325
 
                    try:
1326
 
                        self.wt.lock_read()
1327
 
                        
1328
 
                        for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1329
 
                            if rpathnew == filename:
1330
 
                                status = 'renamed'
1331
 
                                fileid = id
1332
 
                        for rpath, id, kind in delta.added:
1333
 
                            if rpath == filename:
1334
 
                                status = 'added'
1335
 
                                fileid = id
1336
 
                        for rpath, id, kind in delta.removed:
1337
 
                            if rpath == filename:
1338
 
                                status = 'removed'
1339
 
                                fileid = id
1340
 
                        for rpath, id, kind, text_modified, meta_modified in delta.modified:
1341
 
                            if rpath == filename:
1342
 
                                status = 'modified'
1343
 
                                fileid = id
1344
 
                        for rpath, id, kind in delta.unchanged:
1345
 
                            if rpath == filename:
1346
 
                                status = 'unchanged'
1347
 
                                fileid = id
1348
 
                        for rpath, file_class, kind, id, entry in self.wt.list_files():
1349
 
                            if rpath == filename and file_class == 'I':
1350
 
                                status = 'ignored'
1351
 
                    finally:
1352
 
                        self.wt.unlock()
1353
 
                
1354
 
                if status == 'renamed':
1355
 
                    st = _i18n('renamed')
1356
 
                elif status == 'removed':
1357
 
                    st = _i18n('removed')
1358
 
                elif status == 'added':
1359
 
                    st = _i18n('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:
 
1030
                    st, status = self.statusmapper(filename, delta)
 
1031
                    if not ignored_files and status == 'ignored':
1367
1032
                        continue
1368
 
                else:
1369
 
                    st = _i18n('unknown')
1370
1033
                
1371
1034
                try:
1372
1035
                    statinfo = os.stat(self.path + os.sep + item)
1373
1036
                except OSError, e:
1374
 
                    if e.errno == 40:
 
1037
                    if e.errno in self.acceptable_errors:
1375
1038
                        continue
1376
1039
                    else:
1377
1040
                        raise
1389
1052
            # We're remote
1390
1053
            
1391
1054
            # Get ListStore and clear it
1392
 
            liststore = self.treeview_right.get_model()
 
1055
            liststore = self.window.filelist
1393
1056
            liststore.clear()
1394
1057
            
1395
1058
            # Hide Status column
1396
 
            self._tvcolumn_status.set_visible(False)
 
1059
            self.window.col_status.set_visible(False)
1397
1060
            
1398
1061
            dirs = []
1399
1062
            files = []
1400
1063
            
1401
 
            self._show_stock_image(gtk.STOCK_REFRESH)
 
1064
            self.window.set_location_status(gtk.STOCK_REFRESH)
1402
1065
            
1403
1066
            for (name, type) in self.remote_entries:
1404
1067
                if type.kind == 'directory':
1463
1126
                while gtk.events_pending():
1464
1127
                    gtk.main_iteration()
1465
1128
            
1466
 
            self.image_location_error.destroy()
 
1129
            self.window.location_status.destroy()
1467
1130
 
1468
1131
        # Columns should auto-size
1469
 
        self.treeview_right.columns_autosize()
 
1132
        self.window.treeview_right.columns_autosize()
1470
1133
        
1471
1134
        # Set sensitivity
1472
1135
        self.set_sensitivity()
 
1136
    
 
1137
    def statusmapper(self, filename, delta):
 
1138
        status = 'unknown'
 
1139
        try:
 
1140
            self.wt.lock_read()
 
1141
            
 
1142
            for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
 
1143
                if rpathnew == filename:
 
1144
                    status = 'renamed'
 
1145
                    fileid = id
 
1146
            for rpath, id, kind in delta.added:
 
1147
                if rpath == filename:
 
1148
                    status = 'added'
 
1149
                    fileid = id
 
1150
            for rpath, id, kind in delta.removed:
 
1151
                if rpath == filename:
 
1152
                    status = 'removed'
 
1153
                    fileid = id
 
1154
            for rpath, id, kind, text_modified, meta_modified in delta.modified:
 
1155
                if rpath == filename:
 
1156
                    status = 'modified'
 
1157
                    fileid = id
 
1158
            for rpath, id, kind in delta.unchanged:
 
1159
                if rpath == filename:
 
1160
                    status = 'unchanged'
 
1161
                    fileid = id
 
1162
            for rpath, file_class, kind, id, entry in self.wt.list_files():
 
1163
                if rpath == filename and file_class == 'I':
 
1164
                    status = 'ignored'
 
1165
        finally:
 
1166
            self.wt.unlock()
 
1167
    
 
1168
        if status == 'renamed':
 
1169
            st = _i18n('renamed')
 
1170
        elif status == 'removed':
 
1171
            st = _i18n('removed')
 
1172
        elif status == 'added':
 
1173
            st = _i18n('added')
 
1174
        elif status == 'modified':
 
1175
            st = _i18n('modified')
 
1176
        elif status == 'unchanged':
 
1177
            st = _i18n('unchanged')
 
1178
        elif status == 'ignored':
 
1179
            st = _i18n('ignored')
 
1180
        else:
 
1181
            st = _i18n('unknown')
 
1182
        return st, status
1473
1183
 
1474
1184
    def _harddisks(self):
1475
1185
        """ Returns hard drive letters under Win32. """
1480
1190
            if sys.platform == 'win32':
1481
1191
                print "pyWin32 modules needed to run Olive on Win32."
1482
1192
                sys.exit(1)
1483
 
            else:
1484
 
                pass
1485
1193
        
1486
1194
        driveletters = []
1487
1195
        for drive in string.ascii_uppercase:
1488
 
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
 
1196
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED or\
 
1197
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOTE or\
 
1198
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOVABLE:
1489
1199
                driveletters.append(drive+':')
1490
1200
        return driveletters
1491
1201
    
1504
1214
        if active >= 0:
1505
1215
            drive = model[active][0]
1506
1216
            self.set_path(drive + '\\')
1507
 
            self.refresh_right(drive + '\\')
 
1217
            self.refresh_right()
1508
1218
    
1509
1219
    def check_for_changes(self):
1510
1220
        """ Check whether there were changes in the current working tree. """
1583
1293
                    return True
1584
1294
            # Either it's not a directory or not in the inventory
1585
1295
            return False
1586
 
    
1587
 
    def _show_stock_image(self, stock_id):
1588
 
        """ Show a stock image next to the location entry. """
1589
 
        self.image_location_error.destroy()
1590
 
        self.image_location_error = gtk.image_new_from_stock(stock_id, gtk.ICON_SIZE_BUTTON)
1591
 
        self.hbox_location.pack_start(self.image_location_error, False, False, 0)
1592
 
        if sys.platform == 'win32':
1593
 
            self.hbox_location.reorder_child(self.image_location_error, 2)
1594
 
        else:
1595
 
            self.hbox_location.reorder_child(self.image_location_error, 1)
1596
 
        self.image_location_error.show()
1597
 
        while gtk.events_pending():
1598
 
            gtk.main_iteration()
1599
1296
 
1600
1297
import ConfigParser
1601
1298
 
1724
1421
                return self._get_default(option)
1725
1422
            except KeyError:
1726
1423
                return None
1727