/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: Vincent Ladeuil
  • Date: 2009-05-04 07:01:58 UTC
  • mto: This revision was merged to the branch mainline in revision 631.
  • Revision ID: v.ladeuil+lp@free.fr-20090504070158-j5cvke5s82ow4v53
Upgrade COMPATIBLE_BZR_VERSIONS.

* __init__.py: 
(COMPATIBLE_BZR_VERSIONS): Add 1.15.0.

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
    dialog = gtk.AboutDialog()
 
64
    dialog.set_name("Olive")
71
65
    dialog.set_version(__version__)
 
66
    dialog.set_copyright("Copyright (C) 2006-2008 Szilveszter Farkas (Phanatic)")
 
67
    dialog.set_website("https://launchpad.net/bzr-gtk")
 
68
    dialog.set_website_label("https://launchpad.net/bzr-gtk")
 
69
    dialog.set_icon_from_file(icon_path("oliveicon2.png"))
 
70
    dialog.set_logo(gtk.gdk.pixbuf_new_from_file(icon_path("oliveicon2.png")))
72
71
    dialog.set_authors([ _i18n("Lead Developer:"),
73
72
                         "Szilveszter Farkas <szilveszter.farkas@gmail.com>",
74
73
                         _i18n("Contributors:"),
82
81
    # Destroy the dialog
83
82
    dialog.destroy()
84
83
 
 
84
 
85
85
class OliveGtk:
86
86
    """ The main Olive GTK frontend class. This is called when launching the
87
87
    program. """
88
88
    
89
89
    def __init__(self):
90
 
        self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
91
 
        self.window = self.toplevel.get_widget('window_main')
 
90
        self.window = OliveGui(calling_app = self)
 
91
        
92
92
        self.pref = Preferences()
93
93
        self.path = None
94
94
 
95
95
        # Initialize the statusbar
96
 
        self.statusbar = self.toplevel.get_widget('statusbar')
97
 
        self.context_id = self.statusbar.get_context_id('olive')
 
96
        self.context_id = self.window.statusbar.get_context_id('olive')
98
97
        
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
98
        # Get the drive selector
142
99
        self.combobox_drive = gtk.combo_box_new_text()
143
100
        self.combobox_drive.connect("changed", self._refresh_drives)
144
101
        
145
102
        # 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')
 
103
        self.hbox_location = self.window.locationbar
 
104
        self.button_location_up = self.window.button_location_up
 
105
        self.button_location_jump = self.window.button_location_jump
 
106
        self.entry_location = self.window.entry_location
151
107
        
152
108
        # 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)
 
109
        self.check_history = self.window.checkbutton_history
 
110
        self.entry_history = self.window.entry_history_revno
 
111
        self.button_history = self.window.button_history_browse
213
112
        
214
113
        self._just_started = True
215
114
        
222
121
        self.window.move(x, y)
223
122
        # Apply paned position
224
123
        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)
 
124
        self.window.hpaned_main.set_position(pos)
230
125
        
231
126
        # Now we can show the window
232
127
        self.window.show()
238
133
            self.combobox_drive.show()
239
134
            self.gen_hard_selector()
240
135
        
241
 
        self._load_left()
 
136
        self.refresh_left()
242
137
 
243
138
        # 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'))
 
139
        self.window.mb_view_showhidden.set_active(self.pref.get_preference('dotted_files', 'bool'))
 
140
        self.window.mb_view_showignored.set_active(self.pref.get_preference('ignored_files', 'bool'))
246
141
 
247
142
        # We're starting local
248
143
        self.remote = False
251
146
        self.remote_revision = None
252
147
        
253
148
        self.set_path(os.getcwd())
254
 
        self._load_right()
 
149
        self.refresh_right()
255
150
        
256
151
        self._just_started = False
257
152
 
258
153
    def set_path(self, path, force_remote=False):
 
154
        self.window.location_status.destroy()
259
155
        self.notbranch = False
260
156
        
261
157
        if force_remote:
262
158
            # Forcing remote mode (reading data from inventory)
263
 
            self._show_stock_image(gtk.STOCK_DISCONNECT)
 
159
            self.window.set_location_status(gtk.STOCK_DISCONNECT)
264
160
            try:
265
161
                br = Branch.open_containing(path)[0]
266
162
            except bzrerrors.NotBranchError:
267
 
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
163
                self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
268
164
                self.check_history.set_active(False)
269
165
                self.check_history.set_sensitive(False)
270
166
                return False
271
167
            except bzrerrors.UnsupportedProtocol:
272
 
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
168
                self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
273
169
                self.check_history.set_active(False)
274
170
                self.check_history.set_sensitive(False)
275
171
                return False
276
172
            
277
 
            self._show_stock_image(gtk.STOCK_CONNECT)
 
173
            self.window.set_location_status(gtk.STOCK_CONNECT)
278
174
            
279
175
            self.remote = True
280
176
           
303
199
                self.button_location_up.set_sensitive(True)
304
200
        else:
305
201
            if os.path.isdir(path):
306
 
                self.image_location_error.destroy()
307
202
                self.remote = False
308
203
                
309
204
                # We're local
310
205
                try:
311
 
                    self.wt, self.wtpath = WorkingTree.open_containing(path)
 
206
                    self.wt, self.wtpath = WorkingTree.open_containing(os.path.realpath(path))
312
207
                except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
313
208
                    self.notbranch = True
 
209
                except bzrerrors.PermissionDenied:
 
210
                    self.window.set_location_status(gtk.STOCK_DIALOG_WARNING, allowPopup=True)
 
211
                    self.window.location_status.connect_object('clicked', warning_dialog, 
 
212
                                       *(_i18n('Branch information unreadable'),
 
213
                                                _i18n('The current folder is a branch but the .bzr folder is not readable')))
 
214
                    self.notbranch = True
314
215
                
315
216
                # If we're in the root, we cannot go up anymore
316
217
                if sys.platform == 'win32':
327
228
            elif not os.path.isfile(path):
328
229
                # Doesn't seem to be a file nor a directory, trying to open a
329
230
                # remote location
330
 
                self._show_stock_image(gtk.STOCK_DISCONNECT)
 
231
                self.window.set_location_status(gtk.STOCK_DISCONNECT)
331
232
                try:
332
233
                    br = Branch.open_containing(path)[0]
333
234
                except bzrerrors.NotBranchError:
334
 
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
235
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
335
236
                    self.check_history.set_active(False)
336
237
                    self.check_history.set_sensitive(False)
337
238
                    return False
338
239
                except bzrerrors.UnsupportedProtocol:
339
 
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
240
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
340
241
                    self.check_history.set_active(False)
341
242
                    self.check_history.set_sensitive(False)
342
243
                    return False
343
244
                
344
 
                self._show_stock_image(gtk.STOCK_CONNECT)
 
245
                self.window.set_location_status(gtk.STOCK_CONNECT)
345
246
                
346
247
                self.remote = True
347
248
               
375
276
        else:
376
277
            self.check_history.set_sensitive(True)
377
278
        
378
 
        self.statusbar.push(self.context_id, path)
 
279
        self.window.statusbar.push(self.context_id, path)
379
280
        self.entry_location.set_text(path)
380
281
        self.path = path
381
282
        return True
408
309
            if response == gtk.RESPONSE_OK:
409
310
                if revb.selected_revno is not None:
410
311
                    self.entry_history.set_text(revb.selected_revno)
 
312
                    self.on_entry_history_revno_activate()
411
313
            
412
314
            revb.destroy()
413
315
    
438
340
            # History Mode activated
439
341
            self.entry_history.set_sensitive(True)
440
342
            self.button_history.set_sensitive(True)
 
343
            if self.entry_history.get_text() != "":
 
344
                self.on_entry_history_revno_activate()
441
345
        else:
442
346
            # History Mode deactivated
443
347
            self.entry_history.set_sensitive(False)
444
348
            self.button_history.set_sensitive(False)
 
349
            
 
350
            # Return right window to normal view by acting like we jump to it
 
351
            self.on_button_location_jump_clicked(widget)
445
352
    
446
353
    @show_bzr_error
447
 
    def on_entry_history_revno_key_press_event(self, widget, event):
 
354
    def on_entry_history_revno_activate(self, widget=None):
448
355
        """ 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
 
    
 
356
        path = self.get_path()
 
357
        if not self.remote:
 
358
            self.remote = True
 
359
            self.remote_branch = self.wt.branch
 
360
        
 
361
        revno = int(self.entry_history.get_text())
 
362
        self.remote_revision = self.remote_branch.get_rev_id(revno)
 
363
        if self.set_path(path, True):
 
364
            self.refresh_right()
 
365
 
468
366
    def on_menuitem_add_files_activate(self, widget):
469
367
        """ 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
 
    
 
368
        from bzrlib.plugins.gtk.olive.add import AddDialog
 
369
        add = AddDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
370
        response = add.run()
 
371
        add.destroy()
 
372
        if response == gtk.RESPONSE_OK:
 
373
            self.refresh_right()
 
374
 
474
375
    def on_menuitem_branch_get_activate(self, widget):
475
376
        """ Branch/Get... menu handler. """
476
377
        from bzrlib.plugins.gtk.branch import BranchDialog
508
409
    @show_bzr_error
509
410
    def on_menuitem_branch_commit_activate(self, widget):
510
411
        """ Branch/Commit... menu handler. """
511
 
#     def __init__(self, wt, wtpath, notbranch, selected=None, parent=None):
512
412
        selected = self.get_selected_right()
513
413
        if selected:
514
414
            selected = os.path.join(self.wtpath, selected)
541
441
                         _i18n('Please commit or revert the changes before merging.'))
