/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: Jelmer Vernooij
  • Date: 2008-06-29 18:12:29 UTC
  • mto: This revision was merged to the branch mainline in revision 519.
  • Revision ID: jelmer@samba.org-20080629181229-1l2m4cf7vvbyh8qg
Simplify progress bar code, use embedded progress bar inside viz window.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 #!/usr/bin/python
 
2
 
1
3
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
4
#
3
5
# This program is free software; you can redistribute it and/or modify
17
19
import os
18
20
import sys
19
21
import time
20
 
import errno
21
22
 
22
23
# gettext support
23
24
import gettext
32
33
import gobject
33
34
import gtk
34
35
import gtk.gdk
 
36
import gtk.glade
35
37
 
36
38
from bzrlib.branch import Branch
37
39
import bzrlib.errors as bzrerrors
42
44
from bzrlib.plugins.gtk import _i18n
43
45
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
44
46
from bzrlib.plugins.gtk.errors import show_bzr_error
45
 
from bzrlib.plugins.gtk.olive.window import OliveGui
 
47
from guifiles import GLADEFILENAME
46
48
 
47
49
from bzrlib.plugins.gtk.diff import DiffWindow
48
50
lazy_import(globals(), """
58
60
 
59
61
def about():
60
62
    """ Display the AboutDialog. """
61
 
    from bzrlib.plugins.gtk import __version__, icon_path
62
 
    
63
 
    dialog = gtk.AboutDialog()
64
 
    dialog.set_name("Olive")
 
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
65
71
    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")))
71
72
    dialog.set_authors([ _i18n("Lead Developer:"),
72
73
                         "Szilveszter Farkas <szilveszter.farkas@gmail.com>",
73
74
                         _i18n("Contributors:"),
81
82
    # Destroy the dialog
82
83
    dialog.destroy()
83
84
 
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.window = OliveGui(calling_app = self)
91
 
        
 
90
        self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
 
91
        self.window = self.toplevel.get_widget('window_main')
92
92
        self.pref = Preferences()
93
93
        self.path = None
94
94
 
95
95
        # Initialize the statusbar
96
 
        self.context_id = self.window.statusbar.get_context_id('olive')
 
96
        self.statusbar = self.toplevel.get_widget('statusbar')
 
97
        self.context_id = self.statusbar.get_context_id('olive')
97
98
        
 
99
        # Get the main window
 
100
        self.window_main = self.toplevel.get_widget('window_main')
 
101
        # Get the HPaned
 
102
        self.hpaned_main = self.toplevel.get_widget('hpaned_main')
 
103
        # Get the TreeViews
 
104
        self.treeview_left = self.toplevel.get_widget('treeview_left')
 
105
        self.treeview_right = self.toplevel.get_widget('treeview_right')
 
106
        # Get some important menu items
 
107
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
 
108
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
 
109
        self.menuitem_file_bookmark = self.toplevel.get_widget('menuitem_file_bookmark')
 
110
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
 
111
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
 
112
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
 
113
        self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
 
114
        self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
 
115
        self.menuitem_view_show_ignored_files = self.toplevel.get_widget('menuitem_view_show_ignored_files')
 
116
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
 
117
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
 
118
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
 
119
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
 
120
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
 
121
        self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
 
122
        self.menuitem_branch_update = self.toplevel.get_widget('menuitem_branch_update')
 
123
        self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
 
124
        self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
 
125
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
 
126
        self.menuitem_branch_tags = self.toplevel.get_widget('menuitem_branch_tags')
 
127
        self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
 
128
        self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
 
129
        self.menuitem_branch_conflicts = self.toplevel.get_widget('menuitem_branch_conflicts')
 
130
        self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
 
131
        self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
 
132
        self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
 
133
        # Get some toolbuttons
 
134
        #self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
 
135
        self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
 
136
        self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
 
137
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
 
138
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
 
139
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
 
140
        self.toolbutton_update = self.toplevel.get_widget('toolbutton_update')
98
141
        # Get the drive selector
99
142
        self.combobox_drive = gtk.combo_box_new_text()
100
143
        self.combobox_drive.connect("changed", self._refresh_drives)
101
144
        
102
145
        # Get the navigation widgets
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
 
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')
107
151
        
108
152
        # Get the History widgets
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
 
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)
112
213
        
113
214
        self._just_started = True
114
215
        
121
222
        self.window.move(x, y)
122
223
        # Apply paned position
123
224
        pos = self.pref.get_preference('paned_position', 'int')
124
 
        self.window.hpaned_main.set_position(pos)
 
225
        self.hpaned_main.set_position(pos)
 
226
        
 
227
        # Apply menu to the toolbutton
 
228
        #menubutton = self.toplevel.get_widget('menutoolbutton_diff')
 
229
        #menubutton.set_menu(handler.menu.toolbar_diff)
125
230
        
126
231
        # Now we can show the window
127
232
        self.window.show()
133
238
            self.combobox_drive.show()
134
239
            self.gen_hard_selector()
135
240
        
136
 
        self.refresh_left()
 
241
        self._load_left()
137
242
 
138
243
        # Apply menu state
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'))
 
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'))
141
246
 
142
247
        # We're starting local
143
248
        self.remote = False
146
251
        self.remote_revision = None
147
252
        
148
253
        self.set_path(os.getcwd())
149
 
        self.refresh_right()
 
254
        self._load_right()
150
255
        
151
256
        self._just_started = False
152
257
 
153
258
    def set_path(self, path, force_remote=False):
154
 
        self.window.location_status.destroy()
155
259
        self.notbranch = False
156
260
        
157
261
        if force_remote:
158
262
            # Forcing remote mode (reading data from inventory)
159
 
            self.window.set_location_status(gtk.STOCK_DISCONNECT)
 
263
            self._show_stock_image(gtk.STOCK_DISCONNECT)
160
264
            try:
161
265
                br = Branch.open_containing(path)[0]
162
266
            except bzrerrors.NotBranchError:
163
 
                self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
 
267
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
164
268
                self.check_history.set_active(False)
165
269
                self.check_history.set_sensitive(False)
166
270
                return False
167
271
            except bzrerrors.UnsupportedProtocol:
168
 
                self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
 
272
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
169
273
                self.check_history.set_active(False)
170
274
                self.check_history.set_sensitive(False)
171
275
                return False
172
276
            
173
 
            self.window.set_location_status(gtk.STOCK_CONNECT)
 
277
            self._show_stock_image(gtk.STOCK_CONNECT)
174
278
            
175
279
            self.remote = True
176
280
           
199
303
                self.button_location_up.set_sensitive(True)
200
304
        else:
201
305
            if os.path.isdir(path):
 
306
                self.image_location_error.destroy()
202
307
                self.remote = False
203
308
                
204
309
                # We're local
205
310
                try:
206
 
                    self.wt, self.wtpath = WorkingTree.open_containing(os.path.realpath(path))
 
311
                    self.wt, self.wtpath = WorkingTree.open_containing(path)
207
312
                except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
208
313
                    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
215
314
                
216
315
                # If we're in the root, we cannot go up anymore
217
316
                if sys.platform == 'win32':
228
327
            elif not os.path.isfile(path):
229
328
                # Doesn't seem to be a file nor a directory, trying to open a
230
329
                # remote location
231
 
                self.window.set_location_status(gtk.STOCK_DISCONNECT)
 
330
                self._show_stock_image(gtk.STOCK_DISCONNECT)
232
331
                try:
233
332
                    br = Branch.open_containing(path)[0]
234
333
                except bzrerrors.NotBranchError:
235
 
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
 
334
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
236
335
                    self.check_history.set_active(False)
237
336
                    self.check_history.set_sensitive(False)
238
337
                    return False
239
338
                except bzrerrors.UnsupportedProtocol:
240
 
                    self.window.set_location_status(gtk.STOCK_DIALOG_ERROR)
 
339
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
241
340
                    self.check_history.set_active(False)
242
341
                    self.check_history.set_sensitive(False)
243
342
                    return False
244
343
                
245
 
                self.window.set_location_status(gtk.STOCK_CONNECT)
 
344
                self._show_stock_image(gtk.STOCK_CONNECT)
246
345
                
247
346
                self.remote = True
248
347
               
276
375
        else:
277
376
            self.check_history.set_sensitive(True)
278
377
        
279
 
        self.window.statusbar.push(self.context_id, path)
 
378
        self.statusbar.push(self.context_id, path)
280
379
        self.entry_location.set_text(path)
281
380
        self.path = path
282
381
        return True
309
408
            if response == gtk.RESPONSE_OK:
310
409
                if revb.selected_revno is not None:
311
410
                    self.entry_history.set_text(revb.selected_revno)
312
 
                    self.on_entry_history_revno_activate()
313
411
            
314
412
            revb.destroy()
315
413
    
340
438
            # History Mode activated
341
439
            self.entry_history.set_sensitive(True)
342
440
            self.button_history.set_sensitive(True)
343
 
            if self.entry_history.get_text() != "":
344
 
                self.on_entry_history_revno_activate()
345
441
        else:
346
442
            # History Mode deactivated
347
443
            self.entry_history.set_sensitive(False)
348
444
            self.button_history.set_sensitive(False)
 
445
    
 
446
    @show_bzr_error
 
447
    def on_entry_history_revno_key_press_event(self, widget, event):
 
448
        """ Key pressed handler for the history entry. """
 
449
        if event.keyval == gtk.gdk.keyval_from_name('Return') or event.keyval == gtk.gdk.keyval_from_name('KP_Enter'):
 
450
            # Return was hit, so we have to load that specific revision
 
451
            # Emulate being remote, so inventory should be used
 
452
            path = self.get_path()
 
453
            if not self.remote:
 
454
                self.remote = True
 
455
                self.remote_branch = self.wt.branch
349
456
            
350
 
            # Return right window to normal view by acting like we jump to it
 
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
351
466
            self.on_button_location_jump_clicked(widget)
352
467
    
353
 
    @show_bzr_error
354
 
    def on_entry_history_revno_activate(self, widget=None):
355
 
        """ Key pressed handler for the history entry. """
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
 
 
366
468
    def on_menuitem_add_files_activate(self, widget):
367
469
        """ Add file(s)... menu handler. """
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
 
 
 
470
        from add import OliveAdd
 
471
        add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
 
472
        add.display()
 
473
    
375
474
    def on_menuitem_branch_get_activate(self, widget):
376
475
        """ Branch/Get... menu handler. """
377
476
        from bzrlib.plugins.gtk.branch import BranchDialog
409
508
    @show_bzr_error
410
509
    def on_menuitem_branch_commit_activate(self, widget):
411
510
        """ Branch/Commit... menu handler. """
 
511
#     def __init__(self, wt, wtpath, notbranch, selected=None, parent=None):
412
512
        selected = self.get_selected_right()
413
513
        if selected:
414
514
            selected = os.path.join(self.wtpath, selected)
441
541
                         _i18n('Please commit or revert the changes before merging.'))
442
542
        else:
443
543
            parent_branch_path = self.wt.branch.get_parent()
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()
 
544
            merge = MergeDialog(self.wt, self.wtpath,default_branch_path=parent_branch_path )
 
545
            merge.display()
449
546
 
450
547
    @show_bzr_error
451
548
    def on_menuitem_branch_missing_revisions_activate(self, widget):
528
625
        
529
626
    @show_bzr_error
530
627
    def on_menuitem_branch_update_activate(self, widget):
531
 
        """ Branch/checkout update menu handler. """
 
628
        """ Brranch/checkout update menu handler. """
532
629
        
533
630
        ret = self.wt.update()
534
631
        conflicts = self.wt.conflicts()
536
633
            info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
537
634
        else:
538
635
            info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
539
 
        self.refresh_right()
540
636
    
541
637
    def on_menuitem_branch_push_activate(self, widget):
542
638
        """ Branch/Push... menu handler. """
548
644
    @show_bzr_error
549
645
    def on_menuitem_branch_revert_activate(self, widget):
550
646
        """ Branch/Revert all changes menu handler. """
551
 
        ret = self.wt.revert(None)
 
647
        ret = self.wt.revert([])
552
648
        if ret:
553
649
            warning_dialog(_i18n('Conflicts detected'),
554
650
                           _i18n('Please have a look at the working tree before continuing.'))
559
655
    
560
656
    def on_menuitem_branch_status_activate(self, widget):
561
657
        """ Branch/Status... menu handler. """
562
 
        from bzrlib.plugins.gtk.status import StatusWindow
563
 
        status = StatusWindow(self.wt, self.wtpath)
564
 
        status.show()
 
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()
565
663
    
566
664
    def on_menuitem_branch_initialize_activate(self, widget):
567
665
        """ Initialize current directory. """
618
716
    
619
717
    def on_menuitem_file_make_directory_activate(self, widget):
620
718
        """ File/Make directory... menu handler. """
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()
 
719
        from mkdir import OliveMkdir
 
720
        mkdir = OliveMkdir(self.wt, self.wtpath)
 
721
        mkdir.display()
627
722
    
628
723
    def on_menuitem_file_move_activate(self, widget):
629
724
        """ File/Move... menu handler. """
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()
 
725
        from move import OliveMove
 
726
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
 
727
        move.display()
636
728
    
637
729
    def on_menuitem_file_rename_activate(self, widget):
638
730
        """ File/Rename... menu handler. """
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()
 
731
        from rename import OliveRename
 
732
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
 
733
        rename.display()
645
734
 
646
735
    def on_menuitem_remove_file_activate(self, widget):
647
736
        """ Remove (unversion) selected file. """
648
 
        from bzrlib.plugins.gtk.olive.remove import RemoveDialog
649
 
        remove = RemoveDialog(self.wt, self.wtpath,
 
737
        from remove import OliveRemoveDialog
 
738
        remove = OliveRemoveDialog(self.wt, self.wtpath,
650
739
                                   selected=self.get_selected_right(),
651
740
                                   parent=self.window)
652
741
        response = remove.run()
655
744
            remove.hide()
656
745
        
657
746
            if response == gtk.RESPONSE_OK:
 
747
                self.set_path(self.path)
658
748
                self.refresh_right()
659
749
            
660
750
            remove.destroy()
663
753
        """ Statistics/Differences... menu handler. """
664
754
        window = DiffWindow(parent=self.window)
665
755
        parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
666
 
        window.set_diff(self.wt.branch._get_nick(local=True), self.wt, 
667
 
                        parent_tree)
 
756
        window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
668
757
        window.show()
669
758
    
670
759
    def on_menuitem_stats_infos_activate(self, widget):
671
760
        """ Statistics/Informations... menu handler. """
672
 
        from bzrlib.plugins.gtk.olive.info import InfoDialog
 
761
        from info import OliveInfo
673
762
        if self.remote:
674
 
            info = InfoDialog(self.remote_branch)
 
763
            info = OliveInfo(self.remote_branch)
675
764
        else:
676
 
            info = InfoDialog(self.wt.branch)
 
765
            info = OliveInfo(self.wt.branch)
677
766
        info.display()
678
767
    
679
768
    def on_menuitem_stats_log_activate(self, widget):
684
773
        else:
685
774
            branch = self.remote_branch
686
775
 
687
 
        window = branchwin.BranchWindow(branch, [branch.last_revision()], None, 
688
 
                                        parent=self.window)
 
776
        window = branchwin.BranchWindow(branch, branch.last_revision(), None, parent=self.window)
689
777
        window.show()
690
778
    
691
779
    def on_menuitem_view_refresh_activate(self, widget):
698
786
    def on_menuitem_view_show_hidden_files_activate(self, widget):
699
787
        """ View/Show hidden files menu handler. """
700
788
        self.pref.set_preference('dotted_files', widget.get_active())
701
 
        self.pref.write()
702
789
        if self.path is not None:
703
790
            self.refresh_right()
704
791
 
705
792
    def on_menuitem_view_show_ignored_files_activate(self, widget):
706
793
        """ Hide/Show ignored files menu handler. """
707
794
        self.pref.set_preference('ignored_files', widget.get_active())
708
 
        self.pref.write()
709
795
        if self.path is not None:
710
796
            self.refresh_right()
711
797
            
712
798
    def on_treeview_left_button_press_event(self, widget, event):
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()
 
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()
741
827
 
742
828
    def on_treeview_left_row_activated(self, treeview, path, view_column):
743
829
        """ Occurs when somebody double-clicks or enters an item in the
751
837
            self.refresh_right()
752
838
 
753
839
    def on_treeview_right_button_press_event(self, widget, event):
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()
 
840
        """ Occurs when somebody right-clicks in the file list. """
 
841
        if event.button == 3:
767
842
            # Create a menu
768
843
            from menu import OliveMenu
769
844
            menu = OliveMenu(path=self.get_path(),
773
848
            m_open = menu.ui.get_widget('/context_right/open')
774
849
            m_add = menu.ui.get_widget('/context_right/add')
775
850
            m_remove = menu.ui.get_widget('/context_right/remove')
776
 
            m_remove_and_delete = menu.ui.get_widget('/context_right/remove_and_delete')
777
851
            m_rename = menu.ui.get_widget('/context_right/rename')
778
852
            m_revert = menu.ui.get_widget('/context_right/revert')
779
853
            m_commit = menu.ui.get_widget('/context_right/commit')
787
861
                    m_open.set_sensitive(False)
788
862
                    m_add.set_sensitive(False)
789
863
                    m_remove.set_sensitive(False)
790
 
                    m_remove_and_delete.set_sensitive(False)
791
864
                    m_rename.set_sensitive(False)
792
865
                    m_revert.set_sensitive(False)
793
866
                    m_commit.set_sensitive(False)
794
867
                    m_annotate.set_sensitive(False)
795
868
                    m_diff.set_sensitive(False)
796
869
                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)
 
870
                    m_open.set_sensitive(True)
 
871
                    m_add.set_sensitive(True)
 
872
                    m_remove.set_sensitive(True)
 
873
                    m_rename.set_sensitive(True)
 
874
                    m_revert.set_sensitive(True)
815
875
                    m_commit.set_sensitive(True)
 
876
                    m_annotate.set_sensitive(True)
 
877
                    m_diff.set_sensitive(True)
816
878
            except bzrerrors.NotBranchError:
817
 
                if treepathpos is None:
818
 
                    m_open.set_sensitive(False)
819
 
                else:
820
 
                    m_open.set_sensitive(True)
 
879
                m_open.set_sensitive(True)
821
880
                m_add.set_sensitive(False)
822
881
                m_remove.set_sensitive(False)
823
 
                m_remove_and_delete.set_sensitive(False)
824
882
                m_rename.set_sensitive(False)
825
883
                m_revert.set_sensitive(False)
826
884
                m_commit.set_sensitive(False)
861
919
    
862
920
    def on_window_main_delete_event(self, widget, event=None):
863
921
        """ Do some stuff before exiting. """
864
 
        width, height = self.window.get_size()
 
922
        width, height = self.window_main.get_size()
865
923
        self.pref.set_preference('window_width', width)
866
924
        self.pref.set_preference('window_height', height)
867
 
        x, y = self.window.get_position()
 
925
        x, y = self.window_main.get_position()
868
926
        self.pref.set_preference('window_x', x)
869
927
        self.pref.set_preference('window_y', y)
870
928
        self.pref.set_preference('paned_position',
871
 
                                 self.window.hpaned_main.get_position())
 
929
                                 self.hpaned_main.get_position())
