/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: 2007-02-03 10:51:01 UTC
  • Revision ID: jelmer@samba.org-20070203105101-kizl0u7o4xc7phgy
Fix some strings, import.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
import os
18
18
import sys
19
 
import time
20
 
import errno
21
19
 
22
20
# gettext support
23
21
import gettext
29
27
except:
30
28
    pass
31
29
 
32
 
import gobject
33
30
import gtk
34
31
import gtk.gdk
 
32
import gtk.glade
35
33
 
36
34
from bzrlib.branch import Branch
37
35
import bzrlib.errors as bzrerrors
38
 
from bzrlib.lazy_import import lazy_import
39
 
from bzrlib.ui import ui_factory
40
36
from bzrlib.workingtree import WorkingTree
41
37
 
42
 
from bzrlib.plugins.gtk import _i18n
43
 
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
44
 
from bzrlib.plugins.gtk.errors import show_bzr_error
45
 
from bzrlib.plugins.gtk.olive.window import OliveGui
46
 
 
47
 
from bzrlib.plugins.gtk.diff import DiffWindow
48
 
lazy_import(globals(), """
49
 
from bzrlib.plugins.gtk.viz import branchwin
50
 
""")
51
 
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
52
 
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
53
 
from bzrlib.plugins.gtk.commit import CommitDialog
54
 
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
55
 
from bzrlib.plugins.gtk.initialize import InitDialog
56
 
from bzrlib.plugins.gtk.push import PushDialog
57
 
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
58
 
 
59
 
def about():
60
 
    """ Display the AboutDialog. """
61
 
    from bzrlib.plugins.gtk import __version__, icon_path
62
 
    
63
 
    iconpath = icon_path() + os.sep
64
 
    
65
 
    dialog = gtk.AboutDialog()
66
 
    dialog.set_name("Olive")
67
 
    dialog.set_version(__version__)
68
 
    dialog.set_copyright("Copyright (C) 2006 Szilveszter Farkas (Phanatic)")
69
 
    dialog.set_website("https://launchpad.net/products/olive")
70
 
    dialog.set_website_label("https://launchpad.net/products/olive")
71
 
    dialog.set_icon_from_file(iconpath+"oliveicon2.png")
72
 
    dialog.set_logo(gtk.gdk.pixbuf_new_from_file(iconpath+"oliveicon2.png"))
73
 
    dialog.set_authors([ _i18n("Lead Developer:"),
74
 
                         "Szilveszter Farkas <szilveszter.farkas@gmail.com>",
75
 
                         _i18n("Contributors:"),
76
 
                         "Jelmer Vernooij <jelmer@samba.org>",
77
 
                         "Mateusz Korniak <mateusz.korniak@ant.gliwice.pl>",
78
 
                         "Gary van der Merwe <garyvdm@gmail.com>" ])
79
 
    dialog.set_artists([ "Simon Pascal Klein <klepas@klepas.org>",
80
 
                         "Jakub Steiner <jimmac@novell.com>" ])
81
 
 
82
 
    dialog.run()
83
 
    # Destroy the dialog
84
 
    dialog.destroy()
 
38
from dialog import error_dialog, info_dialog, warning_dialog
 
39
from errors import show_bzr_error
 
40
from guifiles import GLADEFILENAME
 
41
 
 
42
# import this classes only once
 
43
try:
 
44
    from bzrlib.plugins.gtk.viz.diffwin import DiffWindow
 
45
    from bzrlib.plugins.gtk.viz.branchwin import BranchWindow
 
46
    from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
 
47
    from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
 
48
    from bzrlib.plugins.gtk.commit import CommitDialog
 
49
    from bzrlib.plugins.gtk.push import PushDialog
 
50
except ImportError:
 
51
    # olive+bzr-gtk not installed. try to import from sources
 
52
    path = os.path.dirname(os.path.dirname(__file__))
 
53
    if path not in sys.path:
 
54
        sys.path.append(path)
 
55
    from viz.diffwin import DiffWindow
 
56
    from viz.branchwin import BranchWindow
 
57
    from annotate.gannotate import GAnnotateWindow
 
58
    from annotate.config import GAnnotateConfig
 
59
 
 
60
# History delimiter used in config files
 
61
delimiter = ' '
85
62
 
86
63
class OliveGtk:
87
64
    """ The main Olive GTK frontend class. This is called when launching the
88
65
    program. """
89
66
    
90
67
    def __init__(self):
91
 
        self.window = OliveGui(calling_app = self)
 
68
        self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
 
69
        
 
70
        self.window = self.toplevel.get_widget('window_main')
92
71
        
93
72
        self.pref = Preferences()
 
73
        
94
74
        self.path = None
95
75
 
96
76
        # Initialize the statusbar
97
 
        self.context_id = self.window.statusbar.get_context_id('olive')
98
 
        
99
 
                # Get the TreeViews
100
 
        self.treeview_left = self.window.treeview_left
101
 
        self.treeview_right = self.window.treeview_right
102
 
        
 
77
        self.statusbar = self.toplevel.get_widget('statusbar')
 
78
        self.context_id = self.statusbar.get_context_id('olive')
 
79
        
 
80
        # Get the main window
 
81
        self.window_main = self.toplevel.get_widget('window_main')
 
82
        # Get the HPaned
 
83
        self.hpaned_main = self.toplevel.get_widget('hpaned_main')
 
84
        # Get the TreeViews
 
85
        self.treeview_left = self.toplevel.get_widget('treeview_left')
 
86
        self.treeview_right = self.toplevel.get_widget('treeview_right')
 
87
        # Get some important menu items
 
88
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
 
89
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
 
90
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
 
91
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
 
92
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
 
93
        self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
 
94
        self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
 
95
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
 
96
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
 
97
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
 
98
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
 
99
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
 
100
        self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
 
101
        self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
 
102
        self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
 
103
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
 
104
        self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
 
105
        self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
 
106
        self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
 
107
        self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
 
108
        self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
 
109
        # Get some toolbuttons
 
110
        #self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
 
111
        self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
 
112
        self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
 
113
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
 
114
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
 
115
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
103
116
        # Get the drive selector
104
117
        self.combobox_drive = gtk.combo_box_new_text()
105
118
        self.combobox_drive.connect("changed", self._refresh_drives)
106
119
        
107
 
        # Get the navigation widgets
108
 
        self.hbox_location = self.window.locationbar
109
 
        self.button_location_up = self.window.button_location_up
110
 
        self.button_location_jump = self.window.button_location_jump
111
 
        self.entry_location = self.window.entry_location
112
 
        self.image_location_error = self.window.image_location_error
113
 
        
114
 
        # Get the History widgets
115
 
        self.check_history = self.window.checkbutton_history
116
 
        self.entry_history = self.window.entry_history_revno
117
 
        self.button_history = self.window.button_history_browse
 
120
        self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
 
121
 
 
122
        
 
123
        # Dictionary for signal_autoconnect
 
124
        dic = { "on_window_main_destroy": gtk.main_quit,
 
125
                "on_window_main_delete_event": self.on_window_main_delete_event,
 
126
                "on_quit_activate": self.on_window_main_delete_event,
 
127
                "on_about_activate": self.on_about_activate,
 
128
                "on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
 
129
                "on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
 
130
                "on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
 
131
                "on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
 
132
                "on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
 
133
                "on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
 
134
                "on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
 
135
                "on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
 
136
                "on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
 
137
                "on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
 
138
                "on_menuitem_branch_checkout_activate": self.on_menuitem_branch_checkout_activate,
 
139
                "on_menuitem_branch_revert_activate": self.on_menuitem_branch_revert_activate,
 
140
                "on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
 
141
                "on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
 
142
                "on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
 
143
                "on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
 
144
                "on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
 
145
                "on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
 
146
                "on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
 
147
                "on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
 
148
                "on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
 
149
                "on_toolbutton_refresh_clicked": self.on_menuitem_view_refresh_activate,
 
150
                "on_toolbutton_log_clicked": self.on_menuitem_stats_log_activate,
 
151
                #"on_menutoolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
 
152
                "on_toolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
 
153
                "on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
 
154
                "on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
 
155
                "on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
 
156
                "on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
 
157
                "on_treeview_right_row_activated": self.on_treeview_right_row_activated,
 
158
                "on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
 
159
                "on_treeview_left_row_activated": self.on_treeview_left_row_activated }
 
160
        
 
161
        # Connect the signals to the handlers
 
162
        self.toplevel.signal_autoconnect(dic)
118
163
        
119
164
        self._just_started = True
120
165
        
127
172
        self.window.move(x, y)
128
173
        # Apply paned position
129
174
        pos = self.pref.get_preference('paned_position', 'int')
130
 
        self.window.hpaned_main.set_position(pos)
 
175
        self.hpaned_main.set_position(pos)
 
176
        
 
177
        # Apply menu to the toolbutton
 
178
        #menubutton = self.toplevel.get_widget('menutoolbutton_diff')
 
179
        #menubutton.set_menu(handler.menu.toolbar_diff)
131
180
        
132
181
        # Now we can show the window
133
182
        self.window.show()
134
183
        
135
184
        # Show drive selector if under Win32
136
185
        if sys.platform == 'win32':
137
 
            self.hbox_location.pack_start(self.combobox_drive, False, False, 0)
138
 
            self.hbox_location.reorder_child(self.combobox_drive, 1)
 
186
            self.vbox_main_right.pack_start(self.combobox_drive, False, True, 0)
 
187
            self.vbox_main_right.reorder_child(self.combobox_drive, 0)
139
188
            self.combobox_drive.show()
140
189
            self.gen_hard_selector()
141
190
        
142
 
        # Acceptable errors when loading files/folders in the treeviews
143
 
        self.acceptable_errors = (errno.ENOENT, errno.ELOOP)
144
 
        
145
191
        self._load_left()
146
192
 
147
193
        # Apply menu state
148
 
        self.window.mb_view_showhidden.set_active(self.pref.get_preference('dotted_files', 'bool'))
149
 
        self.window.mb_view_showignored.set_active(self.pref.get_preference('ignored_files', 'bool'))
 