542
442
        else:
543
443
            parent_branch_path = self.wt.branch.get_parent()
544
 
            merge = MergeDialog(self.wt, self.wtpath,default_branch_path=parent_branch_path )
545
 
            merge.display()
 
444
            merge = MergeDialog(self.wt, self.wtpath, parent_branch_path, self.window)
 
445
            response = merge.run()
 
446
            merge.destroy()
 
447
            if response == gtk.RESPONSE_OK:
 
448
                self.refresh_right()
546
449
 
547
450
    @show_bzr_error
548
451
    def on_menuitem_branch_missing_revisions_activate(self, widget):
625
528
        
626
529
    @show_bzr_error
627
530
    def on_menuitem_branch_update_activate(self, widget):
628
 
        """ Brranch/checkout update menu handler. """
 
531
        """ Branch/checkout update menu handler. """
629
532
        
630
533
        ret = self.wt.update()
631
534
        conflicts = self.wt.conflicts()
633
536
            info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
634
537
        else:
635
538
            info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
 
539
        self.refresh_right()
636
540
    
637
541
    def on_menuitem_branch_push_activate(self, widget):
638
542
        """ Branch/Push... menu handler. """
644
548
    @show_bzr_error
645
549
    def on_menuitem_branch_revert_activate(self, widget):