872
930
        
873
931
        self.pref.write()
874
 
        self.window.destroy()
 
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
960
 
 
961
    def _load_right(self):
 
962
        """ Load data into the right panel. (Filelist) """
 
963
        # Create ListStore
 
964
        # Model: [ icon, dir, name, status text, status, size (int), size (human), mtime (int), mtime (local), fileid ]
 
965
        liststore = gtk.ListStore(gobject.TYPE_STRING,
 
966
                                  gobject.TYPE_BOOLEAN,
 
967
                                  gobject.TYPE_STRING,
 
968
                                  gobject.TYPE_STRING,
 
969
                                  gobject.TYPE_STRING,
 
970
                                  gobject.TYPE_STRING,
 
971
                                  gobject.TYPE_STRING,
 
972
                                  gobject.TYPE_INT,
 
973
                                  gobject.TYPE_STRING,
 
974
                                  gobject.TYPE_STRING)
 
975
        
 
976
        dirs = []
 
977
        files = []
 
978
        
 
979
        # Fill the appropriate lists
 
980
        dotted_files = self.pref.get_preference('dotted_files', 'bool')
 
981
        for item in os.listdir(self.path):
 
982
            if not dotted_files and item[0] == '.':
 
983
                continue
 
984
            if os.path.isdir(self.path + os.sep + item):
 