194
        self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
150
195
 
151
 
        # We're starting local
152
 
        self.remote = False
153
 
        self.remote_branch = None
154
 
        self.remote_path = None
155
 
        self.remote_revision = None
156
 
        
157
196
        self.set_path(os.getcwd())
158
197
        self._load_right()
159
198
        
160
199
        self._just_started = False
161
200
 
162
 
    def set_path(self, path, force_remote=False):
 
201
    def set_path(self, path):
 
202
        self.path = path
163
203
        self.notbranch = False
164
204
        
165
 
        if force_remote:
166
 
            # Forcing remote mode (reading data from inventory)
167
 
            self._show_stock_image(gtk.STOCK_DISCONNECT)
168
 
            try:
169
 
                br = Branch.open_containing(path)[0]
170
 
            except bzrerrors.NotBranchError:
171
 
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
172
 
                self.check_history.set_active(False)
173
 
                self.check_history.set_sensitive(False)
174
 
                return False
175
 
            except bzrerrors.UnsupportedProtocol:
176
 
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
177
 
                self.check_history.set_active(False)
178
 
                self.check_history.set_sensitive(False)
179
 
                return False
180
 
            
181
 
            self._show_stock_image(gtk.STOCK_CONNECT)
182
 
            
183
 
            self.remote = True
184
 
           
185
 
            # We're remote
186
 
            self.remote_branch, self.remote_path = Branch.open_containing(path)
187
 
            
188
 
            if self.remote_revision is None:
189
 
                self.remote_revision = self.remote_branch.last_revision()
190
 
            
191
 
            self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
192
 
            
193
 
            if len(self.remote_path) == 0:
194
 
                self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
195
 
            else:
196
 
                for (name, type) in self.remote_entries:
197
 
                    if name == self.remote_path:
198
 
                        self.remote_parent = type.file_id
199
 
                        break
200
 
            
201
 
            if not path.endswith('/'):
202
 
                path += '/'
203
 
            
204
 
            if self.remote_branch.base == path:
205
 
                self.button_location_up.set_sensitive(False)
206
 
            else:
207
 
                self.button_location_up.set_sensitive(True)
208
 
        else:
209
 
            if os.path.isdir(path):
210
 
                self.image_location_error.destroy()
211
 
                self.remote = False
212
 
                
213
 
                # We're local
214
 
                try:
215
 
                    self.wt, self.wtpath = WorkingTree.open_containing(path)
216
 
                except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
217
 
                    self.notbranch = True
218
 
                
219
 
                # If we're in the root, we cannot go up anymore
220
 
                if sys.platform == 'win32':
221
 
                    drive, tail = os.path.splitdrive(path)
222
 
                    if tail in ('', '/', '\\'):
223
 
                        self.button_location_up.set_sensitive(False)
224
 
                    else:
225
 
                        self.button_location_up.set_sensitive(True)
226
 
                else:
227
 
                    if self.path == '/':
228
 
                        self.button_location_up.set_sensitive(False)
229
 
                    else:
230
 
                        self.button_location_up.set_sensitive(True)
231
 
            elif not os.path.isfile(path):
232
 
                # Doesn't seem to be a file nor a directory, trying to open a
233
 
                # remote location
234
 
                self._show_stock_image(gtk.STOCK_DISCONNECT)
235
 
                try:
236
 
                    br = Branch.open_containing(path)[0]
237
 
                except bzrerrors.NotBranchError:
238
 
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
239
 
                    self.check_history.set_active(False)
240
 
                    self.check_history.set_sensitive(False)
241
 
                    return False
242
 
                except bzrerrors.UnsupportedProtocol:
243
 
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
244
 
                    self.check_history.set_active(False)
245
 
                    self.check_history.set_sensitive(False)
246
 
                    return False
247
 
                
248
 
                self._show_stock_image(gtk.STOCK_CONNECT)
249
 
                
250
 
                self.remote = True
251
 
               
252
 
                # We're remote
253
 
                self.remote_branch, self.remote_path = Branch.open_containing(path)
254
 
                
255
 
                if self.remote_revision is None:
256
 
                    self.remote_revision = self.remote_branch.last_revision()
257
 
                
258
 
                self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
259
 
                
260
 
                if len(self.remote_path) == 0:
261
 
                    self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
262
 
                else:
263
 
                    for (name, type) in self.remote_entries:
264
 
                        if name == self.remote_path:
265
 
                            self.remote_parent = type.file_id
266
 
                            break
267
 
                
268
 
                if not path.endswith('/'):
269
 
                    path += '/'
270
 
                
271
 
                if self.remote_branch.base == path:
272
 
                    self.button_location_up.set_sensitive(False)
273
 
                else:
274
 
                    self.button_location_up.set_sensitive(True)
275
 
        
276
 
        if self.notbranch:
277
 
            self.check_history.set_active(False)
278
 
            self.check_history.set_sensitive(False)
279
 
        else:
280
 
            self.check_history.set_sensitive(True)
281
 
        
282
 
        self.window.statusbar.push(self.context_id, path)
283
 
        self.entry_location.set_text(path)
284
 
        self.path = path
285
 
        return True
 
205
        try:
 
206
            self.wt, self.wtpath = WorkingTree.open_containing(self.path)
 
207
        except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
 
208
            self.notbranch = True
 
209
        
 
210
        self.statusbar.push(self.context_id, path)
286
211
 
287
212
    def get_path(self):
288
 
        if not self.remote:
289
 
            return self.path
290
 
        else:
291
 
            # Remote mode
292
 
            if len(self.remote_path) > 0:
293
 
                return self.remote_branch.base + self.remote_path + '/'
294
 
            else:
295
 
                return self.remote_branch.base
 
213
        return self.path
296
214
   
297
215
    def on_about_activate(self, widget):
 
216
        from dialog import about
298
217
        about()
299
 
    
300
 
    def on_button_history_browse_clicked(self, widget):
301
 
        """ Browse for revision button handler. """
302
 
        if self.remote:
303
 
            br = self.remote_branch
304
 
        else:
305
 
            br = self.wt.branch
306
 
            
307
 
        revb = RevisionBrowser(br, self.window)
308
 
        response = revb.run()
309
 
        if response != gtk.RESPONSE_NONE:
310
 
            revb.hide()
311
 
        
312
 
            if response == gtk.RESPONSE_OK:
313
 
                if revb.selected_revno is not None:
314
 
                    self.entry_history.set_text(revb.selected_revno)
315
 
                    self.on_entry_history_revno_activate()
316
 
            
317
 
            revb.destroy()
318
 
    
319
 
    def on_button_location_jump_clicked(self, widget):
320
 
        """ Location Jump button handler. """
321
 
        location = self.entry_location.get_text()
322
 
        
323
 
        if self.set_path(location):
324
 
            self.refresh_right()
325
 
    
326
 
    def on_button_location_up_clicked(self, widget):
327
 
        """ Location Up button handler. """
328
 
        if not self.remote:
329
 
            # Local mode
330
 
            self.set_path(os.path.split(self.get_path())[0])
331
 
        else:
332
 
            # Remote mode
333
 
            delim = '/'
334
 
            newpath = delim.join(self.get_path().split(delim)[:-2])
335
 
            newpath += '/'
336
 
            self.set_path(newpath)
337
 
 
338
 
        self.refresh_right()
339
 
    
340
 
    def on_checkbutton_history_toggled(self, widget):
341
 
        """ History Mode toggle handler. """
342
 
        if self.check_history.get_active():
343
 
            # History Mode activated
344
 
            self.entry_history.set_sensitive(True)
345
 
            self.button_history.set_sensitive(True)
346
 
            if self.entry_history.get_text() != "":
347
 
                self.on_entry_history_revno_activate()
348
 
        else:
349
 
            # History Mode deactivated
350
 
            self.entry_history.set_sensitive(False)
351
 
            self.button_history.set_sensitive(False)
352
 
            
353
 
            # Return right window to normal view by acting like we jump to it
354
 
            self.on_button_location_jump_clicked(widget)
355
 
    
356
 
    @show_bzr_error
357
 
    def on_entry_history_revno_activate(self, widget=None):
358
 
        """ Key pressed handler for the history entry. """
359
 
        path = self.get_path()
360
 
        if not self.remote:
361
 
            self.remote = True
362
 
            self.remote_branch = self.wt.branch
363
 
        
364
 
        revno = int(self.entry_history.get_text())
365
 
        self.remote_revision = self.remote_branch.get_rev_id(revno)
366
 
        if self.set_path(path, True):
367
 
            self.refresh_right()
368
 
 
 
218
        
369
219
    def on_menuitem_add_files_activate(self, widget):
370
220
        """ Add file(s)... menu handler. """
371
 
        from bzrlib.plugins.gtk.olive.add import AddDialog
372
 
        add = AddDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
373
 
        response = add.run()
374
 
        add.destroy()
375
 
        if response == gtk.RESPONSE_OK:
376
 
            self.refresh_right()
377
 
 
 
221
        from add import OliveAdd
 
222
        add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
 
223
        add.display()
 
224
    
378
225
    def on_menuitem_branch_get_activate(self, widget):
379
226
        """ Branch/Get... menu handler. """
380
 
        from bzrlib.plugins.gtk.branch import BranchDialog
381
 
        
382
 
        if self.remote:
383
 
            branch = BranchDialog(os.getcwd(), self.window, self.remote_branch.base)
384
 
        else:
385
 
            branch = BranchDialog(self.get_path(), self.window)
 
227
        from branch import BranchDialog
 
228
        branch = BranchDialog(self.get_path(), self.window)
386
229
        response = branch.run()
387
230
        if response != gtk.RESPONSE_NONE:
388
231
            branch.hide()
389
 
            
 
232
        
390
233
            if response == gtk.RESPONSE_OK:
391
234
                self.refresh_right()
392
235
            
394
237
    
395
238
    def on_menuitem_branch_checkout_activate(self, widget):
396
239
        """ Branch/Checkout... menu handler. """
397
 
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
398
 
        
399
 
        if self.remote:
