/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: Adrian Room
  • Date: 2009-12-23 05:17:26 UTC
  • mto: This revision was merged to the branch mainline in revision 684.
  • Revision ID: ingolemo@gmail.com-20091223051726-zfl6dt9hslbyxuuh
Added tooltips and 'important button' status to the olive toolbar buttons

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.'))
655
559
    
656
560
    def on_menuitem_branch_status_activate(self, widget):
657
561
        """ Branch/Status... menu handler. """
658
 
        from bzrlib.plugins.gtk.status import StatusDialog
659
 
        status = StatusDialog(self.wt, self.wtpath)
660
 
        response = status.run()
661
 
        if response != gtk.RESPONSE_NONE:
662
 
            status.destroy()
 
562
        from bzrlib.plugins.gtk.status import StatusWindow
 
563
        status = StatusWindow(self.wt, self.wtpath)
 
564
        status.show()
663
565
    
664
566
    def on_menuitem_branch_initialize_activate(self, widget):
665
567
        """ Initialize current directory. """
716
618
    
717
619
    def on_menuitem_file_make_directory_activate(self, widget):
718
620
        """ File/Make directory... menu handler. """
719
 
        from mkdir import OliveMkdir
720
 
        mkdir = OliveMkdir(self.wt, self.wtpath)
721
 
        mkdir.display()
 
621
        from bzrlib.plugins.gtk.olive.mkdir import MkdirDialog
 
622
        mkdir = MkdirDialog(self.wt, self.wtpath, self.window)
 
623
        response = mkdir.run()
 
624
        mkdir.destroy()
 
625
        if response == gtk.RESPONSE_OK:
 
626
            self.refresh_right()
722
627
    
723
628
    def on_menuitem_file_move_activate(self, widget):
724
629
        """ File/Move... menu handler. """
725
 
        from move import OliveMove
726
 
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
727
 
        move.display()
 
630
        from bzrlib.plugins.gtk.olive.move import MoveDialog
 
631
        move = MoveDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
632
        response = move.run()
 
633
        move.destroy()
 
634
        if response == gtk.RESPONSE_OK:
 
635
            self.refresh_right()
728
636
    
729
637
    def on_menuitem_file_rename_activate(self, widget):
730
638
        """ File/Rename... menu handler. """
731
 
        from rename import OliveRename
732
 
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
733
 
        rename.display()
 
639
        from bzrlib.plugins.gtk.olive.rename import RenameDialog
 
640
        rename = RenameDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
 
641
        response = rename.run()
 
642
        rename.destroy()
 
643
        if response == gtk.RESPONSE_OK:
 
644
            self.refresh_right()
734
645
 
735
646
    def on_menuitem_remove_file_activate(self, widget):
736
647
        """ Remove (unversion) selected file. """
737
 
        from remove import OliveRemoveDialog