985
                dirs.append(item)
 
986
            else:
 
987
                files.append(item)
 
988
        
 
989
        if not self.notbranch:
 
990
            branch = self.wt.branch
 
991
            tree2 = self.wt.branch.repository.revision_tree(branch.last_revision())
 
992
        
 
993
            delta = self.wt.changes_from(tree2, want_unchanged=True)
 
994
        
 
995
        # Add'em to the ListStore
 
996
        for item in dirs:
 
997
            try:
 
998
                statinfo = os.stat(self.path + os.sep + item)
 
999
            except OSError, e:
 
1000
                if e.errno == 40:
 
1001
                    continue
 
1002
                else:
 
1003
                    raise
 
1004
            liststore.append([ gtk.STOCK_DIRECTORY,
 
1005
                               True,
 
1006
                               item,
 
1007
                               '',
 
1008
                               '',
 
1009
                               "<DIR>",
 
1010
                               "<DIR>",
 
1011
                               statinfo.st_mtime,
 
1012
                               self._format_date(statinfo.st_mtime),
 
1013
                               ''])
 
1014
        for item in files:
 
1015
            status = 'unknown'
 
1016
            fileid = ''
 
1017
            if not self.notbranch:
 
1018
                filename = self.wt.relpath(self.path + os.sep + item)
 