400
 
            checkout = CheckoutDialog(os.getcwd(), self.window, self.remote_branch.base)
401
 
        else:
402
 
            checkout = CheckoutDialog(self.get_path(), self.window)
 
240
        from checkout import CheckoutDialog
 
241
        checkout = CheckoutDialog(self.get_path(), self.window)
403
242
        response = checkout.run()
404
243
        if response != gtk.RESPONSE_NONE:
405
244
            checkout.hide()
409
248
            
410
249
            checkout.destroy()
411
250
    
412
 
    @show_bzr_error
413
251
    def on_menuitem_branch_commit_activate(self, widget):
414
252
        """ Branch/Commit... menu handler. """
415
 
        selected = self.get_selected_right()
416
 
        if selected:
417
 
            selected = os.path.join(self.wtpath, selected)
418
 
        commit = CommitDialog(wt=self.wt,
419
 
                              parent=self.window,
420
 
                              selected=selected,
421
 
                             )
 
253
        commit = CommitDialog(self.wt, self.wtpath, self.notbranch, self.get_selected_right(), self.window)
422
254
        response = commit.run()
423
255
        if response != gtk.RESPONSE_NONE:
424
256
            commit.hide()
428
260
            
429
261
            commit.destroy()
430
262
    
431
 
    def on_menuitem_branch_conflicts_activate(self, widget):
432
 
        """ Branch/Conflicts... menu handler. """
433
 
        conflicts = ConflictsDialog(self.wt, self.window)
434
 
        response = conflicts.run()
435
 
        if response != gtk.RESPONSE_NONE:
436
 
            conflicts.destroy()
437
 
    
438
263
    def on_menuitem_branch_merge_activate(self, widget):
439
264
        """ Branch/Merge... menu handler. """
440
 
        from bzrlib.plugins.gtk.merge import MergeDialog
 
265
        from merge import MergeDialog
441
266
        
442
267
        if self.check_for_changes():
443
 
            error_dialog(_i18n('There are local changes in the branch'),
444
 
                         _i18n('Please commit or revert the changes before merging.'))
 
268
            error_dialog(_('There are local changes in the branch'),
 
269
                         _('Please commit or revert the changes before merging.'))
445
270
        else:
446
 
            parent_branch_path = self.wt.branch.get_parent()
447
 
            merge = MergeDialog(self.wt, self.wtpath, parent_branch_path, self.window)
448
 
            response = merge.run()
449
 
            merge.destroy()
450
 
            if response == gtk.RESPONSE_OK:
451
 
                self.refresh_right()
 
271
            merge = MergeDialog(self.wt, self.wtpath)
 
272
            merge.display()
452
273
 
453
 
    @show_bzr_error
454
274
    def on_menuitem_branch_missing_revisions_activate(self, widget):
455
275
        """ Branch/Missing revisions menu handler. """
456
 
        
457
 
        from bzrlib.missing import find_unmerged, iter_log_revisions
458
 
        
459
276
        local_branch = self.wt.branch
460
 
        parent_branch_path = local_branch.get_parent()
461
 
        if parent_branch_path is None:
462
 
            error_dialog(_i18n('Parent location is unknown'),
463
 
                         _i18n('Cannot determine missing revisions if no parent location is known.'))
 
277
        
 
278
        other_branch = local_branch.get_parent()
 
279
        if other_branch is None:
 
280
            error_dialog(_('Parent location is unknown'),
 
281
                         _('Cannot determine missing revisions if no parent location is known.'))
464
282
            return
465
283
        
466
 
        parent_branch = Branch.open(parent_branch_path)
467
 
        
468
 
        if parent_branch.base == local_branch.base:
469
 
            parent_branch = local_branch
470
 
        
471
 
        local_extra, remote_extra = find_unmerged(local_branch,parent_branch)
472
 
 
473
 
        if local_extra or remote_extra:
474
 
            
475
 
            ## def log_revision_one_line_text(log_revision):
476
 
            ##    """ Generates one line description of log_revison ended with end of line."""
477
 
            ##    revision = log_revision.rev
478
 
            ##    txt =  "- %s (%s)\n" % (revision.get_summary(), revision.committer, )
479
 
            ##    txt = txt.replace("<"," ") # Seems < > chars are expected to be xml tags ...
480
 
            ##    txt = txt.replace(">"," ")
481
 
            ##    return txt
482
 
            
483
 
            dlg_txt = ""
484
 
            if local_extra:
485
 
                dlg_txt += _i18n('%d local extra revision(s). \n') % (len(local_extra),) 
486
 
                ## NOTE: We do not want such ugly info about missing revisions
487
 
                ##       Revision Browser should be used there
488
 
                ## max_revisions = 10
489
 
                ## for log_revision in iter_log_revisions(local_extra, local_branch.repository, verbose=1):
490
 
                ##    dlg_txt += log_revision_one_line_text(log_revision)
491
 
                ##    if max_revisions <= 0:
492
 
                ##        dlg_txt += _i18n("more ... \n")
493
 
                ##        break
494
 
                ## max_revisions -= 1
495
 
            ## dlg_txt += "\n"
496
 
            if remote_extra:
497
 
                dlg_txt += _i18n('%d local missing revision(s).\n') % (len(remote_extra),) 
498
 
                ## max_revisions = 10
499
 
                ## for log_revision in iter_log_revisions(remote_extra, parent_branch.repository, verbose=1):
500
 
                ##    dlg_txt += log_revision_one_line_text(log_revision)
501
 
                ##    if max_revisions <= 0:
502
 
                ##        dlg_txt += _i18n("more ... \n")
503
 
                ##        break
504
 
                ##    max_revisions -= 1
505
 
                
506
 
            info_dialog(_i18n('There are missing revisions'),
507
 
                        dlg_txt)
 
284
        remote_branch = Branch.open(other_branch)
 
285
        
 
286
        if remote_branch.base == local_branch.base:
 
287
            remote_branch = local_branch
 
288
 
 
289
        ret = len(local_branch.missing_revisions(remote_branch))
 
290
 
 
291
        if ret > 0:
 
292
            info_dialog(_('There are missing revisions'),
 
293
                        _('%d revision(s) missing.') % ret)
508
294
        else:
509
 
            info_dialog(_i18n('Local branch up to date'),
510
 
                        _i18n('There are no missing revisions.'))
 
295
            info_dialog(_('Local branch up to date'),
 
296
                        _('There are no missing revisions.'))
511
297
 
512
298
    @show_bzr_error
513
299
    def on_menuitem_branch_pull_activate(self, widget):
516
302
 
517
303
        location = branch_to.get_parent()
518
304
        if location is None:
519
 
            error_dialog(_i18n('Parent location is unknown'),
520
 
                                     _i18n('Pulling is not possible until there is a parent location.'))
 
305
            error_dialog(_('Parent location is unknown'),
 
306
                                     _('Pulling is not possible until there is a parent location.'))
521
307
            return
522
308
 
523
309
        branch_from = Branch.open(location)
525
311
        if branch_to.get_parent() is None:
526
312
            branch_to.set_parent(branch_from.base)
527
313
 
 
314
        #old_rh = branch_to.revision_history()
 
315
        #if tree_to is not None:
 
316
        #    tree_to.pull(branch_from)
 
317
        #else:
 
318
        #    branch_to.pull(branch_from)
528
319
        ret = branch_to.pull(branch_from)
529
320
        
530
 
        info_dialog(_i18n('Pull successful'), _i18n('%d revision(s) pulled.') % ret)
531
 
        
532
 
    @show_bzr_error
533
 
    def on_menuitem_branch_update_activate(self, widget):
534
 
        """ Brranch/checkout update menu handler. """
535
 
        
536
 
        ret = self.wt.update()
537
 
        conflicts = self.wt.conflicts()
538
 
        if conflicts:
539
 
            info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
540
 
        else:
541
 
            info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
 
321
        info_dialog(_('Pull successful'), _('%d revision(s) pulled.') % ret)
542
322
    
543
323
    def on_menuitem_branch_push_activate(self, widget):
544
324
        """ Branch/Push... menu handler. """
545
 
        push = PushDialog(repository=None,revid=None,branch=self.wt.branch, parent=self.window)
 
325
        push = PushDialog(self.wt.branch, self.window)
546
326
        response = push.run()
547
327
        if response != gtk.RESPONSE_NONE:
548
328
            push.destroy()
550
330
    @show_bzr_error
551
331
    def on_menuitem_branch_revert_activate(self, widget):
552
332
        """ Branch/Revert all changes menu handler. """
553
 
        ret = self.wt.revert(None)
 
333
        ret = self.wt.revert([])
554
334
        if ret:
555
 
            warning_dialog(_i18n('Conflicts detected'),
556
 
                           _i18n('Please have a look at the working tree before continuing.'))
 
335
            warning_dialog(_('Conflicts detected'),
 
336
                           _('Please have a look at the working tree before continuing.'))
557
337
        else:
558
 
            info_dialog(_i18n('Revert successful'),
559
 
                        _i18n('All files reverted to last revision.'))
 
338
            info_dialog(_('Revert successful'),
 
339
                        _('All files reverted to last revision.'))
560
340
        self.refresh_right()
561
341
    
562
342
    def on_menuitem_branch_status_activate(self, widget):
563
343
        """ Branch/Status... menu handler. """
564
 
        from bzrlib.plugins.gtk.status import StatusDialog
565
 
        status = StatusDialog(self.wt, self.wtpath)
566
 
        response = status.run()
567
 
        if response != gtk.RESPONSE_NONE:
568
 
            status.destroy()
 
344
        from status import OliveStatus
 
345
        status = OliveStatus(self.wt, self.wtpath)
 
346
        status.display()
569
347
    
 
348
    @show_bzr_error
570
349
    def on_menuitem_branch_initialize_activate(self, widget):
571
350
        """ Initialize current directory. """
572
 
        init = InitDialog(self.path, self.window)
573
 
        response = init.run()
574
 
        if response != gtk.RESPONSE_NONE:
575
 
            init.hide()
576
 
        
577
 
            if response == gtk.RESPONSE_OK:
578
 
                self.refresh_right()