646
550
        """ Branch/Revert all changes menu handler. """
647
 
        ret = self.wt.revert([])
 
551
        ret = self.wt.revert(None)
648
552
        if ret:
649
553
            warning_dialog(_i18n('Conflicts detected'),
650
554
                           _i18n('Please have a look at the working tree before continuing.'))
716
620
    
717
621
    def on_menuitem_file_make_directory_activate(self, widget):
718
622
        """ File/Make directory... menu handler. """
719
 
        from mkdir import OliveMkdir
720
 
        mkdir = OliveMkdir(self.wt, self.wtpath)
721
 
        mkdir.display()
 
623
        from bzrlib.plugins.gtk.olive.mkdir import MkdirDialog
 
624
        mkdir = MkdirDialog(self.wt, self.wtpath, self.window)
 
625
        response = mkdir.run()
 
626
        mkdir.destroy()
 
627
        if response == gtk.RESPONSE_OK:
 
628
            self.refresh_right()
722
629
    
723
630
    def on_menuitem_file_move_activate(self, widget):
724
631
        """ File/Move... menu handler. """
725
 
        from move import OliveMove
726
 
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
727
 
        move.display()
 
632
        from bzrlib.plugins.gtk.olive.move import MoveDialog
 
633
        move = MoveDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
634
        response = move.run()
 