1019
                
 
1020
                try:
 
1021
                    self.wt.lock_read()
 
1022
                    
 
1023
                    for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
 
1024
                        if rpathnew == filename:
 
1025
                            status = 'renamed'
 
1026
                            fileid = id
 
1027
                    for rpath, id, kind in delta.added:
 
1028
                        if rpath == filename:
 
1029
                            status = 'added'
 
1030
                            fileid = id
 
1031
                    for rpath, id, kind in delta.removed:
 
1032
                        if rpath == filename:
 
1033
                            status = 'removed'
 
1034
                            fileid = id
 
1035
                    for rpath, id, kind, text_modified, meta_modified in delta.modified:
 
1036
                        if rpath == filename:
 
1037
                            status = 'modified'
 
1038
                            fileid = id
 
1039
                    for rpath, id, kind in delta.unchanged:
 
1040
                        if rpath == filename:
 
1041
                            status = 'unchanged'
 
1042
                            fileid = id
 
1043
                    for rpath, file_class, kind, id, entry in self.wt.list_files():
 
1044
                        if rpath == filename and file_class == 'I':
 
1045
                            status = 'ignored'
 
1046
                finally:
 
1047
                    self.wt.unlock()
 
1048
            
 
1049
            if status == 'renamed':
 
1050
                st = _i18n('renamed')
 