579
 
            
580
 
            init.destroy()
581
 
        
582
 
    def on_menuitem_branch_tags_activate(self, widget):
583
 
        """ Branch/Tags... menu handler. """
584
 
        from bzrlib.plugins.gtk.tags import TagsWindow
585
 
        if not self.remote:
586
 
            window = TagsWindow(self.wt.branch, self.window)
 
351
        import bzrlib.bzrdir as bzrdir
 
352
        
 
353
        if not os.path.exists(self.path):
 
354
            os.mkdir(self.path)
 
355
 
 
356
        try:
 
357
            existing_bzrdir = bzrdir.BzrDir.open(self.path)
 
358
        except bzrerrors.NotBranchError:
 
359
            bzrdir.BzrDir.create_branch_convenience(self.path)
587
360
        else:
588
 
            window = TagsWindow(self.remote_branch, self.window)
589
 
        window.show()
590
 
    
 
361
            if existing_bzrdir.has_branch():
 
362
                if existing_bzrdir.has_workingtree():
 
363
                    raise bzrerrors.AlreadyBranchError(self.path)
 
364
                else:
 
365
                    raise bzrerrors.BranchExistsWithoutWorkingTree(self.path)
 
366
            else:
 
367
                existing_bzrdir.create_branch()
 
368
                existing_bzrdir.create_workingtree()
 
369
        info_dialog(_('Initialize successful'),
 
370
                    _('Directory successfully initialized.'))
 
371
        self.refresh_right()
 
372
        
591
373
    def on_menuitem_file_annotate_activate(self, widget):
592
374
        """ File/Annotate... menu handler. """
593
375
        if self.get_selected_right() is None:
594
 
            error_dialog(_i18n('No file was selected'),
595
 
                         _i18n('Please select a file from the list.'))
 
376
            error_dialog(_('No file was selected'),
 
377
                         _('Please select a file from the list.'))
596
378
            return
597
379
        
598
380
        branch = self.wt.branch
599
381
        file_id = self.wt.path2id(self.wt.relpath(os.path.join(self.path, self.get_selected_right())))
600
382
        
601
 
        window = GAnnotateWindow(all=False, plain=False, parent=self.window)
 
383
        window = GAnnotateWindow(all=False, plain=False)
602
384
        window.set_title(os.path.join(self.path, self.get_selected_right()) + " - Annotate")
603
385
        config = GAnnotateConfig(window)
604
386
        window.show()
608
390
        finally:
609
391
            branch.unlock()
610
392
    
611
 
    def on_menuitem_file_bookmark_activate(self, widget):
612
 
        """ File/Bookmark current directory menu handler. """
613
 
        if self.pref.add_bookmark(self.path):
614
 
            info_dialog(_i18n('Bookmark successfully added'),
615
 
                        _i18n('The current directory was bookmarked. You can reach\nit by selecting it from the left panel.'))
616
 
            self.pref.write()
617
 
        else:
618
 
            warning_dialog(_i18n('Location already bookmarked'),
619
 
                           _i18n('The current directory is already bookmarked.\nSee the left panel for reference.'))
620
 
        
621
 
        self.refresh_left()
622
 
    
623
393
    def on_menuitem_file_make_directory_activate(self, widget):
624
394
        """ File/Make directory... menu handler. """
625
 
        from bzrlib.plugins.gtk.olive.mkdir import MkdirDialog
626
 
        mkdir = MkdirDialog(self.wt, self.wtpath, self.window)
627
 
        response = mkdir.run()
628
 
        mkdir.destroy()
629
 
        if response == gtk.RESPONSE_OK:
630
 
            self.refresh_right()
 
395
        from mkdir import OliveMkdir
 
396
        mkdir = OliveMkdir(self.wt, self.wtpath)
 
397
        mkdir.display()
631
398
    
632
399
    def on_menuitem_file_move_activate(self, widget):
633
400
        """ File/Move... menu handler. """
634
 
        from bzrlib.plugins.gtk.olive.move import MoveDialog
635
 
        move = MoveDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
636
 
        response = move.run()
637
 
        move.destroy()
638
 
        if response == gtk.RESPONSE_OK:
639
 
            self.refresh_right()
 
401
        from move import OliveMove
 
402
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
 
403
        move.display()
640
404
    
641
405
    def on_menuitem_file_rename_activate(self, widget):
642
406
        """ File/Rename... menu handler. """
643
 
        from bzrlib.plugins.gtk.olive.rename import RenameDialog
644
 
        rename = RenameDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
645
 
        response = rename.run()
646
 
        rename.destroy()
647
 
        if response == gtk.RESPONSE_OK:
648
 
            self.refresh_right()
 
407
        from rename import OliveRename
 
408
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
 
409
        rename.display()
649
410
 
650
411
    def on_menuitem_remove_file_activate(self, widget):
651
412
        """ Remove (unversion) selected file. """
652
 
        from bzrlib.plugins.gtk.olive.remove import RemoveDialog