738
 
        remove = OliveRemoveDialog(self.wt, self.wtpath,
 
648
        from bzrlib.plugins.gtk.olive.remove import RemoveDialog
 
649
        remove = RemoveDialog(self.wt, self.wtpath,
739
650
                                   selected=self.get_selected_right(),
740
651
                                   parent=self.window)
741
652
        response = remove.run()
744
655
            remove.hide()
745
656
        
746
657
            if response == gtk.RESPONSE_OK:
747
 
                self.set_path(self.path)
748
658
                self.refresh_right()
749
659
            
750
660
            remove.destroy()
753
663
        """ Statistics/Differences... menu handler. """
754
664
        window = DiffWindow(parent=self.window)
755
665
        parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
756
 
        window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
 
666
        window.set_diff(self.wt.branch._get_nick(local=True), self.wt, 
 
667
                        parent_tree)
757
668
        window.show()
758
669
    
759
670
    def on_menuitem_stats_infos_activate(self, widget):
760
671
        """ Statistics/Informations... menu handler. """
761
 
        from info import OliveInfo
 
672
        from bzrlib.plugins.gtk.olive.info import InfoDialog
762
673
        if self.remote:
763
 
            info = OliveInfo(self.remote_branch)
 
674
            info = InfoDialog(self.remote_branch)
764
675
        else:
765
 
            info = OliveInfo(self.wt.branch)
 
676
            info = InfoDialog(self.wt.branch)
766
677
        info.display()
767
678
    
768
679
    def on_menuitem_stats_log_activate(self, widget):
773
684
        else:
774
685
            branch = self.remote_branch
775
686
 
776
 
        window = branchwin.BranchWindow(branch, branch.last_revision(), None, parent=self.window)
 
687
        window = branchwin.BranchWindow(branch, [branch.last_revision()], None, 
 
688
                                        parent=self.window)
777
689
        window.show()
778
690
    
779
691
    def on_menuitem_view_refresh_activate(self, widget):
786
698
    def on_menuitem_view_show_hidden_files_activate(self, widget):
787
699
        """ View/Show hidden files menu handler. """
788
700
        self.pref.set_preference('dotted_files', widget.get_active())
 
701
        self.pref.write()
789
702
        if self.path is not None:
790
703
            self.refresh_right()
791
704
 
792
705
    def on_menuitem_view_show_ignored_files_activate(self, widget):
793
706
        """ Hide/Show ignored files menu handler. """
794
707
        self.pref.set_preference('ignored_files', widget.get_active())
 
708
        self.pref.write()
795
709
        if self.path is not None:
796
710
            self.refresh_right()
797
711
            
798
712
    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()
 
713
        """ Occurs when somebody clicks in the bookmark list. """
 
714
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
 
715
        treeselection = widget.get_selection()
 
716
        if treepathpos is not None:
 
717
            treeselection.select_path(treepathpos[0])
 
718
            if event.button == 1:
 
719
                newdir = self.get_selected_left()
 
720
                if newdir == None:
 
721
                    return
 
722
 
 
723
                if self.set_path(newdir):
 
724
                    self.refresh_right()
 
725
            elif event.button == 3:
 
726
                # Don't show context with nothing selected
 
727
                if self.get_selected_left() == None:
 
728
                    return
 
729
 
 
730
                # Create a menu
 
731
                from menu import OliveMenu
 
732
                menu = OliveMenu(path=self.get_path(),
 
733
                                 selected=self.get_selected_left(),
 
734
                                 app=self)
 
735
                
 
736
                menu.left_context_menu().popup(None, None, None, 0,
 
737
                                               event.time)
 
738
        else:
 
739
            if treeselection is not None:
 
740
                treeselection.unselect_all()
827
741
 
828
742
    def on_treeview_left_row_activated(self, treeview, path, view_column):
829
743
        """ Occurs when somebody double-clicks or enters an item in the
837
751
            self.refresh_right()
838
752
 
839
753
    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:
 
754
        """ Occurs when somebody clicks in the file list. """
 
755
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
 
756
        if event.button == 1:
 
757
            if treepathpos is None and widget.get_selection is not None:
 
758
                treeselection = widget.get_selection()
 
759
                treeselection.unselect_all()
 
760
        elif event.button == 3:
 
761
            treeselection = widget.get_selection()
 
762
            if treepathpos is not None:
 
763
                treeselection.select_path(treepathpos[0])
 
764
            else:
 
765
                if treeselection is not None:
 
766
                    treeselection.unselect_all()
842
767
            # Create a menu
843
768
            from menu import OliveMenu
844
769
            menu = OliveMenu(path=self.get_path(),
848
773
            m_open = menu.ui.get_widget('/context_right/open')
849
774
            m_add = menu.ui.get_widget('/context_right/add')
850
775
            m_remove = menu.ui.get_widget('/context_right/remove')
 
776
            m_remove_and_delete = menu.ui.get_widget('/context_right/remove_and_delete')
851
777
            m_rename = menu.ui.get_widget('/context_right/rename')
852
778
            m_revert = menu.ui.get_widget('/context_right/revert')
853
779
            m_commit = menu.ui.get_widget('/context_right/commit')
861
787
                    m_open.set_sensitive(False)
862
788
                    m_add.set_sensitive(False)
863
789
                    m_remove.set_sensitive(False)
 
790
                    m_remove_and_delete.set_sensitive(False)
864
791
                    m_rename.set_sensitive(False)
865
792
                    m_revert.set_sensitive(False)
866
793
                    m_commit.set_sensitive(False)
867
794
                    m_annotate.set_sensitive(False)
868
795
                    m_diff.set_sensitive(False)
869
796
                else:
 
797
                    if treepathpos is None:
 
798
                        m_open.set_sensitive(False)
 
799
                        m_add.set_sensitive(False)
 
800
                        m_remove.set_sensitive(False)
 
801
                        m_remove_and_delete.set_sensitive(False)
 
802
                        m_rename.set_sensitive(False)
 
803
                        m_annotate.set_sensitive(False)
 
804
                        m_diff.set_sensitive(False)
 
805
                        m_revert.set_sensitive(False)
 
806
                    else:
 
807
                        m_open.set_sensitive(True)
 
808
                        m_add.set_sensitive(True)
 
809
                        m_remove.set_sensitive(True)
 
810
                        m_remove_and_delete.set_sensitive(True)
 
811
                        m_rename.set_sensitive(True)
 
812
                        m_annotate.set_sensitive(True)
 
813
                        m_diff.set_sensitive(True)
 
814
                        m_revert.set_sensitive(True)
 
815
                    m_commit.set_sensitive(True)
 
816
            except bzrerrors.NotBranchError:
 
817
                if treepathpos is None:
 
818
                    m_open.set_sensitive(False)
 
819
                else:
870
820
                    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
821
                m_add.set_sensitive(False)
881
822
                m_remove.set_sensitive(False)
 
823
                m_remove_and_delete.set_sensitive(False)
882
824
                m_rename.set_sensitive(False)
883
825
                m_revert.set_sensitive(False)
884
826
                m_commit.set_sensitive(False)
919
861
    
920
862
    def on_window_main_delete_event(self, widget, event=None):
921
863
        """ Do some stuff before exiting. """
922
 
        width, height = self.window_main.get_size()
 
864
        width, height = self.window.get_size()
923
865
        self.pref.set_preference('window_width', width)
924
866
        self.pref.set_preference('window_height', height)
925
 
        x, y = self.window_main.get_position()
 
867
        x, y = self.window.get_position()
926
868
        self.pref.set_preference('window_x', x)
927
869
        self.pref.set_preference('window_y', y)
928
870
        self.pref.set_preference('paned_position',
929
 
                                 self.hpaned_main.get_position())
 
871
                                 self.window.hpaned_main.get_position())
930
872
        
931
873
        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()
 
874
        self.window.destroy()
960
875
 
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
876
    def get_selected_fileid(self):
1127
877
        """ Get the file_id of the selected file. """
1128
 
        treeselection = self.treeview_right.get_selection()
 
878
        treeselection = self.window.treeview_right.get_selection()
1129
879
        (model, iter) = treeselection.get_selected()
1130
880
        
1131
881
        if iter is None:
1135
885
    
1136
886
    def get_selected_right(self):
1137
887
        """ Get the selected filename. """
1138
 
        treeselection = self.treeview_right.get_selection()
 
888
        treeselection = self.window.treeview_right.get_selection()
1139
889
        (model, iter) = treeselection.get_selected()
1140
890
        
1141
891
        if iter is None:
1145
895
    
1146
896
    def get_selected_left(self):
1147
897
        """ Get the selected bookmark. """
1148
 
        treeselection = self.treeview_left.get_selection()
 
898
        treeselection = self.window.treeview_left.get_selection()
1149
899
        (model, iter) = treeselection.get_selected()
1150
900
        
1151
901
        if iter is None:
1155
905
 
1156
906
    def set_statusbar(self, message):
1157
907
        """ Set the statusbar message. """
1158
 
        self.statusbar.push(self.context_id, message)
 
908
        self.window.statusbar.push(self.context_id, message)
1159
909
    
1160
910
    def clear_statusbar(self):
1161
911
        """ Clean the last message from the statusbar. """
1162
 
        self.statusbar.pop(self.context_id)
 
912
        self.window.statusbar.pop(self.context_id)
1163
913
    
1164
914
    def set_sensitivity(self):
1165
915
        """ Set menu and toolbar sensitivity. """
1166
916
        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)
 
917
            self.window.set_view_to_localbranch(self.notbranch)
1196
918
        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)
 
919
            self.window.set_view_to_remotebranch()
1226
920
    
1227
921
    def refresh_left(self):
1228
922
        """ Refresh the bookmark list. """
1229
923
        
1230
 
        # Get TreeStore and clear it
1231
 
        treestore = self.treeview_left.get_model()
1232
 
        treestore.clear()
 
924
        # Get ListStore and clear it
 
925
        liststore = self.window.bookmarklist
 
926
        liststore.clear()
1233
927
 
1234
928
        # Re-read preferences
1235
929
        self.pref.read()
1237
931
        # Get bookmarks
1238
932
        bookmarks = self.pref.get_bookmarks()
1239
933
 
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):
 
934
        # Get titles and sort by title
 
935
        bookmarks = [[self.pref.get_bookmark_title(item), item, gtk.STOCK_DIRECTORY] for item in bookmarks]
 
936
        bookmarks.sort()
 
937
        for title_item in bookmarks:
 
938
            liststore.append(title_item)
 
939
        
 
940
        # Add the ListStore to the TreeView and refresh column width
 
941
        self.window.treeview_left.set_model(liststore)
 
942
        self.window.treeview_left.columns_autosize()
 
943
 
 
944
    def refresh_right(self):
1253
945
        """ Refresh the file list. """
1254
946
        if not self.remote:
1255
947
            # We're local
1256
948
            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
 
    
 
949
            
 
950
            path = self.get_path()
 
951
            
1265
952
            # Get ListStore and clear it
1266
 
            liststore = self.treeview_right.get_model()
 
953
            liststore = self.window.filelist
1267
954
            liststore.clear()
1268
955
            
1269
 
            # Show Status column
1270
 
            self._tvcolumn_status.set_visible(True)
1271
 
    
1272
956
            dirs = []
1273
957
            files = []
1274
 
    
 
958
            
1275
959
            # Fill the appropriate lists
1276
960
            dotted_files = self.pref.get_preference('dotted_files', 'bool')
1277
961
            ignored_files = self.pref.get_preference('ignored_files', 'bool')
1278
 
 
 
962
            
1279
963
            for item in os.listdir(path):
1280
964
                if not dotted_files and item[0] == '.':
1281
965
                    continue
1282
 
                if os.path.isdir(path + os.sep + item):
 
966
                if os.path.isdir(os.path.join(path, item)):
1283
967
                    dirs.append(item)
1284
968
                else:
1285
969
                    files.append(item)
1286
970
            
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
 
                
 
971
            self.window.col_status.set_visible(False)
 
972
            if not self.notbranch:
 
973
                try:
 
974
                    tree1 = WorkingTree.open_containing(os.path.realpath(path))[0]
 
975
                    branch = tree1.branch
 
976
                    tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
 
977
                    
 
978
                    delta = tree1.changes_from(tree2, want_unchanged=True)
 
979
                    
 
980
                    # Show Status column
 
981
                    self.window.col_status.set_visible(True)
 
982
                except bzrerrors.LockContention:
 
983
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR, allowPopup=True)
 
984
                    self.window.location_status.connect_object('clicked', error_dialog, 
 
985
                                       *(_i18n('Branch is locked'),
 
986
                                                _i18n('The branch in the current folder is locked by another Bazaar program')))
 
987
                    self.notbranch = True
 
988
                    self.window.set_view_to_localbranch(False) 
 
989
            
1300
990
            # Add'em to the ListStore
1301
991
            for item in dirs:
1302
 
                try:
1303
 
                    statinfo = os.stat(self.path + os.sep + item)
1304
 
                except OSError, e:
1305
 
                    if e.errno == 40:
 
992
                status = ''
 
993
                st = ''
 
994
                fileid = ''
 
995
                if not self.notbranch:
 
996
                    filename = tree1.relpath(os.path.join(os.path.realpath(path), item))
 
997
                    
 
998
                    st, status = self.statusmapper(filename, delta)
 
999
                    if not ignored_files and status == 'ignored':
1306
1000
                        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
 
                                  ''])
 
1001
                
 
1002
                statinfo = os.lstat(os.path.join(self.path, item))
 
1003
                liststore.append([ gtk.STOCK_DIRECTORY,
 
1004
                                   True,
 
1005
                                   item,
 
1006
                                   st,
 
1007
                                   status,
 
1008
                                   "<DIR>",
 
1009
                                   "<DIR>",
 
1010
                                   statinfo.st_mtime,
 
1011
                                   self._format_date(statinfo.st_mtime),
 
1012
                                   ''])
1319
1013
            for item in files:
1320
 
                status = 'unknown'
 
1014
                status = ''
 
1015
                st = ''
1321
1016
                fileid = ''
1322
 
                if not notbranch:
1323
 
                    filename = tree1.relpath(path + os.sep + item)
 
1017
                if not self.notbranch:
 
1018
                    filename = tree1.relpath(os.path.join(os.path.realpath(path), item))
1324
1019
                    
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
 
1020
                    st, status = self.statusmapper(filename, delta)
 
1021
                    if not ignored_files and status == 'ignored':
 
1022
                        continue
 
1023
                
 
1024
                statinfo = os.lstat(os.path.join(self.path, item))
1378
1025
                liststore.append([gtk.STOCK_FILE,
1379
1026
                                  False,
1380
1027
                                  item,
1389
1036
            # We're remote
1390
1037
            
1391
1038
            # Get ListStore and clear it
1392
 
            liststore = self.treeview_right.get_model()
 
1039
            liststore = self.window.filelist
1393
1040
            liststore.clear()
1394
1041
            
1395
1042
            # Hide Status column
1396
 
            self._tvcolumn_status.set_visible(False)
 
1043
            self.window.col_status.set_visible(False)
1397
1044
            
1398
1045
            dirs = []
1399
1046
            files = []
1400
1047
            
1401
 
            self._show_stock_image(gtk.STOCK_REFRESH)
 
1048
            self.window.set_location_status(gtk.STOCK_REFRESH)
1402
1049
            
1403
1050
            for (name, type) in self.remote_entries:
1404
1051
                if type.kind == 'directory':
1463
1110
                while gtk.events_pending():
1464
1111
                    gtk.main_iteration()
1465
1112
            
1466
 
            self.image_location_error.destroy()
 
1113
            self.window.location_status.destroy()
1467
1114
 
1468
1115
        # Columns should auto-size
1469
 
        self.treeview_right.columns_autosize()
 
1116
        self.window.treeview_right.columns_autosize()
1470
1117
        
1471
1118
        # Set sensitivity
1472
1119
        self.set_sensitivity()
 
1120
    
 
1121
    def statusmapper(self, filename, delta):
 
1122
        status = 'unknown'
 
1123
        try:
 
1124
            self.wt.lock_read()
 
1125
            
 
1126
            for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
 
1127
                if rpathnew == filename:
 
1128
                    status = 'renamed'
 
1129
                    fileid = id
 
1130
            for rpath, id, kind in delta.added:
 
1131
                if rpath == filename:
 
1132
                    status = 'added'
 
1133
                    fileid = id
 
1134
            for rpath, id, kind in delta.removed:
 
1135
                if rpath == filename:
 
1136
                    status = 'removed'
 
1137
                    fileid = id
 
1138
            for rpath, id, kind, text_modified, meta_modified in delta.modified:
 
1139
                if rpath == filename:
 
1140
                    status = 'modified'
 
1141
                    fileid = id
 
1142
            for rpath, id, kind in delta.unchanged:
 
1143
                if rpath == filename:
 
1144
                    status = 'unchanged'
 
1145
                    fileid = id
 
1146
            for rpath, file_class, kind, id, entry in self.wt.list_files():
 
1147
                if rpath == filename and file_class == 'I':
 
1148
                    status = 'ignored'
 
1149
        finally:
 
1150
            self.wt.unlock()
 
1151
    
 
1152
        if status == 'renamed':
 
1153
            st = _i18n('renamed')
 
1154
        elif status == 'removed':
 
1155
            st = _i18n('removed')
 
1156
        elif status == 'added':
 
1157
            st = _i18n('added')
 
1158
        elif status == 'modified':
 
1159
            st = _i18n('modified')
 
1160
        elif status == 'unchanged':
 
1161
            st = _i18n('unchanged')
 
1162
        elif status == 'ignored':
 
1163
            st = _i18n('ignored')
 
1164
        else:
 
1165
            st = _i18n('unknown')
 
1166
        return st, status
1473
1167
 
1474
1168
    def _harddisks(self):
1475
1169
        """ Returns hard drive letters under Win32. """
1480
1174
            if sys.platform == 'win32':
1481
1175
                print "pyWin32 modules needed to run Olive on Win32."
1482
1176
                sys.exit(1)
1483
 
            else:
1484
 
                pass
1485
1177
        
1486
1178
        driveletters = []
1487
1179
        for drive in string.ascii_uppercase:
1488
 
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
 
1180
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED or\
 
1181
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOTE or\
 
1182
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOVABLE:
1489
1183
                driveletters.append(drive+':')
1490
1184
        return driveletters
1491
1185
    
1504
1198
        if active >= 0:
1505
1199
            drive = model[active][0]
1506
1200
            self.set_path(drive + '\\')
1507
 
            self.refresh_right(drive + '\\')
 
1201
            self.refresh_right()
1508
1202
    
1509
1203
    def check_for_changes(self):
1510
1204
        """ Check whether there were changes in the current working tree. """
1583
1277
                    return True
1584
1278
            # Either it's not a directory or not in the inventory
1585
1279
            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
1280
 
1600
1281
import ConfigParser
1601
1282
 
1724
1405
                return self._get_default(option)
1725
1406
            except KeyError:
1726
1407
                return None
1727