1051
            elif status == 'removed':
 
1052
                st = _i18n('removed')
 
1053
            elif status == 'added':
 
1054
                st = _i18n('added')
 
1055
            elif status == 'modified':
 
1056
                st = _i18n('modified')
 
1057
            elif status == 'unchanged':
 
1058
                st = _i18n('unchanged')
 
1059
            elif status == 'ignored':
 
1060
                st = _i18n('ignored')
 
1061
            else:
 
1062
                st = _i18n('unknown')
 
1063
            
 
1064
            try:
 
1065
                statinfo = os.stat(self.path + os.sep + item)
 
1066
            except OSError, e:
 
1067
                if e.errno == 40:
 
1068
                    continue
 
1069
                else:
 
1070
                    raise
 
1071
            liststore.append([gtk.STOCK_FILE,
 
1072
                              False,
 
1073
                              item,
 
1074
                              st,
 
1075
                              status,
 
1076
                              str(statinfo.st_size), # NOTE: if int used there it will fail for large files (size expressed as long int)
 
1077
                              self._format_size(statinfo.st_size),
 
1078
                              statinfo.st_mtime,
 
1079
                              self._format_date(statinfo.st_mtime),
 
1080
                              fileid])
 
1081
        
 
1082
        # Create the columns and add them to the TreeView
 