653
 
        remove = RemoveDialog(self.wt, self.wtpath,
 
413
        from remove import OliveRemoveDialog
 
414
        remove = OliveRemoveDialog(self.wt, self.wtpath,
654
415
                                   selected=self.get_selected_right(),
655
416
                                   parent=self.window)
656
417
        response = remove.run()
666
427
    
667
428
    def on_menuitem_stats_diff_activate(self, widget):
668
429
        """ Statistics/Differences... menu handler. """
669
 
        window = DiffWindow(parent=self.window)
 
430
        window = DiffWindow()
670
431
        parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
671
432
        window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
672
433
        window.show()
673
434
    
674
435
    def on_menuitem_stats_infos_activate(self, widget):
675
436
        """ Statistics/Informations... menu handler. """
676
 
        from bzrlib.plugins.gtk.olive.info import InfoDialog
677
 
        if self.remote:
678
 
            info = InfoDialog(self.remote_branch)
679
 
        else:
680
 
            info = InfoDialog(self.wt.branch)
 
437
        from info import OliveInfo
 
438
        info = OliveInfo(self.wt)
681
439
        info.display()
682
440
    
683
441
    def on_menuitem_stats_log_activate(self, widget):
684
442
        """ Statistics/Log... menu handler. """
685
 
 
686
 
        if not self.remote:
687
 
            branch = self.wt.branch
688
 
        else:
689
 
            branch = self.remote_branch
690
 
 
691
 
        window = branchwin.BranchWindow(branch, [branch.last_revision()], None, 
692
 
                                        parent=self.window)
 
443
        window = BranchWindow()
 
444
        window.set_branch(self.wt.branch, self.wt.branch.last_revision(), None)
693
445
        window.show()
694
446
    
695
447
    def on_menuitem_view_refresh_activate(self, widget):
705
457
        if self.path is not None:
706
458
            self.refresh_right()
707
459
 
708
 
    def on_menuitem_view_show_ignored_files_activate(self, widget):
709
 
        """ Hide/Show ignored files menu handler. """
710
 
        self.pref.set_preference('ignored_files', widget.get_active())
711
 
        if self.path is not None:
712
 
            self.refresh_right()
713
 
            
714
460
    def on_treeview_left_button_press_event(self, widget, event):
715
 
        """ Occurs when somebody clicks in the bookmark list. """
716
 
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
717
 
        treeselection = widget.get_selection()
718
 
        if treepathpos is not None:
719
 
            treeselection.select_path(treepathpos[0])
720
 
            if event.button == 1:
721
 
                newdir = self.get_selected_left()
722
 
                if newdir == None:
723
 
                    return
724
 
 
725
 
                if self.set_path(newdir):
726
 
                    self.refresh_right()
727
 
            elif event.button == 3:
728
 
                # Don't show context with nothing selected
729
 
                if self.get_selected_left() == None:
730
 
                    return
731
 
 
732
 
                # Create a menu
733
 
                from menu import OliveMenu
734
 
                menu = OliveMenu(path=self.get_path(),
735
 
                                 selected=self.get_selected_left(),
736
 
                                 app=self)
737
 
                
738
 
                menu.left_context_menu().popup(None, None, None, 0,
739
 
                                               event.time)
740
 
        else:
741
 
            if treeselection is not None:
742
 
                treeselection.unselect_all()
 
461
        """ Occurs when somebody right-clicks in the bookmark list. """
 
462
        if event.button == 3:
 
463
            # Don't show context with nothing selected
 
464
            if self.get_selected_left() == None:
 
465
                return
 
466
 
 
467
            # Create a menu
 
468
            from menu import OliveMenu
 
469
            menu = OliveMenu(path=self.get_path(),
 
470
                             selected=self.get_selected_left(),
 
471
                             app=self)
 
472
            
 
473
            menu.left_context_menu().popup(None, None, None, 0,
 
474
                                           event.time)
743
475
 
744
476
    def on_treeview_left_row_activated(self, treeview, path, view_column):
745
477
        """ Occurs when somebody double-clicks or enters an item in the
749
481
        if newdir == None:
750
482
            return
751
483
 
752
 
        if self.set_path(newdir):
753
 
            self.refresh_right()
 
484
        self.set_path(newdir)
 
485
        self.refresh_right()
754
486
 
755
487
    def on_treeview_right_button_press_event(self, widget, event):
756
 
        """ Occurs when somebody clicks in the file list. """
757
 
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
758
 
        if event.button == 1:
759
 
            if treepathpos is None and widget.get_selection is not None:
760
 
                treeselection = widget.get_selection()
761
 
                treeselection.unselect_all()
762
 
        elif event.button == 3:
763
 
            treeselection = widget.get_selection()
764
 
            if treepathpos is not None:
765
 
                treeselection.select_path(treepathpos[0])
766
 
            else:
767
 
                if treeselection is not None:
768
 
                    treeselection.unselect_all()
 
488
        """ Occurs when somebody right-clicks in the file list. """
 
489
        if event.button == 3:
769
490
            # Create a menu
770
491
            from menu import OliveMenu
771
492
            menu = OliveMenu(path=self.get_path(),
772
493
                             selected=self.get_selected_right(),
773
494
                             app=self)
774
495
            # get the menu items
775
 
            m_open = menu.ui.get_widget('/context_right/open')
776
496
            m_add = menu.ui.get_widget('/context_right/add')
777
497
            m_remove = menu.ui.get_widget('/context_right/remove')
778
 
            m_remove_and_delete = menu.ui.get_widget('/context_right/remove_and_delete')
779
498
            m_rename = menu.ui.get_widget('/context_right/rename')
780
499
            m_revert = menu.ui.get_widget('/context_right/revert')
781
500
            m_commit = menu.ui.get_widget('/context_right/commit')
782
 
            m_annotate = menu.ui.get_widget('/context_right/annotate')
783
501
            m_diff = menu.ui.get_widget('/context_right/diff')
784
502
            # check if we're in a branch
785
503
            try:
786
504
                from bzrlib.branch import Branch
787
505
                Branch.open_containing(self.get_path())
788
 
                if self.remote:
789
 
                    m_open.set_sensitive(False)
790
 
                    m_add.set_sensitive(False)
791
 
                    m_remove.set_sensitive(False)
792
 
                    m_remove_and_delete.set_sensitive(False)
793
 
                    m_rename.set_sensitive(False)
794
 
                    m_revert.set_sensitive(False)
795
 
                    m_commit.set_sensitive(False)
796
 
                    m_annotate.set_sensitive(False)
797
 
                    m_diff.set_sensitive(False)
798
 
                else:
799
 
                    if treepathpos is None:
800
 
                        m_open.set_sensitive(False)
801
 
                        m_add.set_sensitive(False)
802
 
                        m_remove.set_sensitive(False)
803
 
                        m_remove_and_delete.set_sensitive(False)
804
 
                        m_rename.set_sensitive(False)
805
 
                        m_annotate.set_sensitive(False)
806
 
                        m_diff.set_sensitive(False)
807
 
                        m_revert.set_sensitive(False)
808
 
                    else:
809
 
                        m_open.set_sensitive(True)
810
 
                        m_add.set_sensitive(True)
811
 
                        m_remove.set_sensitive(True)
812
 
                        m_remove_and_delete.set_sensitive(True)
813
 
                        m_rename.set_sensitive(True)
814
 
                        m_annotate.set_sensitive(True)
815
 
                        m_diff.set_sensitive(True)
816
 
                        m_revert.set_sensitive(True)
817
 
                    m_commit.set_sensitive(True)
 
506
                m_add.set_sensitive(True)
 
507
                m_remove.set_sensitive(True)
 
508
                m_rename.set_sensitive(True)
 
509
                m_revert.set_sensitive(True)
 
510
                m_commit.set_sensitive(True)
 
511
                m_diff.set_sensitive(True)
818
512
            except bzrerrors.NotBranchError:
819
 
                if treepathpos is None:
820
 
                    m_open.set_sensitive(False)
821
 
                else:
822
 
                    m_open.set_sensitive(True)
823
513
                m_add.set_sensitive(False)
824
514
                m_remove.set_sensitive(False)
825
 
                m_remove_and_delete.set_sensitive(False)
826
515
                m_rename.set_sensitive(False)
827
516
                m_revert.set_sensitive(False)
828
517
                m_commit.set_sensitive(False)
829
 
                m_annotate.set_sensitive(False)
830
518
                m_diff.set_sensitive(False)
831
519
 
832
 
            if not self.remote:
833
 
                menu.right_context_menu().popup(None, None, None, 0,
834
 
                                                event.time)
835
 
            else:
836
 
                menu.remote_context_menu().popup(None, None, None, 0,
837
 
                                                 event.time)
 
520
            menu.right_context_menu().popup(None, None, None, 0,
 
521
                                            event.time)
838
522
        
839
523
    def on_treeview_right_row_activated(self, treeview, path, view_column):
840
524
        """ Occurs when somebody double-clicks or enters an item in the
843
527
        
844
528
        newdir = self.get_selected_right()
845
529
        
846
 
        if not self.remote:
847
 
            # We're local
848
 
            if newdir == '..':
849
 
                self.set_path(os.path.split(self.get_path())[0])
 
530
        if newdir == '..':
 
531
            self.set_path(os.path.split(self.get_path())[0])
 
532
        else:
 
533
            fullpath = os.path.join(self.get_path(), newdir)
 
534
            if os.path.isdir(fullpath):
 
535
                # selected item is an existant directory
 
536
                self.set_path(fullpath)
850
537
            else:
851
 
                fullpath = os.path.join(self.get_path(), newdir)
852
 
                if os.path.isdir(fullpath):
853
 
                    # selected item is an existant directory
854
 
                    self.set_path(fullpath)
855
 
                else:
856
 
                    launch(fullpath)
857
 
        else:
858
 
            # We're remote
859
 
            if self._is_remote_dir(self.get_path() + newdir):
860
 
                self.set_path(self.get_path() + newdir)
 
538
                launch(fullpath) 
861
539
        
862
540
        self.refresh_right()
863
541
    
864
542
    def on_window_main_delete_event(self, widget, event=None):
865
543
        """ Do some stuff before exiting. """
866
 
        width, height = self.window.get_size()
 
544
        width, height = self.window_main.get_size()
867
545
        self.pref.set_preference('window_width', width)
868
546
        self.pref.set_preference('window_height', height)
869
 
        x, y = self.window.get_position()
 
547
        x, y = self.window_main.get_position()
870
548
        self.pref.set_preference('window_x', x)
871
549
        self.pref.set_preference('window_y', y)
872
550
        self.pref.set_preference('paned_position',
873
 
                                 self.window.hpaned_main.get_position())
 
551
                                 self.hpaned_main.get_position())
874
552
        
875
553
        self.pref.write()
876
 
        self.window.destroy()
 
554
        self.window_main.destroy()
877
555
        
878
556
    def _load_left(self):
879
557
        """ Load data into the left panel. (Bookmarks) """
884
562
        bookmarks = self.pref.get_bookmarks()
885
563
        
886
564
        # Add them to the TreeStore
887
 
        titer = treestore.append(None, [_i18n('Bookmarks'), None])
888
 
 
889
 
        # Get titles and sort by title
890
 
        bookmarks = [[self.pref.get_bookmark_title(item), item] for item in bookmarks]
891
 
        bookmarks.sort()
892
 
        for title_item in bookmarks:
893
 
            treestore.append(titer, title_item)
 
565
        titer = treestore.append(None, [_('Bookmarks'), None])
 
566
        for item in bookmarks:
 
567
            title = self.pref.get_bookmark_title(item)
 
568
            treestore.append(titer, [title, item])
894
569
        
895
570
        # Create the column and add it to the TreeView
896
571
        self.treeview_left.set_model(treestore)
897
 
        tvcolumn_bookmark = gtk.TreeViewColumn(_i18n('Bookmark'))
 
572
        tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
898
573
        self.treeview_left.append_column(tvcolumn_bookmark)
899
574
        
900
575
        # Set up the cells
905
580
        # Expand the tree
906
581
        self.treeview_left.expand_all()
907
582
 
 
583
    def _add_updir_to_dirlist(self, dirlist, curdir):
 
584
        """Add .. to the top of directories list if we not in root directory
 
585
 
 
586
        :param dirlist:     list of directories (modified in place)
 
587
        :param curdir:      current directory
 
588
        :return:            nothing
 
589
        """
 
590
        if curdir is None:
 
591
            curdir = self.path
 
592
 
 
593
        if sys.platform == 'win32':
 
594
            drive, tail = os.path.splitdrive(curdir)
 
595
            if tail in ('', '/', '\\'):
 
596
                return
 
597
        else:
 
598
            if curdir == '/':
 
599
                return
 
600
 
 
601
        # insert always as first element
 
602
        dirlist.insert(0, '..')
 
603
 
908
604
    def _load_right(self):
909
605
        """ Load data into the right panel. (Filelist) """
910
606
        # Create ListStore
911
 
        # Model: [ icon, dir, name, status text, status, size (int), size (human), mtime (int), mtime (local), fileid ]
912
 
        liststore = gtk.ListStore(gobject.TYPE_STRING,
913
 
                                  gobject.TYPE_BOOLEAN,
914
 
                                  gobject.TYPE_STRING,
915
 
                                  gobject.TYPE_STRING,
916
 
                                  gobject.TYPE_STRING,
917
 
                                  gobject.TYPE_STRING,
918
 
                                  gobject.TYPE_STRING,
919
 
                                  gobject.TYPE_INT,
920
 
                                  gobject.TYPE_STRING,
921
 
                                  gobject.TYPE_STRING)
 
607
        liststore = gtk.ListStore(str, str, str)
922
608
        
923
609
        dirs = []
924
610
        files = []
932
618
                dirs.append(item)
933
619
            else:
934
620
                files.append(item)
 
621
            
 
622
        # Sort'em
 
623
        dirs.sort()
 
624
        files.sort()
 
625
 
 
626
        # add updir link to dirs
 
627
        self._add_updir_to_dirlist(dirs, self.path)
935
628
        
936
629
        if not self.notbranch:
937
630
            branch = self.wt.branch
940
633
            delta = self.wt.changes_from(tree2, want_unchanged=True)
941
634
        
942
635
        # Add'em to the ListStore
943
 
        for item in dirs:
944
 
            try:
945
 
                statinfo = os.stat(self.path + os.sep + item)
946
 
            except OSError, e:
947
 
                if e.errno in self.acceptable_errors:
948
 
                    continue
949
 
                else:
950
 
                    raise
951
 
            liststore.append([ gtk.STOCK_DIRECTORY,
952
 
                               True,
953
 
                               item,
954
 
                               '',
955
 
                               '',
956
 
                               "<DIR>",
957
 
                               "<DIR>",
958
 
                               statinfo.st_mtime,
959
 
                               self._format_date(statinfo.st_mtime),
960
 
                               ''])
 
636
        for item in dirs:    
 
637
            liststore.append([gtk.STOCK_DIRECTORY, item, ''])
961
638
        for item in files:
962
639
            status = 'unknown'
963
 
            fileid = ''
964
640
            if not self.notbranch:
965
641
                filename = self.wt.relpath(self.path + os.sep + item)
966
642
                
967
 
                try:
968
 
                    self.wt.lock_read()
969
 
                    
970
 
                    for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
971
 
                        if rpathnew == filename:
972
 
                            status = 'renamed'
973
 
                            fileid = id
974
 
                    for rpath, id, kind in delta.added:
975
 
                        if rpath == filename:
976
 
                            status = 'added'
977
 
                            fileid = id
978
 
                    for rpath, id, kind in delta.removed:
979
 
                        if rpath == filename:
980
 
                            status = 'removed'
981
 
                            fileid = id
982
 
                    for rpath, id, kind, text_modified, meta_modified in delta.modified:
983
 
                        if rpath == filename:
984
 
                            status = 'modified'
985
 
                            fileid = id
986
 
                    for rpath, id, kind in delta.unchanged:
987
 
                        if rpath == filename:
988
 
                            status = 'unchanged'
989
 
                            fileid = id
990
 
                    for rpath, file_class, kind, id, entry in self.wt.list_files():
991
 
                        if rpath == filename and file_class == 'I':
992
 
                            status = 'ignored'
993
 
                finally:
994
 
                    self.wt.unlock()
 
643
                for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
 
644
                    if rpathnew == filename:
 
645
                        status = 'renamed'
 
646
                for rpath, id, kind in delta.added:
 
647
                    if rpath == filename:
 
648
                        status = 'added'
 
649
                for rpath, id, kind in delta.removed:
 
650
                    if rpath == filename:
 
651
                        status = 'removed'
 
652
                for rpath, id, kind, text_modified, meta_modified in delta.modified:
 
653
                    if rpath == filename:
 
654
                        status = 'modified'
 
655
                for rpath, id, kind in delta.unchanged:
 
656
                    if rpath == filename:
 
657
                        status = 'unchanged'
 
658
                for rpath, file_class, kind, id, entry in self.wt.list_files():
 
659
                    if rpath == filename and file_class == 'I':
 
660
                        status = 'ignored'
 
661
            
 
662
            #try:
 
663
            #    status = fileops.status(path + os.sep + item)
 
664
            #except errors.PermissionDenied:
 
665
            #    continue
995
666
            
996
667
            if status == 'renamed':
997
 
                st = _i18n('renamed')
 
668
                st = _('renamed')
998
669
            elif status == 'removed':
999
 
                st = _i18n('removed')
 
670
                st = _('removed')
1000
671
            elif status == 'added':
1001
 
                st = _i18n('added')
 
672
                st = _('added')
1002
673
            elif status == 'modified':
1003
 
                st = _i18n('modified')
 
674
                st = _('modified')
1004
675
            elif status == 'unchanged':
1005
 
                st = _i18n('unchanged')
 
676
                st = _('unchanged')
1006
677
            elif status == 'ignored':
1007
 
                st = _i18n('ignored')
 
678
                st = _('ignored')
1008
679
            else:
1009
 
                st = _i18n('unknown')
1010
 
            
1011
 
            try:
1012
 
                statinfo = os.stat(self.path + os.sep + item)
1013
 
            except OSError, e:
1014
 
                if e.errno in self.acceptable_errors:
1015
 
                    continue
1016
 
                else:
1017
 
                    raise
1018
 
            liststore.append([gtk.STOCK_FILE,
1019
 
                              False,
1020
 
                              item,
1021
 
                              st,
1022
 
                              status,
1023
 
                              str(statinfo.st_size), # NOTE: if int used there it will fail for large files (size expressed as long int)
1024
 
                              self._format_size(statinfo.st_size),
1025
 
                              statinfo.st_mtime,
1026
 
                              self._format_date(statinfo.st_mtime),
1027
 
                              fileid])
 
680
                st = _('unknown')
 
681
            liststore.append([gtk.STOCK_FILE, item, st])
1028
682
        
1029
683
        # Create the columns and add them to the TreeView
1030
684
        self.treeview_right.set_model(liststore)
1031
 
        self._tvcolumn_filename = gtk.TreeViewColumn(_i18n('Filename'))
1032
 
        self._tvcolumn_status = gtk.TreeViewColumn(_i18n('Status'))
1033
 
        self._tvcolumn_size = gtk.TreeViewColumn(_i18n('Size'))
1034
 
        self._tvcolumn_mtime = gtk.TreeViewColumn(_i18n('Last modified'))
1035
 
        self.treeview_right.append_column(self._tvcolumn_filename)
1036
 
        self.treeview_right.append_column(self._tvcolumn_status)
1037
 
        self.treeview_right.append_column(self._tvcolumn_size)
1038
 
        self.treeview_right.append_column(self._tvcolumn_mtime)
 
685
        tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
 
686
        tvcolumn_status = gtk.TreeViewColumn(_('Status'))
 
687
        self.treeview_right.append_column(tvcolumn_filename)
 
688
        self.treeview_right.append_column(tvcolumn_status)
1039
689
        
1040
690
        # Set up the cells
1041
691
        cellpb = gtk.CellRendererPixbuf()
1042
692
        cell = gtk.CellRendererText()
1043
 
        self._tvcolumn_filename.pack_start(cellpb, False)
1044
 
        self._tvcolumn_filename.pack_start(cell, True)
1045
 
        self._tvcolumn_filename.set_attributes(cellpb, stock_id=0)
1046
 
        self._tvcolumn_filename.add_attribute(cell, 'text', 2)
1047
 
        self._tvcolumn_status.pack_start(cell, True)
1048
 
        self._tvcolumn_status.add_attribute(cell, 'text', 3)
1049
 
        self._tvcolumn_size.pack_start(cell, True)
1050
 
        self._tvcolumn_size.add_attribute(cell, 'text', 6)
1051
 
        self._tvcolumn_mtime.pack_start(cell, True)
1052
 
        self._tvcolumn_mtime.add_attribute(cell, 'text', 8)
1053
 
        
1054
 
        # Set up the properties of the TreeView
1055
 
        self.treeview_right.set_headers_visible(True)
1056
 
        self.treeview_right.set_headers_clickable(True)
1057
 
        self.treeview_right.set_search_column(1)
1058
 
        self._tvcolumn_filename.set_resizable(True)
1059
 
        self._tvcolumn_status.set_resizable(True)
1060
 
        self._tvcolumn_size.set_resizable(True)
1061
 
        self._tvcolumn_mtime.set_resizable(True)
1062
 
        # Set up sorting
1063
 
        liststore.set_sort_func(13, self._sort_filelist_callback, None)
1064
 
        liststore.set_sort_column_id(13, gtk.SORT_ASCENDING)
1065
 
        self._tvcolumn_filename.set_sort_column_id(13)
1066
 
        self._tvcolumn_status.set_sort_column_id(3)
1067
 
        self._tvcolumn_size.set_sort_column_id(5)
1068
 
        self._tvcolumn_mtime.set_sort_column_id(7)
 
693
        tvcolumn_filename.pack_start(cellpb, False)
 
694
        tvcolumn_filename.pack_start(cell, True)
 
695
        tvcolumn_filename.set_attributes(cellpb, stock_id=0)
 
696
        tvcolumn_filename.add_attribute(cell, 'text', 1)
 
697
        tvcolumn_status.pack_start(cell, True)
 
698
        tvcolumn_status.add_attribute(cell, 'text', 2)
1069
699
        
1070
700
        # Set sensitivity
1071
701
        self.set_sensitivity()
1072
702
        
1073
 
    def get_selected_fileid(self):
1074
 
        """ Get the file_id of the selected file. """
1075
 
        treeselection = self.treeview_right.get_selection()
1076
 
        (model, iter) = treeselection.get_selected()
1077
 
        
1078
 
        if iter is None:
1079
 
            return None
1080
 
        else:
1081
 
            return model.get_value(iter, 9)
1082
 
    
1083
703
    def get_selected_right(self):
1084
704
        """ Get the selected filename. """
1085
705
        treeselection = self.treeview_right.get_selection()
1088
708
        if iter is None:
1089
709
            return None
1090
710
        else:
1091
 
            return model.get_value(iter, 2)
 
711
            return model.get_value(iter, 1)
1092
712
    
1093
713
    def get_selected_left(self):
1094
714
        """ Get the selected bookmark. """
1102
722
 
1103
723
    def set_statusbar(self, message):
1104
724
        """ Set the statusbar message. """
1105
 
        self.window.statusbar.push(self.context_id, message)
 
725
        self.statusbar.push(self.context_id, message)
1106
726
    
1107
727
    def clear_statusbar(self):
1108
728
        """ Clean the last message from the statusbar. """
1109
 
        self.window.statusbar.pop(self.context_id)
 
729
        self.statusbar.pop(self.context_id)
1110
730
    
1111
731
    def set_sensitivity(self):
1112
732
        """ Set menu and toolbar sensitivity. """
1113
 
        if not self.remote:
1114
 
            self.window.set_view_to_localbranch(self.notbranch)
1115
 
        else:
1116
 
            self.window.set_view_to_remotebranch()
 
733
        self.menuitem_branch_init.set_sensitive(self.notbranch)
 
734
        self.menuitem_branch_get.set_sensitive(self.notbranch)
 
735
        self.menuitem_branch_checkout.set_sensitive(self.notbranch)
 
736
        self.menuitem_branch_pull.set_sensitive(not self.notbranch)
 
737
        self.menuitem_branch_push.set_sensitive(not self.notbranch)
 
738
        self.menuitem_branch_revert.set_sensitive(not self.notbranch)
 
739
        self.menuitem_branch_merge.set_sensitive(not self.notbranch)
 
740
        self.menuitem_branch_commit.set_sensitive(not self.notbranch)
 
741
        self.menuitem_branch_status.set_sensitive(not self.notbranch)
 
742
        self.menuitem_branch_missing.set_sensitive(not self.notbranch)
 
743
        self.menuitem_stats.set_sensitive(not self.notbranch)
 
744
        self.menuitem_add_files.set_sensitive(not self.notbranch)
 
745
        self.menuitem_remove_files.set_sensitive(not self.notbranch)
 