635
        move.destroy()
 
636
        if response == gtk.RESPONSE_OK:
 
637
            self.refresh_right()
728
638
    
729
639
    def on_menuitem_file_rename_activate(self, widget):
730
640
        """ File/Rename... menu handler. """
731
 
        from rename import OliveRename
732
 
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
733
 
        rename.display()
 
641
        from bzrlib.plugins.gtk.olive.rename import RenameDialog
 
642
        rename = RenameDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
643
        response = rename.run()
 
644
        rename.destroy()
 
645
        if response == gtk.RESPONSE_OK:
 
646
            self.refresh_right()
734
647
 
735
648
    def on_menuitem_remove_file_activate(self, widget):
736
649
        """ Remove (unversion) selected file. """
737
 
        from remove import OliveRemoveDialog
738
 
        remove = OliveRemoveDialog(self.wt, self.wtpath,
 
650
        from bzrlib.plugins.gtk.olive.remove import RemoveDialog
 
651
        remove = RemoveDialog(self.wt, self.wtpath,
739
652
                                   selected=self.get_selected_right(),
740
653
                                   parent=self.window)
741
654
        response = remove.run()
744
657
            remove.hide()
745
658
        
746
659
            if response == gtk.RESPONSE_OK:
747
 
                self.set_path(self.path)
748
660
                self.refresh_right()
749
661
            
750
662
            remove.destroy()
758
670
    
759
671
    def on_menuitem_stats_infos_activate(self, widget):
760
672
        """ Statistics/Informations... menu handler. """
761
 
        from info import OliveInfo
 
673
        from bzrlib.plugins.gtk.olive.info import InfoDialog
762
674
        if self.remote:
763
 
            info = OliveInfo(self.remote_branch)
 
675
            info = InfoDialog(self.remote_branch)
764
676
        else:
765
 
            info = OliveInfo(self.wt.branch)
 
677
            info = InfoDialog(self.wt.branch)
766
678
        info.display()
767
679
    
768
680
    def on_menuitem_stats_log_activate(self, widget):
773
685
        else:
774
686
            branch = self.remote_branch
775
687
 
776
 
        window = branchwin.BranchWindow(branch, branch.last_revision(), None, parent=self.window)
 
688
        window = branchwin.BranchWindow(branch, [branch.last_revision()], None, 
 
689
                                        parent=self.window)
777
690
        window.show()
778
691
    
779
692
    def on_menuitem_view_refresh_activate(self, widget):
786
699
    def on_menuitem_view_show_hidden_files_activate(self, widget):
787
700
        """ View/Show hidden files menu handler. """
788
701
        self.pref.set_preference('dotted_files', widget.get_active())
 
702
        self.pref.write()
789
703
        if self.path is not None:
790
704
            self.refresh_right()
791
705
 
792
706
    def on_menuitem_view_show_ignored_files_activate(self, widget):
793
707
        """ Hide/Show ignored files menu handler. """
794
708
        self.pref.set_preference('ignored_files', widget.get_active())
 
709
        self.pref.write()
795
710
        if self.path is not None:
796
711
            self.refresh_right()
797
712
            
798
713
    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()
 
714
        """ Occurs when somebody clicks in the bookmark list. """
 
715
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
 
716
        treeselection = widget.get_selection()
 
717
        if treepathpos is not None:
 
718
            treeselection.select_path(treepathpos[0])
 
719
            if event.button == 1:
 
720
                newdir = self.get_selected_left()
 
721
                if newdir == None:
 
722
                    return
 
723
 
 
724
                if self.set_path(newdir):
 
725
                    self.refresh_right()
 
726
            elif event.button == 3:
 
727
                # Don't show context with nothing selected
 
728
                if self.get_selected_left() == None:
 
729
                    return
 
730
 
 
731
                # Create a menu
 
732
                from menu import OliveMenu
 
733
                menu = OliveMenu(path=self.get_path(),
 
734
                                 selected=self.get_selected_left(),
 
735
                                 app=self)
 
736
                
 
737
                menu.left_context_menu().popup(None, None, None, 0,
 
738
                                               event.time)
 
739
        else:
 
740
            if treeselection is not None:
 
741
                treeselection.unselect_all()
827
742
 
828
743
    def on_treeview_left_row_activated(self, treeview, path, view_column):
829
744
        """ Occurs when somebody double-clicks or enters an item in the
837
752
            self.refresh_right()
838
753
 
839
754
    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:
 
755
        """ Occurs when somebody clicks in the file list. """
 
756
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
 
757
        if event.button == 1:
 
758
            if treepathpos is None and widget.get_selection is not None:
 
759
                treeselection = widget.get_selection()
 
760
                treeselection.unselect_all()
 
761
        elif event.button == 3:
 
762
            treeselection = widget.get_selection()
 
763
            if treepathpos is not None:
 
764
                treeselection.select_path(treepathpos[0])
 
765
            else:
 
766
                if treeselection is not None:
 
767
                    treeselection.unselect_all()
842
768
            # Create a menu
843
769
            from menu import OliveMenu
844
770
            menu = OliveMenu(path=self.get_path(),
848
774
            m_open = menu.ui.get_widget('/context_right/open')
849
775
            m_add = menu.ui.get_widget('/context_right/add')
850
776
            m_remove = menu.ui.get_widget('/context_right/remove')
 
777
            m_remove_and_delete = menu.ui.get_widget('/context_right/remove_and_delete')
851
778
            m_rename = menu.ui.get_widget('/context_right/rename')
852
779
            m_revert = menu.ui.get_widget('/context_right/revert')
853
780
            m_commit = menu.ui.get_widget('/context_right/commit')
861
788
                    m_open.set_sensitive(False)
862
789
                    m_add.set_sensitive(False)
863
790
                    m_remove.set_sensitive(False)
 
791
                    m_remove_and_delete.set_sensitive(False)
864
792
                    m_rename.set_sensitive(False)
865
793
                    m_revert.set_sensitive(False)
866
794
                    m_commit.set_sensitive(False)
867
795
                    m_annotate.set_sensitive(False)
868
796
                    m_diff.set_sensitive(False)
869
797
                else:
 
798
                    if treepathpos is None:
 
799
                        m_open.set_sensitive(False)
 
800
                        m_add.set_sensitive(False)
 
801
                        m_remove.set_sensitive(False)
 
802
                        m_remove_and_delete.set_sensitive(False)
 
803
                        m_rename.set_sensitive(False)
 
804
                        m_annotate.set_sensitive(False)
 
805
                        m_diff.set_sensitive(False)
 
806
                        m_revert.set_sensitive(False)
 
807
                    else:
 
808
                        m_open.set_sensitive(True)
 
809
                        m_add.set_sensitive(True)
 
810
                        m_remove.set_sensitive(True)
 
811
                        m_remove_and_delete.set_sensitive(True)
 
812
                        m_rename.set_sensitive(True)
 
813
                        m_annotate.set_sensitive(True)
 
814
                        m_diff.set_sensitive(True)
 
815
                        m_revert.set_sensitive(True)
 
816
                    m_commit.set_sensitive(True)
 
817
            except bzrerrors.NotBranchError:
 
818
                if treepathpos is None:
 
819
                    m_open.set_sensitive(False)
 
820
                else:
870
821
                    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
822
                m_add.set_sensitive(False)
881
823
                m_remove.set_sensitive(False)
 
824
                m_remove_and_delete.set_sensitive(False)
882
825
                m_rename.set_sensitive(False)
883
826
                m_revert.set_sensitive(False)
884
827
                m_commit.set_sensitive(False)
919
862
    
920
863
    def on_window_main_delete_event(self, widget, event=None):
921
864
        """ Do some stuff before exiting. """
922
 
        width, height = self.window_main.get_size()
 
865
        width, height = self.window.get_size()
923
866
        self.pref.set_preference('window_width', width)
924
867
        self.pref.set_preference('window_height', height)
925
 
        x, y = self.window_main.get_position()
 
868
        x, y = self.window.get_position()
926
869
        self.pref.set_preference('window_x', x)
927
870
        self.pref.set_preference('window_y', y)
928
871
        self.pref.set_preference('paned_position',
929
 
                                 self.hpaned_main.get_position())
 
872
                                 self.window.hpaned_main.get_position())
930
873
        
931
874
        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()
 
875
        self.window.destroy()
960
876
 
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
 
        
1126
877
    def get_selected_fileid(self):
1127
878
        """ Get the file_id of the selected file. """
1128
 
        treeselection = self.treeview_right.get_selection()
 
879
        treeselection = self.window.treeview_right.get_selection()
1129
880
        (model, iter) = treeselection.get_selected()
1130
881
        
1131
882
        if iter is None:
1135
886
    
1136
887
    def get_selected_right(self):
1137
888
        """ Get the selected filename. """
1138
 
        treeselection = self.treeview_right.get_selection()
 
889
        treeselection = self.window.treeview_right.get_selection()
1139
890
        (model, iter) = treeselection.get_selected()
1140
891
        
1141
892
        if iter is None:
1145
896
    
1146
897
    def get_selected_left(self):
1147
898
        """ Get the selected bookmark. """
1148
 
        treeselection = self.treeview_left.get_selection()
 
899
        treeselection = self.window.treeview_left.get_selection()
1149
900
        (model, iter) = treeselection.get_selected()
1150
901
        
1151
902
        if iter is None:
1155
906
 
1156
907
    def set_statusbar(self, message):
1157
908
        """ Set the statusbar message. """
1158
 
        self.statusbar.push(self.context_id, message)
 
909
        self.window.statusbar.push(self.context_id, message)
1159
910
    
1160
911
    def clear_statusbar(self):
1161
912
        """ Clean the last message from the statusbar. """
1162
 
        self.statusbar.pop(self.context_id)
 
913
        self.window.statusbar.pop(self.context_id)
1163
914
    
1164
915
    def set_sensitivity(self):
1165
916
        """ Set menu and toolbar sensitivity. """
1166
917
        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)
 
918
            self.window.set_view_to_localbranch(self.notbranch)
1196
919
        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)
 
920
            self.window.set_view_to_remotebranch()
1226
921
    
1227
922
    def refresh_left(self):
1228
923
        """ Refresh the bookmark list. """
1229
924
        
1230
 
        # Get TreeStore and clear it
1231
 
        treestore = self.treeview_left.get_model()
1232
 
        treestore.clear()
 
925
        # Get ListStore and clear it
 
926
        liststore = self.window.bookmarklist
 
927
        liststore.clear()
1233
928
 
1234
929
        # Re-read preferences
1235
930
        self.pref.read()
1237
932
        # Get bookmarks
1238
933
        bookmarks = self.pref.get_bookmarks()
1239
934
 
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):
 
935
        # Get titles and sort by title
 
936
        bookmarks = [[self.pref.get_bookmark_title(item), item, gtk.STOCK_DIRECTORY] for item in bookmarks]
 
937
        bookmarks.sort()
 
938
        for title_item in bookmarks:
 
939
            liststore.append(title_item)
 
940
        
 
941
        # Add the ListStore to the TreeView and refresh column width
 
942
        self.window.treeview_left.set_model(liststore)
 
943
        self.window.treeview_left.columns_autosize()
 
944
 
 
945
    def refresh_right(self):
1253
946
        """ Refresh the file list. """
1254
947
        if not self.remote:
1255
948
            # We're local
1256
949
            from bzrlib.workingtree import WorkingTree
1257
 
    
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
 
    
 
950
            
 
951
            path = self.get_path()
 
952
            
1265
953
            # Get ListStore and clear it
1266
 
            liststore = self.treeview_right.get_model()
 
954
            liststore = self.window.filelist
1267
955
            liststore.clear()
1268
956
            
1269
 
            # Show Status column
1270
 
            self._tvcolumn_status.set_visible(True)
1271
 
    
1272
957
            dirs = []
1273
958
            files = []
1274
 
    
 
959
            
1275
960
            # Fill the appropriate lists
1276
961
            dotted_files = self.pref.get_preference('dotted_files', 'bool')
1277
962
            ignored_files = self.pref.get_preference('ignored_files', 'bool')
1278
 
 
 
963
            
1279
964
            for item in os.listdir(path):
1280
965
                if not dotted_files and item[0] == '.':
1281
966
                    continue
1282
 
                if os.path.isdir(path + os.sep + item):
 
967
                if os.path.isdir(os.path.join(path, item)):
1283
968
                    dirs.append(item)
1284
969
                else:
1285
970
                    files.append(item)
1286
971
            
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)
1299
 
                
 
972
            self.window.col_status.set_visible(False)
 
973
            if not self.notbranch:
 
974
                try:
 
975
                    tree1 = WorkingTree.open_containing(os.path.realpath(path))[0]
 
976
                    branch = tree1.branch
 
977
                    tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
 
978
                    
 
979
                    delta = tree1.changes_from(tree2, want_unchanged=True)
 
980
                    
 
981
                    # Show Status column
 
982
                    self.window.col_status.set_visible(True)
 
983
                except bzrerrors.LockContention:
 
984
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR, allowPopup=True)
 
985
                    self.window.location_status.connect_object('clicked', error_dialog, 
 
986
                                       *(_i18n('Branch is locked'),
 
987
                                                _i18n('The branch in the current folder is locked by another Bazaar program')))
 
988
                    self.notbranch = True
 
989
                    self.window.set_view_to_localbranch(False) 
 
990
            
1300
991
            # Add'em to the ListStore
1301
992
            for item in dirs:
1302
 
                try:
1303
 
                    statinfo = os.stat(self.path + os.sep + item)
1304
 
                except OSError, e:
1305
 
                    if e.errno == 40:
 
993
                status = ''
 
994
                st = ''
 
995
                fileid = ''
 
996
                if not self.notbranch:
 
997
                    filename = tree1.relpath(os.path.join(os.path.realpath(path), item))
 
998
                    
 
999
                    st, status = self.statusmapper(filename, delta)
 
1000
                    if not ignored_files and status == 'ignored':
1306
1001
                        continue
1307
 
                    else:
1308
 
                        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
 
                                  ''])
 
1002
                
 
1003
                statinfo = os.lstat(os.path.join(self.path, item))
 
1004
                liststore.append([ gtk.STOCK_DIRECTORY,
 
1005
                                   True,
 
1006
                                   item,
 
1007
                                   st,
 
1008
                                   status,
 
1009
                                   "<DIR>",
 
1010
                                   "<DIR>",
 
1011
                                   statinfo.st_mtime,
 
1012
                                   self._format_date(statinfo.st_mtime),
 
1013
                                   ''])
1319
1014
            for item in files:
1320
 
                status = 'unknown'
 
1015
                status = ''
 
1016
                st = ''
1321
1017
                fileid = ''
1322
 
                if not notbranch:
1323
 
                    filename = tree1.relpath(path + os.sep + item)
 
1018
                if not self.notbranch:
 
1019
                    filename = tree1.relpath(os.path.join(os.path.realpath(path), item))
1324
1020
                    
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:
1367
 
                        continue
1368
 
                else:
1369
 
                    st = _i18n('unknown')
1370
 
                
1371
 
                try:
1372
 
                    statinfo = os.stat(self.path + os.sep + item)
1373
 
                except OSError, e:
1374
 
                    if e.errno == 40:
1375
 
                        continue
1376
 
                    else:
1377
 
                        raise
 
1021
                    st, status = self.statusmapper(filename, delta)
 
1022
                    if not ignored_files and status == 'ignored':
 
1023
                        continue
 
1024
                
 
1025
                statinfo = os.lstat(os.path.join(self.path, item))
1378
1026
                liststore.append([gtk.STOCK_FILE,
1379
1027
                                  False,
1380
1028
                                  item,
1389
1037
            # We're remote
1390
1038
            
1391
1039
            # Get ListStore and clear it
1392
 
            liststore = self.treeview_right.get_model()
 
1040
            liststore = self.window.filelist
1393
1041
            liststore.clear()
1394
1042
            
1395
1043
            # Hide Status column
1396
 
            self._tvcolumn_status.set_visible(False)
 
1044
            self.window.col_status.set_visible(False)
1397
1045
            
1398
1046
            dirs = []
1399
1047
            files = []
1400
1048
            
1401
 
            self._show_stock_image(gtk.STOCK_REFRESH)
 
1049
            self.window.set_location_status(gtk.STOCK_REFRESH)
1402
1050
            
1403
1051
            for (name, type) in self.remote_entries:
1404
1052
                if type.kind == 'directory':
1463
1111
                while gtk.events_pending():
1464
1112
                    gtk.main_iteration()
1465
1113
            
1466
 
            self.image_location_error.destroy()
 
1114
            self.window.location_status.destroy()
1467
1115
 
1468
1116
        # Columns should auto-size
1469
 
        self.treeview_right.columns_autosize()
 
1117
        self.window.treeview_right.columns_autosize()
1470
1118
        
1471
1119
        # Set sensitivity
1472
1120
        self.set_sensitivity()
 
1121
    
 
1122
    def statusmapper(self, filename, delta):
 
1123
        status = 'unknown'
 
1124
        try:
 
1125
            self.wt.lock_read()
 
1126
            
 
1127
            for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
 
1128
                if rpathnew == filename:
 
1129
                    status = 'renamed'
 
1130
                    fileid = id
 
1131
            for rpath, id, kind in delta.added:
 
1132
                if rpath == filename:
 
1133
                    status = 'added'
 
1134
                    fileid = id
 
1135
            for rpath, id, kind in delta.removed:
 
1136
                if rpath == filename:
 
1137
                    status = 'removed'
 
1138
                    fileid = id
 
1139
            for rpath, id, kind, text_modified, meta_modified in delta.modified:
 
1140
                if rpath == filename:
 
1141
                    status = 'modified'
 
1142
                    fileid = id
 
1143
            for rpath, id, kind in delta.unchanged:
 
1144
                if rpath == filename:
 
1145
                    status = 'unchanged'
 
1146
                    fileid = id
 
1147
            for rpath, file_class, kind, id, entry in self.wt.list_files():
 
1148
                if rpath == filename and file_class == 'I':
 
1149
                    status = 'ignored'
 
1150
        finally:
 
1151
            self.wt.unlock()
 
1152
    
 
1153
        if status == 'renamed':
 
1154
            st = _i18n('renamed')
 
1155
        elif status == 'removed':
 
1156
            st = _i18n('removed')
 
1157
        elif status == 'added':
 
1158
            st = _i18n('added')
 
1159
        elif status == 'modified':
 
1160
            st = _i18n('modified')
 
1161
        elif status == 'unchanged':
 
1162
            st = _i18n('unchanged')
 
1163
        elif status == 'ignored':
 
1164
            st = _i18n('ignored')
 
1165
        else:
 
1166
            st = _i18n('unknown')
 
1167
        return st, status
1473
1168
 
1474
1169
    def _harddisks(self):
1475
1170
        """ Returns hard drive letters under Win32. """
1480
1175
            if sys.platform == 'win32':
1481
1176
                print "pyWin32 modules needed to run Olive on Win32."
1482
1177
                sys.exit(1)
1483
 
            else:
1484
 
                pass
1485
1178
        
1486
1179
        driveletters = []
1487
1180
        for drive in string.ascii_uppercase:
1488
 
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
 
1181
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED or\
 
1182
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOTE or\
 
1183
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOVABLE:
1489
1184
                driveletters.append(drive+':')
1490
1185
        return driveletters
1491
1186
    
1504
1199
        if active >= 0:
1505
1200
            drive = model[active][0]
1506
1201
            self.set_path(drive + '\\')
1507
 
            self.refresh_right(drive + '\\')
 
1202
            self.refresh_right()
1508
1203
    
1509
1204
    def check_for_changes(self):
1510
1205
        """ Check whether there were changes in the current working tree. """
1583
1278
                    return True
1584
1279
            # Either it's not a directory or not in the inventory
1585
1280
            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
1281
 
1600
1282
import ConfigParser
1601
1283
 
1724
1406
                return self._get_default(option)
1725
1407
            except KeyError:
1726
1408
                return None
1727