1083
        self.treeview_right.set_model(liststore)
 
1084
        self._tvcolumn_filename = gtk.TreeViewColumn(_i18n('Filename'))
 
1085
        self._tvcolumn_status = gtk.TreeViewColumn(_i18n('Status'))
 
1086
        self._tvcolumn_size = gtk.TreeViewColumn(_i18n('Size'))
 
1087
        self._tvcolumn_mtime = gtk.TreeViewColumn(_i18n('Last modified'))
 
1088
        self.treeview_right.append_column(self._tvcolumn_filename)
 
1089
        self.treeview_right.append_column(self._tvcolumn_status)
 
1090
        self.treeview_right.append_column(self._tvcolumn_size)
 
1091
        self.treeview_right.append_column(self._tvcolumn_mtime)
 
1092
        
 
1093
        # Set up the cells
 
1094
        cellpb = gtk.CellRendererPixbuf()
 
1095
        cell = gtk.CellRendererText()
 
1096
        self._tvcolumn_filename.pack_start(cellpb, False)
 
1097
        self._tvcolumn_filename.pack_start(cell, True)
 
1098
        self._tvcolumn_filename.set_attributes(cellpb, stock_id=0)
 
1099
        self._tvcolumn_filename.add_attribute(cell, 'text', 2)
 
1100
        self._tvcolumn_status.pack_start(cell, True)
 