746
        self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
 
747
        self.menuitem_file_rename.set_sensitive(not self.notbranch)
 
748
        self.menuitem_file_move.set_sensitive(not self.notbranch)
 
749
        self.menuitem_file_annotate.set_sensitive(not self.notbranch)
 
750
        #self.menutoolbutton_diff.set_sensitive(True)
 
751
        self.toolbutton_diff.set_sensitive(not self.notbranch)
 
752
        self.toolbutton_log.set_sensitive(not self.notbranch)
 
753
        self.toolbutton_commit.set_sensitive(not self.notbranch)
 
754
        self.toolbutton_pull.set_sensitive(not self.notbranch)
 
755
        self.toolbutton_push.set_sensitive(not self.notbranch)
1117
756
    
1118
757
    def refresh_left(self):
1119
758
        """ Refresh the bookmark list. """
1129
768
        bookmarks = self.pref.get_bookmarks()
1130
769
 
1131
770
        # Add them to the TreeStore
1132
 
        titer = treestore.append(None, [_i18n('Bookmarks'), None])
 
771
        titer = treestore.append(None, [_('Bookmarks'), None])
 
772
        for item in bookmarks:
 
773
            title = self.pref.get_bookmark_title(item)
 
774
            treestore.append(titer, [title, item])
1133
775
 
1134
 
        # Get titles and sort by title
1135
 
        bookmarks = [[self.pref.get_bookmark_title(item), item] for item in bookmarks]
1136
 
        bookmarks.sort()
1137
 
        for title_item in bookmarks:
1138
 
            treestore.append(titer, title_item)
1139
 
        
1140
776
        # Add the TreeStore to the TreeView
1141
777
        self.treeview_left.set_model(treestore)
1142
778
 
1145
781
 
1146
782
    def refresh_right(self, path=None):
1147
783
        """ Refresh the file list. """
1148
 
        if not self.remote:
1149
 
            # We're local
1150
 
            from bzrlib.workingtree import WorkingTree
1151
 
    
1152
 
            if path is None:
1153
 
                path = self.get_path()
1154
 
    
1155
 
            # A workaround for double-clicking Bookmarks
1156
 
            if not os.path.exists(path):
1157
 
                return
1158
 
    
1159
 
            # Get ListStore and clear it
1160
 
            liststore = self.treeview_right.get_model()
1161
 
            liststore.clear()
1162
 
            
1163
 
            # Show Status column
1164
 
            self._tvcolumn_status.set_visible(True)
1165
 
    
1166
 
            dirs = []
1167
 
            files = []
1168
 
    
1169
 
            # Fill the appropriate lists
1170
 
            dotted_files = self.pref.get_preference('dotted_files', 'bool')
1171
 
            ignored_files = self.pref.get_preference('ignored_files', 'bool')
1172
 
 
1173
 
            for item in os.listdir(path):
1174
 
                if not dotted_files and item[0] == '.':
1175
 
                    continue
1176
 
                if os.path.isdir(path + os.sep + item):
1177
 
                    dirs.append(item)
1178
 
                else:
1179
 
                    files.append(item)
1180
 
            
1181
 
            # Try to open the working tree
1182
 
            notbranch = False
1183
 
            try:
1184
 
                tree1 = WorkingTree.open_containing(path)[0]
1185
 
            except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
1186
 
                notbranch = True
1187
 
            
 
784
        from bzrlib.workingtree import WorkingTree
 
785
 
 
786
        if path is None:
 
787
            path = self.get_path()
 
788
 
 
789
        # A workaround for double-clicking Bookmarks
 
790
        if not os.path.exists(path):
 
791
            return
 
792
 
 
793
        # Get ListStore and clear it
 
794
        liststore = self.treeview_right.get_model()
 
795
        liststore.clear()
 
796
 
 
797
        dirs = []
 
798
        files = []
 
799
 
 
800
        # Fill the appropriate lists
 
801
        dotted_files = self.pref.get_preference('dotted_files', 'bool')
 
802
        for item in os.listdir(path):
 
803
            if not dotted_files and item[0] == '.':
 
804
                continue
 
805
            if os.path.isdir(path + os.sep + item):
 
806
                dirs.append(item)
 
807
            else:
 
808
                files.append(item)
 
809
 
 
810
        # Sort'em
 
811
        dirs.sort()
 
812
        files.sort()
 
813
 
 
814
        # add updir link to dirs
 
815
        self._add_updir_to_dirlist(dirs, path)
 
816
 
 
817
        # Try to open the working tree
 
818
        notbranch = False
 
819
        try:
 
820
            tree1 = WorkingTree.open_containing(path)[0]
 
821
        except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
 
822
            notbranch = True
 
823
        
 
824
        if not notbranch:
 
825
            branch = tree1.branch
 
826
            tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
 
827
        
 
828
            delta = tree1.changes_from(tree2, want_unchanged=True)
 
829
            
 
830
        # Add'em to the ListStore
 
831
        for item in dirs:
 
832
            liststore.append([gtk.STOCK_DIRECTORY, item, ''])
 
833
        for item in files:
 
834
            status = 'unknown'
1188
835
            if not notbranch:
1189
 
                branch = tree1.branch
1190
 
                tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
1191
 
            
1192
 
                delta = tree1.changes_from(tree2, want_unchanged=True)
1193
 
                
1194
 
            # Add'em to the ListStore
1195
 
            for item in dirs:
1196
 
                try:
1197
 
                    statinfo = os.stat(self.path + os.sep + item)
1198
 
                except OSError, e:
1199
 
                    if e.errno in self.acceptable_errors:
1200
 
                        continue
1201
 
                    else:
1202
 
                        raise
1203
 
                liststore.append([gtk.STOCK_DIRECTORY,
1204
 
                                  True,
1205
 
                                  item,
1206
 
                                  '',
1207
 
                                  '',
1208
 
                                  "<DIR>",
1209
 
                                  "<DIR>",
1210
 
                                  statinfo.st_mtime,
1211
 
                                  self._format_date(statinfo.st_mtime),
1212
 
                                  ''])
1213
 
            for item in files:
1214
 
                status = 'unknown'
1215
 
                fileid = ''
1216
 
                if not notbranch:
1217
 
                    filename = tree1.relpath(path + os.sep + item)
1218
 
                    
1219
 
                    try:
1220
 
                        self.wt.lock_read()
1221
 
                        
1222
 
                        for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1223
 
                            if rpathnew == filename:
1224
 
                                status = 'renamed'
1225
 
                                fileid = id
1226
 
                        for rpath, id, kind in delta.added:
1227
 
                            if rpath == filename:
1228
 
                                status = 'added'
1229
 
                                fileid = id
1230
 
                        for rpath, id, kind in delta.removed:
1231
 
                            if rpath == filename:
1232
 
                                status = 'removed'
1233
 
                                fileid = id
1234
 
                        for rpath, id, kind, text_modified, meta_modified in delta.modified:
1235
 
                            if rpath == filename:
1236
 
                                status = 'modified'
1237
 
                                fileid = id
1238
 
                        for rpath, id, kind in delta.unchanged:
1239
 
                            if rpath == filename:
1240
 
                                status = 'unchanged'
1241
 
                                fileid = id
1242
 
                        for rpath, file_class, kind, id, entry in self.wt.list_files():
1243
 
                            if rpath == filename and file_class == 'I':
1244
 
                                status = 'ignored'
1245
 
                    finally:
1246
 
                        self.wt.unlock()
1247
 
                
1248
 
                if status == 'renamed':
1249
 
                    st = _i18n('renamed')
1250
 
                elif status == 'removed':
1251
 
                    st = _i18n('removed')
1252
 
                elif status == 'added':
1253
 
                    st = _i18n('added')
1254
 
                elif status == 'modified':
1255
 
                    st = _i18n('modified')
1256
 
                elif status == 'unchanged':
1257
 
                    st = _i18n('unchanged')
1258
 
                elif status == 'ignored':
1259
 
                    st = _i18n('ignored')
1260
 
                    if not ignored_files:
1261
 
                        continue
1262
 
                else:
1263
 
                    st = _i18n('unknown')
1264
 
                
1265
 
                try:
1266
 
                    statinfo = os.stat(self.path + os.sep + item)
1267
 
                except OSError, e:
1268
 
                    if e.errno in self.acceptable_errors:
1269
 
                        continue
1270
 
                    else:
1271
 
                        raise
1272
 
                liststore.append([gtk.STOCK_FILE,
1273
 
                                  False,
1274
 
                                  item,
1275
 
                                  st,
1276
 
                                  status,
1277
 
                                  str(statinfo.st_size),
1278
 
                                  self._format_size(statinfo.st_size),
1279
 
                                  statinfo.st_mtime,
1280
 
                                  self._format_date(statinfo.st_mtime),
1281
 
                                  fileid])
1282
 
        else:
1283
 
            # We're remote
1284
 
            
1285
 
            # Get ListStore and clear it
1286
 
            liststore = self.treeview_right.get_model()
1287
 
            liststore.clear()
1288
 
            
1289
 
            # Hide Status column
1290
 
            self._tvcolumn_status.set_visible(False)
1291
 
            
1292
 
            dirs = []
1293
 
            files = []
1294
 
            
1295
 
            self._show_stock_image(gtk.STOCK_REFRESH)
1296
 
            
1297
 
            for (name, type) in self.remote_entries:
1298
 
                if type.kind == 'directory':
1299
 
                    dirs.append(type)
1300
 
                elif type.kind == 'file':
1301
 
                    files.append(type)
1302
 
            
1303
 
            class HistoryCache:
1304
 
                """ Cache based on revision history. """
1305
 
                def __init__(self, history):
1306
 
                    self._history = history
1307
 
                
1308
 
                def _lookup_revision(self, revid):
1309
 
                    for r in self._history:
1310
 
                        if r.revision_id == revid:
1311
 
                            return r
1312
 
                    rev = repo.get_revision(revid)
1313
 
                    self._history.append(rev)
1314
 
                    return rev
1315
 
            
1316
 
            repo = self.remote_branch.repository
1317
 
            
1318
 
            revhistory = self.remote_branch.revision_history()
1319
 
            try:
1320
 
                revs = repo.get_revisions(revhistory)
1321
 
                cache = HistoryCache(revs)
1322
 
            except bzrerrors.InvalidHttpResponse:
1323
 
                # Fallback to dummy algorithm, because of LP: #115209
1324
 
                cache = HistoryCache([])
1325
 
            
1326
 
            for item in dirs:
1327
 
                if item.parent_id == self.remote_parent:
1328
 
                    rev = cache._lookup_revision(item.revision)
1329
 
                    liststore.append([ gtk.STOCK_DIRECTORY,
1330
 
                                       True,
1331
 
                                       item.name,
1332
 
                                       '',
1333
 
                                       '',
1334
 
                                       "<DIR>",
1335
 
                                       "<DIR>",
1336
 
                                       rev.timestamp,
1337
 
                                       self._format_date(rev.timestamp),
1338
 
                                       ''
1339
 
                                   ])
1340
 
                while gtk.events_pending():
1341
 
                    gtk.main_iteration()
1342
 
            
1343
 
            for item in files:
1344
 
                if item.parent_id == self.remote_parent:
1345
 
                    rev = cache._lookup_revision(item.revision)
1346
 
                    liststore.append([ gtk.STOCK_FILE,
1347
 
                                       False,
1348
 
                                       item.name,
1349
 
                                       '',
1350
 
                                       '',
1351
 
                                       str(item.text_size),
1352
 
                                       self._format_size(item.text_size),
1353
 
                                       rev.timestamp,
1354
 
                                       self._format_date(rev.timestamp),
1355
 
                                       item.file_id
1356
 
                                   ])
1357
 
                while gtk.events_pending():
1358
 
                    gtk.main_iteration()
1359
 
            
1360
 
            self.image_location_error.destroy()
1361
 
 
1362
 
        # Columns should auto-size
1363
 
        self.treeview_right.columns_autosize()
 
836
                filename = tree1.relpath(path + os.sep + item)
 
837
                
 
838
                for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
 
839
                    if rpathnew == filename:
 
840
                        status = 'renamed'
 
841
                for rpath, id, kind in delta.added:
 
842
                    if rpath == filename:
 
843
                        status = 'added'                
 
844
                for rpath, id, kind in delta.removed:
 
845
                    if rpath == filename:
 
846
                        status = 'removed'
 
847
                for rpath, id, kind, text_modified, meta_modified in delta.modified:
 
848
                    if rpath == filename:
 
849
                        status = 'modified'
 
850
                for rpath, id, kind in delta.unchanged:
 
851
                    if rpath == filename:
 
852
                        status = 'unchanged'
 
853
                for rpath, file_class, kind, id, entry in self.wt.list_files():
 
854
                    if rpath == filename and file_class == 'I':
 
855
                        status = 'ignored'
 
856
            
 
857
            #try:
 
858
            #    status = fileops.status(path + os.sep + item)
 
859
            #except errors.PermissionDenied:
 
860
            #    continue
 
861
 
 
862
            if status == 'renamed':
 
863
                st = _('renamed')
 
864
            elif status == 'removed':
 
865
                st = _('removed')
 
866
            elif status == 'added':
 
867
                st = _('added')
 
868
            elif status == 'modified':
 
869
                st = _('modified')
 
870
            elif status == 'unchanged':
 
871
                st = _('unchanged')
 
872
            elif status == 'ignored':
 
873
                st = _('ignored')
 
874
            else:
 
875
                st = _('unknown')
 
876
            liststore.append([gtk.STOCK_FILE, item, st])
 
877
 
 
878
        # Add the ListStore to the TreeView
 
879
        self.treeview_right.set_model(liststore)
1364
880
        
1365
881
        # Set sensitivity
1366
882
        self.set_sensitivity()
1374
890
            if sys.platform == 'win32':
1375
891
                print "pyWin32 modules needed to run Olive on Win32."
1376
892
                sys.exit(1)
 
893
            else:
 
894
                pass
1377
895
        
1378
896
        driveletters = []
1379
897
        for drive in string.ascii_uppercase:
1380
 
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED or\
1381
 
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOTE:
 
898
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
1382
899
                driveletters.append(drive+':')
1383
900
        return driveletters
1384
901
    
1410
927
            changes = True
1411
928
        
1412
929
        return changes
1413
 
    
1414
 
    def _sort_filelist_callback(self, model, iter1, iter2, data):
1415
 
        """ The sort callback for the file list, return values:
1416
 
        -1: iter1 < iter2
1417
 
        0: iter1 = iter2
1418
 
        1: iter1 > iter2
1419
 
        """
1420
 
        name1 = model.get_value(iter1, 2)
1421
 
        name2 = model.get_value(iter2, 2)
1422
 
        
1423
 
        if model.get_value(iter1, 1):
1424
 
            # item1 is a directory
1425
 
            if not model.get_value(iter2, 1):
1426
 
                # item2 isn't
1427
 
                return -1
1428
 
            else:
1429
 
                # both of them are directories, we compare their names
1430
 
                if name1 < name2:
1431
 
                    return -1
1432
 
                elif name1 == name2:
1433
 
                    return 0
1434
 
                else:
1435
 
                    return 1
1436
 
        else:
1437
 
            # item1 is not a directory
1438
 
            if model.get_value(iter2, 1):
1439
 
                # item2 is
1440
 
                return 1
1441
 
            else:
1442
 
                # both of them are files, compare them
1443
 
                if name1 < name2:
1444
 
                    return -1
1445
 
                elif name1 == name2:
1446
 
                    return 0
1447
 
                else:
1448
 
                    return 1
1449
 
    
1450
 
    def _format_size(self, size):
1451
 
        """ Format size to a human readable format. """
1452
 
        if size < 1000:
1453
 
            return "%d[B]" % (size,)
1454
 
        size = size / 1000.0
1455
 
        
1456
 
        for metric in ["kB","MB","GB","TB"]:
1457
 
            if size < 1000:
1458
 
                break
1459
 
            size = size / 1000.0
1460
 
        return "%.1f[%s]" % (size,metric) 
1461
 
    
1462
 
    def _format_date(self, timestamp):
1463
 
        """ Format the time (given in secs) to a human readable format. """
1464
 
        return time.ctime(timestamp)
1465
 
    
1466
 
    def _is_remote_dir(self, location):
1467
 
        """ Determine whether the given location is a directory or not. """
1468
 
        if not self.remote:
1469
 
            # We're in local mode
1470
 
            return False
1471
 
        else:
1472
 
            branch, path = Branch.open_containing(location)
1473
 
            for (name, type) in self.remote_entries:
1474
 
                if name == path and type.kind == 'directory':
1475
 
                    # We got it
1476
 
                    return True
1477
 
            # Either it's not a directory or not in the inventory
1478
 
            return False
1479
 
    
1480
 
    def _show_stock_image(self, stock_id):
1481
 
        """ Show a stock image next to the location entry. """
1482
 
        self.image_location_error.destroy()
1483
 
        self.image_location_error = gtk.image_new_from_stock(stock_id, gtk.ICON_SIZE_BUTTON)
1484
 
        self.hbox_location.pack_start(self.image_location_error, False, False, 0)
1485
 
        if sys.platform == 'win32':
1486
 
            self.hbox_location.reorder_child(self.image_location_error, 2)
1487
 
        else:
1488
 
            self.hbox_location.reorder_child(self.image_location_error, 1)
1489
 
        self.image_location_error.show()
1490
 
        while gtk.events_pending():
1491
 
            gtk.main_iteration()
1492
930
 
1493
931
import ConfigParser
1494
932
 
1495
933
class Preferences:
1496
934
    """ A class which handles Olive's preferences. """
1497
 
    def __init__(self, path=None):
 
935
    def __init__(self):
1498
936
        """ Initialize the Preferences class. """
1499
937
        # Some default options
1500
938
        self.defaults = { 'strict_commit' : False,
1501
939
                          'dotted_files'  : False,
1502
 
                          'ignored_files' : True,
1503
940
                          'window_width'  : 700,
1504
941
                          'window_height' : 400,
1505
942
                          'window_x'      : 40,
1508
945
 
1509
946
        # Create a config parser object
1510
947
        self.config = ConfigParser.RawConfigParser()
1511
 
 
1512
 
        # Set filename
1513
 
        if path is None:
1514
 
            if sys.platform == 'win32':
1515
 
                # Windows - no dotted files
1516
 
                self._filename = os.path.expanduser('~/olive.conf')
1517
 
            else:
1518
 
                self._filename = os.path.expanduser('~/.olive.conf')
1519
 
        else:
1520
 
            self._filename = path
1521
948
        
1522
949
        # Load the configuration
1523
950
        self.read()
1542
969
        """ Just read the configuration. """
1543
970
        # Re-initialize the config parser object to avoid some bugs
1544
971
        self.config = ConfigParser.RawConfigParser()
1545
 
        self.config.read([self._filename])
 
972
        if sys.platform == 'win32':
 
973
            # Windows - no dotted files
 
974
            self.config.read([os.path.expanduser('~/olive.conf')])
 
975
        else:
 
976
            self.config.read([os.path.expanduser('~/.olive.conf')])
1546
977
    
1547
978
    def write(self):
1548
979
        """ Write the configuration to the appropriate files. """
1549
 
        fp = open(self._filename, 'w')
1550
 
        self.config.write(fp)
1551
 
        fp.close()
 
980
        if sys.platform == 'win32':
 
981
            # Windows - no dotted files
 
982
            fp = open(os.path.expanduser('~/olive.conf'), 'w')
 
983
            self.config.write(fp)
 
984
            fp.close()
 
985
        else:
 
986
            fp = open(os.path.expanduser('~/.olive.conf'), 'w')
 
987
            self.config.write(fp)
 
988
            fp.close()
1552
989
 
1553
990
    def get_bookmarks(self):
1554
991
        """ Return the list of bookmarks. """
1617
1054
                return self._get_default(option)
1618
1055
            except KeyError:
1619
1056
                return None
 
1057