1101
        self._tvcolumn_status.add_attribute(cell, 'text', 3)
 
1102
        self._tvcolumn_size.pack_start(cell, True)
 
1103
        self._tvcolumn_size.add_attribute(cell, 'text', 6)
 
1104
        self._tvcolumn_mtime.pack_start(cell, True)
 
1105
        self._tvcolumn_mtime.add_attribute(cell, 'text', 8)
 
1106
        
 
1107
        # Set up the properties of the TreeView
 
1108
        self.treeview_right.set_headers_visible(True)
 
1109
        self.treeview_right.set_headers_clickable(True)
 
1110
        self.treeview_right.set_search_column(1)
 
1111
        self._tvcolumn_filename.set_resizable(True)
 
1112
        self._tvcolumn_status.set_resizable(True)
 
1113
        self._tvcolumn_size.set_resizable(True)
 
1114
        self._tvcolumn_mtime.set_resizable(True)
 
1115
        # Set up sorting
 
1116
        liststore.set_sort_func(13, self._sort_filelist_callback, None)
 
1117
        liststore.set_sort_column_id(13, gtk.SORT_ASCENDING)
 
1118
        self._tvcolumn_filename.set_sort_column_id(13)
 
1119
        self._tvcolumn_status.set_sort_column_id(3)
 
1120
        self._tvcolumn_size.set_sort_column_id(5)
 
1121
        self._tvcolumn_mtime.set_sort_column_id(7)
 
1122
        
 
1123
        # Set sensitivity
 
1124
        self.set_sensitivity()
 
1125
        
876
1126
    def get_selected_fileid(self):
877
1127
        """ Get the file_id of the selected file. """
878
 
        treeselection = self.window.treeview_right.get_selection()
 
1128
        treeselection = self.treeview_right.get_selection()
879
1129
        (model, iter) = treeselection.get_selected()
880
1130
        
881
1131
        if iter is None:
885
1135
    
886
1136
    def get_selected_right(self):
887
1137
        """ Get the selected filename. """
888
 
        treeselection = self.window.treeview_right.get_selection()
 
1138
        treeselection = self.treeview_right.get_selection()
889
1139
        (model, iter) = treeselection.get_selected()
890
1140
        
891
1141
        if iter is None:
895
1145
    
896
1146
    def get_selected_left(self):
897
1147
        """ Get the selected bookmark. """
898
 
        treeselection = self.window.treeview_left.get_selection()
 
1148
        treeselection = self.treeview_left.get_selection()
899
1149
        (model, iter) = treeselection.get_selected()
900
1150
        
901
1151
        if iter is None:
905
1155
 
906
1156
    def set_statusbar(self, message):
907
1157
        """ Set the statusbar message. """
908
 
        self.window.statusbar.push(self.context_id, message)
 
1158
        self.statusbar.push(self.context_id, message)
909
1159
    
910
1160
    def clear_statusbar(self):
911
1161
        """ Clean the last message from the statusbar. """
912
 
        self.window.statusbar.pop(self.context_id)
 
1162
        self.statusbar.pop(self.context_id)
913
1163
    
914
1164
    def set_sensitivity(self):
915
1165
        """ Set menu and toolbar sensitivity. """
916
1166
        if not self.remote:
917
 
            self.window.set_view_to_localbranch(self.notbranch)
 
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
1196
        else:
919
 
            self.window.set_view_to_remotebranch()
 
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
1226
    
921
1227
    def refresh_left(self):
922
1228
        """ Refresh the bookmark list. """
923
1229
        
924
 
        # Get ListStore and clear it
925
 
        liststore = self.window.bookmarklist
926
 
        liststore.clear()
 
1230
        # Get TreeStore and clear it
 
1231
        treestore = self.treeview_left.get_model()
 
1232
        treestore.clear()
927
1233
 
928
1234
        # Re-read preferences
929
1235
        self.pref.read()
931
1237
        # Get bookmarks
932
1238
        bookmarks = self.pref.get_bookmarks()
933
1239
 
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):
 
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):
945
1253
        """ Refresh the file list. """
946
1254
        if not self.remote:
947
1255
            # We're local
948
1256
            from bzrlib.workingtree import WorkingTree
949
 
            
950
 
            path = self.get_path()
951
 
            
 
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
    
952
1265
            # Get ListStore and clear it
953
 
            liststore = self.window.filelist
 
1266
            liststore = self.treeview_right.get_model()
954
1267
            liststore.clear()
955
1268
            
 
1269
            # Show Status column
 
1270
            self._tvcolumn_status.set_visible(True)
 
1271
    
956
1272
            dirs = []
957
1273
            files = []
958
 
            
 
1274
    
959
1275
            # Fill the appropriate lists
960
1276
            dotted_files = self.pref.get_preference('dotted_files', 'bool')
961
1277
            ignored_files = self.pref.get_preference('ignored_files', 'bool')
962
 
            
 
1278
 
963
1279
            for item in os.listdir(path):
964
1280
                if not dotted_files and item[0] == '.':
965
1281
                    continue
966
 
                if os.path.isdir(os.path.join(path, item)):
 
1282
                if os.path.isdir(path + os.sep + item):
967
1283
                    dirs.append(item)
968
1284
                else:
969
1285
                    files.append(item)
970
1286
            
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
 
            
 
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
                
990
1300
            # Add'em to the ListStore
991
1301
            for item in dirs:
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':
 
1302
                try:
 
1303
                    statinfo = os.stat(self.path + os.sep + item)
 
1304
                except OSError, e:
 
1305
                    if e.errno == 40:
1000
1306
                        continue
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
 
                                   ''])
 
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
                                  ''])
1013
1319
            for item in files:
1014
 
                status = ''
1015
 
                st = ''
 
1320
                status = 'unknown'
1016
1321
                fileid = ''
1017
 
                if not self.notbranch:
1018
 
                    filename = tree1.relpath(os.path.join(os.path.realpath(path), item))
 
1322
                if not notbranch:
 
1323
                    filename = tree1.relpath(path + os.sep + item)
1019
1324
                    
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))
 
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
1025
1378
                liststore.append([gtk.STOCK_FILE,
1026
1379
                                  False,
1027
1380
                                  item,
1036
1389
            # We're remote
1037
1390
            
1038
1391
            # Get ListStore and clear it
1039
 
            liststore = self.window.filelist
 
1392
            liststore = self.treeview_right.get_model()
1040
1393
            liststore.clear()
1041
1394
            
1042
1395
            # Hide Status column
1043
 
            self.window.col_status.set_visible(False)
 
1396
            self._tvcolumn_status.set_visible(False)
1044
1397
            
1045
1398
            dirs = []
1046
1399
            files = []
1047
1400
            
1048
 
            self.window.set_location_status(gtk.STOCK_REFRESH)
 
1401
            self._show_stock_image(gtk.STOCK_REFRESH)
1049
1402
            
1050
1403
            for (name, type) in self.remote_entries:
1051
1404
                if type.kind == 'directory':
1110
1463
                while gtk.events_pending():
1111
1464
                    gtk.main_iteration()
1112
1465
            
1113
 
            self.window.location_status.destroy()
 
1466
            self.image_location_error.destroy()
1114
1467
 
1115
1468
        # Columns should auto-size
1116
 
        self.window.treeview_right.columns_autosize()
 
1469
        self.treeview_right.columns_autosize()
1117
1470
        
1118
1471
        # Set sensitivity
1119
1472
        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
1167
1473
 
1168
1474
    def _harddisks(self):
1169
1475
        """ Returns hard drive letters under Win32. """
1174
1480
            if sys.platform == 'win32':
1175
1481
                print "pyWin32 modules needed to run Olive on Win32."
1176
1482
                sys.exit(1)
 
1483
            else:
 
1484
                pass
1177
1485
        
1178
1486
        driveletters = []
1179
1487
        for drive in string.ascii_uppercase:
1180
 
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED or\
1181
 
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOTE or\
1182
 
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOVABLE:
 
1488
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
1183
1489
                driveletters.append(drive+':')
1184
1490
        return driveletters
1185
1491
    
1198
1504
        if active >= 0:
1199
1505
            drive = model[active][0]
1200
1506
            self.set_path(drive + '\\')
1201
 
            self.refresh_right()
 
1507
            self.refresh_right(drive + '\\')
1202
1508
    
1203
1509
    def check_for_changes(self):
1204
1510
        """ Check whether there were changes in the current working tree. """
1277
1583
                    return True
1278
1584
            # Either it's not a directory or not in the inventory
1279
1585
            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()
1280
1599
 
1281
1600
import ConfigParser
1282
1601
 
1405
1724
                return self._get_default(option)
1406
1725
            except KeyError:
1407
1726
                return None
 
1727