/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: 2006-09-13 20:19:31 UTC
  • mfrom: (0.8.79 main)
  • mto: (0.8.83 merge)
  • mto: This revision was merged to the branch mainline in revision 83.
  • Revision ID: jelmer@samba.org-20060913201931-23adba246d4d6529
Merge main branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
import ConfigParser
18
 
import os
19
 
import os.path
20
 
import sys
21
 
 
22
 
try:
23
 
    import pygtk
24
 
    pygtk.require("2.0")
25
 
except:
26
 
    pass
27
 
try:
28
 
    import gtk
29
 
    import gtk.gdk
30
 
    import gtk.glade
31
 
except:
32
 
    sys.exit(1)
33
 
 
34
 
from handler import OliveHandler
35
 
import bzrlib.errors as errors
36
 
 
37
 
# Olive GTK UI version
38
 
__version__ = '0.10.0'
39
 
 
40
 
class OliveGtk:
41
 
    """ The main Olive GTK frontend class. This is called when launching the
42
 
    program. """
43
 
    
44
 
    def __init__(self):
45
 
        # Load the glade file
46
 
        if sys.platform == 'win32':
47
 
            self.gladefile = os.path.dirname(sys.executable) + "/share/olive/olive.glade"
48
 
        else:
49
 
            self.gladefile = "/usr/share/olive/olive.glade"
50
 
 
51
 
        if not os.path.exists(self.gladefile):
52
 
            # Load from current directory if not installed
53
 
            self.gladefile = "olive.glade"
54
 
            # Check again
55
 
            if not os.path.exists(self.gladefile):
56
 
                # Fail
57
 
                print _('Glade file cannot be found.')
58
 
                sys.exit(1)
59
 
 
60
 
        self.toplevel = gtk.glade.XML(self.gladefile, 'window_main', 'olive-gtk')
61
 
        
62
 
        self.window = self.toplevel.get_widget('window_main')
63
 
        
64
 
        self.pref = OlivePreferences()
65
 
        self.comm = OliveCommunicator(self.toplevel, self.pref)
66
 
        handler = OliveHandler(self.gladefile, self.comm)
67
 
        
68
 
        # Dictionary for signal_autoconnect
69
 
        dic = { "on_window_main_destroy": gtk.main_quit,
70
 
                "on_window_main_delete_event": handler.on_window_main_delete_event,
71
 
                "on_quit_activate": handler.on_window_main_delete_event,
72
 
                "on_about_activate": handler.on_about_activate,
73
 
                "on_menuitem_add_files_activate": handler.on_menuitem_add_files_activate,
74
 
                "on_menuitem_remove_file_activate": handler.on_menuitem_remove_file_activate,
75
 
                "on_menuitem_file_make_directory_activate": handler.on_menuitem_file_make_directory_activate,
76
 
                "on_menuitem_file_move_activate": handler.on_menuitem_file_move_activate,
77
 
                "on_menuitem_file_rename_activate": handler.on_menuitem_file_rename_activate,
78
 
                "on_menuitem_view_show_hidden_files_activate": handler.on_menuitem_view_show_hidden_files_activate,
79
 
                "on_menuitem_view_refresh_activate": handler.on_menuitem_view_refresh_activate,
80
 
                "on_menuitem_branch_initialize_activate": handler.on_menuitem_branch_initialize_activate,
81
 
                "on_menuitem_branch_get_activate": handler.on_menuitem_branch_get_activate,
82
 
                "on_menuitem_branch_checkout_activate": handler.on_menuitem_branch_checkout_activate,
83
 
                "on_menuitem_branch_commit_activate": handler.on_menuitem_branch_commit_activate,
84
 
                "on_menuitem_branch_push_activate": handler.on_menuitem_branch_push_activate,
85
 
                "on_menuitem_branch_pull_activate": handler.on_menuitem_branch_pull_activate,
86
 
                "on_menuitem_branch_status_activate": handler.on_menuitem_branch_status_activate,
87
 
                "on_menuitem_branch_missing_revisions_activate": handler.on_menuitem_branch_missing_revisions_activate,
88
 
                "on_menuitem_stats_diff_activate": handler.on_menuitem_stats_diff_activate,
89
 
                "on_menuitem_stats_log_activate": handler.on_menuitem_stats_log_activate,
90
 
                "on_menuitem_stats_infos_activate": handler.on_menuitem_stats_infos_activate,
91
 
                "on_toolbutton_refresh_clicked": handler.on_menuitem_view_refresh_activate,
92
 
                "on_toolbutton_log_clicked": handler.on_menuitem_stats_log_activate,
93
 
                #"on_menutoolbutton_diff_clicked": handler.on_menuitem_stats_diff_activate,
94
 
                "on_toolbutton_diff_clicked": handler.on_menuitem_stats_diff_activate,
95
 
                "on_toolbutton_commit_clicked": handler.on_menuitem_branch_commit_activate,
96
 
                "on_toolbutton_pull_clicked": handler.on_menuitem_branch_pull_activate,
97
 
                "on_toolbutton_push_clicked": handler.on_menuitem_branch_push_activate,
98
 
                "on_treeview_right_button_press_event": handler.on_treeview_right_button_press_event,
99
 
                "on_treeview_right_row_activated": handler.on_treeview_right_row_activated,
100
 
                "on_treeview_left_button_press_event": handler.on_treeview_left_button_press_event,
101
 
                "on_treeview_left_row_activated": handler.on_treeview_left_row_activated }
102
 
        
103
 
        # Connect the signals to the handlers
104
 
        self.toplevel.signal_autoconnect(dic)
105
 
        
106
 
        # Apply window size and position
107
 
        width = self.pref.get_preference('window_width', 'int')
108
 
        height = self.pref.get_preference('window_height', 'int')
109
 
        self.window.resize(width, height)
110
 
        x = self.pref.get_preference('window_x', 'int')
111
 
        y = self.pref.get_preference('window_y', 'int')
112
 
        self.window.move(x, y)
113
 
        # Apply paned position
114
 
        pos = self.pref.get_preference('paned_position', 'int')
115
 
        self.comm.hpaned_main.set_position(pos)
116
 
        
117
 
        # Apply menu to the toolbutton
118
 
        #menubutton = self.toplevel.get_widget('menutoolbutton_diff')
119
 
        #menubutton.set_menu(handler.menu.toolbar_diff)
120
 
        
121
 
        # Now we can show the window
122
 
        self.window.show_all()
123
 
        
124
 
        # Load default data into the panels
125
 
        self.treeview_left = self.toplevel.get_widget('treeview_left')
126
 
        self.treeview_right = self.toplevel.get_widget('treeview_right')
127
 
        self._load_left()
128
 
        self._load_right()
129
 
 
130
 
        # Apply menu state
131
 
        self.comm.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
132
 
        
133
 
    def _load_left(self):
134
 
        """ Load data into the left panel. (Bookmarks) """
135
 
        # set cursor to busy
136
 
        self.comm.set_busy(self.treeview_left)
137
 
        
138
 
        # Create TreeStore
139
 
        treestore = gtk.TreeStore(str, str)
140
 
        
141
 
        # Get bookmarks
142
 
        bookmarks = self.comm.pref.get_bookmarks()
143
 
        
144
 
        # Add them to the TreeStore
145
 
        titer = treestore.append(None, [_('Bookmarks'), None])
146
 
        for item in bookmarks:
147
 
            title = self.comm.pref.get_bookmark_title(item)
148
 
            treestore.append(titer, [title, item])
149
 
        
150
 
        # Create the column and add it to the TreeView
151
 
        self.treeview_left.set_model(treestore)
152
 
        tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
153
 
        self.treeview_left.append_column(tvcolumn_bookmark)
154
 
        
155
 
        # Set up the cells
156
 
        cell = gtk.CellRendererText()
157
 
        tvcolumn_bookmark.pack_start(cell, True)
158
 
        tvcolumn_bookmark.add_attribute(cell, 'text', 0)
159
 
        
160
 
        # Expand the tree
161
 
        self.treeview_left.expand_all()
162
 
        
163
 
        self.comm.set_busy(self.treeview_left, False)
164
 
        
165
 
    def _load_right(self):
166
 
        """ Load data into the right panel. (Filelist) """
167
 
        # set cursor to busy
168
 
        self.comm.set_busy(self.treeview_right)
169
 
        
170
 
        # Create ListStore
171
 
        liststore = gtk.ListStore(str, str, str)
172
 
        
173
 
        dirs = ['..']
174
 
        files = []
175
 
        
176
 
        # Fill the appropriate lists
177
 
        path = self.comm.get_path()
178
 
        dotted_files = self.pref.get_preference('dotted_files', 'bool')
179
 
        for item in os.listdir(path):
180
 
            if not dotted_files and item[0] == '.':
181
 
                continue
182
 
            if os.path.isdir(path + '/' + item):
183
 
                dirs.append(item)
184
 
            else:
185
 
                files.append(item)
186
 
            
187
 
        # Sort'em
188
 
        dirs.sort()
189
 
        files.sort()
190
 
        
191
 
        # Add'em to the ListStore
192
 
        for item in dirs:    
193
 
            liststore.append([gtk.STOCK_DIRECTORY, item, ''])
194
 
        for item in files:
195
 
            try:
196
 
                status = check_status(path + '/' + item)
197
 
            except errors.PermissionDenied:
198
 
                continue
199
 
            
200
 
            if status == 'renamed':
201
 
                st = _('renamed')
202
 
            elif status == 'removed':
203
 
                st = _('removed')
204
 
            elif status == 'added':
205
 
                st = _('added')
206
 
            elif status == 'modified':
207
 
                st = _('modified')
208
 
            elif status == 'unchanged':
209
 
                st = _('unchanged')
210
 
            else:
211
 
                st = _('unknown')
212
 
            liststore.append([gtk.STOCK_FILE, item, st])
213
 
        
214
 
        # Create the columns and add them to the TreeView
215
 
        self.treeview_right.set_model(liststore)
216
 
        tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
217
 
        tvcolumn_status = gtk.TreeViewColumn(_('Status'))
218
 
        self.treeview_right.append_column(tvcolumn_filename)
219
 
        self.treeview_right.append_column(tvcolumn_status)
220
 
        
221
 
        # Set up the cells
222
 
        cellpb = gtk.CellRendererPixbuf()
223
 
        cell = gtk.CellRendererText()
224
 
        tvcolumn_filename.pack_start(cellpb, False)
225
 
        tvcolumn_filename.pack_start(cell, True)
226
 
        tvcolumn_filename.set_attributes(cellpb, stock_id=0)
227
 
        tvcolumn_filename.add_attribute(cell, 'text', 1)
228
 
        tvcolumn_status.pack_start(cell, True)
229
 
        tvcolumn_status.add_attribute(cell, 'text', 2)
230
 
        
231
 
        # Check if current directory is versioned
232
 
        try:
233
 
            from bzrlib.branch import Branch
234
 
            Branch.open_containing(self.comm.get_path())
235
 
            # Activate some items
236
 
            self.comm.menuitem_branch_init.set_sensitive(False)
237
 
            self.comm.menuitem_branch_get.set_sensitive(True)
238
 
            self.comm.menuitem_branch_checkout.set_sensitive(True)
239
 
            self.comm.menuitem_branch_pull.set_sensitive(True)
240
 
            self.comm.menuitem_branch_push.set_sensitive(True)
241
 
            self.comm.menuitem_branch_commit.set_sensitive(True)
242
 
            self.comm.menuitem_branch_status.set_sensitive(True)
243
 
            self.comm.menuitem_branch_missing.set_sensitive(True)
244
 
            self.comm.menuitem_stats.set_sensitive(True)
245
 
            self.comm.menuitem_add_files.set_sensitive(True)
246
 
            self.comm.menuitem_remove_files.set_sensitive(True)
247
 
            self.comm.menuitem_file_make_directory.set_sensitive(True)
248
 
            self.comm.menuitem_file_rename.set_sensitive(True)
249
 
            self.comm.menuitem_file_move.set_sensitive(True)
250
 
            #self.comm.menutoolbutton_diff.set_sensitive(True)
251
 
            self.comm.toolbutton_diff.set_sensitive(True)
252
 
            self.comm.toolbutton_log.set_sensitive(True)
253
 
            self.comm.toolbutton_commit.set_sensitive(True)
254
 
            self.comm.toolbutton_pull.set_sensitive(True)
255
 
            self.comm.toolbutton_push.set_sensitive(True)
256
 
        except errors.NotBranchError:
257
 
            # Deactivate some items
258
 
            self.comm.menuitem_branch_init.set_sensitive(True)
259
 
            self.comm.menuitem_branch_get.set_sensitive(False)
260
 
            self.comm.menuitem_branch_checkout.set_sensitive(False)
261
 
            self.comm.menuitem_branch_pull.set_sensitive(False)
262
 
            self.comm.menuitem_branch_push.set_sensitive(False)
263
 
            self.comm.menuitem_branch_commit.set_sensitive(False)
264
 
            self.comm.menuitem_branch_status.set_sensitive(False)
265
 
            self.comm.menuitem_branch_missing.set_sensitive(False)
266
 
            self.comm.menuitem_stats.set_sensitive(False)
267
 
            self.comm.menuitem_add_files.set_sensitive(False)
268
 
            self.comm.menuitem_remove_files.set_sensitive(False)
269
 
            self.comm.menuitem_file_make_directory.set_sensitive(False)
270
 
            self.comm.menuitem_file_rename.set_sensitive(False)
271
 
            self.comm.menuitem_file_move.set_sensitive(False)
272
 
            #self.comm.menutoolbutton_diff.set_sensitive(False)
273
 
            self.comm.toolbutton_diff.set_sensitive(False)
274
 
            self.comm.toolbutton_log.set_sensitive(False)
275
 
            self.comm.toolbutton_commit.set_sensitive(False)
276
 
            self.comm.toolbutton_pull.set_sensitive(False)
277
 
            self.comm.toolbutton_push.set_sensitive(False)
278
 
    
279
 
        # set cursor to default
280
 
        self.comm.set_busy(self.treeview_right, False)
281
 
 
282
 
class OliveCommunicator:
283
 
    """ This class is responsible for the communication between the different
284
 
    modules. """
285
 
    def __init__(self, toplevel, pref):
286
 
        # Get glade main component
287
 
        self.toplevel = toplevel
288
 
        # Preferences object
289
 
        self.pref = pref
290
 
        # Default path
291
 
        self._path = os.getcwd()
292
 
        
293
 
        # Initialize the statusbar
294
 
        self.statusbar = self.toplevel.get_widget('statusbar')
295
 
        self.context_id = self.statusbar.get_context_id('olive')
296
 
        
297
 
        # Get the main window
298
 
        self.window_main = self.toplevel.get_widget('window_main')
299
 
        # Get the HPaned
300
 
        self.hpaned_main = self.toplevel.get_widget('hpaned_main')
301
 
        # Get the TreeViews
302
 
        self.treeview_left = self.toplevel.get_widget('treeview_left')
303
 
        self.treeview_right = self.toplevel.get_widget('treeview_right')
304
 
        # Get some important menu items
305
 
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
306
 
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
307
 
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
308
 
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
309
 
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
310
 
        self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
311
 
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
312
 
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
313
 
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
314
 
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
315
 
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
316
 
        self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
317
 
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
318
 
        self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
319
 
        self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
320
 
        self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
321
 
        self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
322
 
        self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
323
 
        # Get some toolbuttons
324
 
        #self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
325
 
        self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
326
 
        self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
327
 
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
328
 
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
329
 
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
330
 
    
331
 
    def set_path(self, path):
332
 
        """ Set the current path while browsing the directories. """
333
 
        self._path = path
334
 
    
335
 
    def get_path(self):
336
 
        """ Get the current path. """
337
 
        return self._path
338
 
    
339
 
    def get_selected_right(self):
340
 
        """ Get the selected filename. """
341
 
        treeselection = self.treeview_right.get_selection()
342
 
        (model, iter) = treeselection.get_selected()
343
 
        
344
 
        if iter is None:
345
 
            return None
346
 
        else:
347
 
            return model.get_value(iter, 1)
348
 
    
349
 
    def get_selected_left(self):
350
 
        """ Get the selected bookmark. """
351
 
        treeselection = self.treeview_left.get_selection()
352
 
        (model, iter) = treeselection.get_selected()
353
 
        
354
 
        if iter is None:
355
 
            return None
356
 
        else:
357
 
            return model.get_value(iter, 1)
358
 
 
359
 
    def set_statusbar(self, message):
360
 
        """ Set the statusbar message. """
361
 
        self.statusbar.push(self.context_id, message)
362
 
    
363
 
    def clear_statusbar(self):
364
 
        """ Clean the last message from the statusbar. """
365
 
        self.statusbar.pop(self.context_id)
366
 
    
367
 
    def refresh_left(self):
368
 
        """ Refresh the bookmark list. """
369
 
        # set cursor to busy
370
 
        self.set_busy(self.treeview_left)
371
 
        
372
 
        # Get TreeStore and clear it
373
 
        treestore = self.treeview_left.get_model()
374
 
        treestore.clear()
375
 
        
376
 
        # Get bookmarks
377
 
        bookmarks = self.pref.get_bookmarks()
378
 
        
379
 
        # Add them to the TreeStore
380
 
        titer = treestore.append(None, [_('Bookmarks'), None])
381
 
        for item in bookmarks:
382
 
            title = self.pref.get_bookmark_title(item)
383
 
            treestore.append(titer, [title, item])
384
 
        
385
 
        # Add the TreeStore to the TreeView
386
 
        self.treeview_left.set_model(treestore)
387
 
        
388
 
        # Expand the tree
389
 
        self.treeview_left.expand_all()
390
 
        
391
 
        self.set_busy(self.treeview_left, False)
392
 
    
393
 
    def refresh_right(self, path=None):
394
 
        """ Refresh the file list. """
395
 
        self.set_busy(self.treeview_right)
396
 
        
397
 
        if path is None:
398
 
            path = self.get_path()
399
 
        
400
 
        # A workaround for double-clicking Bookmarks
401
 
        if not os.path.exists(path):
402
 
            self.set_busy(self.treeview_right, False)
403
 
            return
404
 
 
405
 
        # Get ListStore and clear it
406
 
        liststore = self.treeview_right.get_model()
407
 
        liststore.clear()
408
 
        
409
 
        dirs = ['..']
410
 
        files = []
411
 
        
412
 
        # Fill the appropriate lists
413
 
        dotted_files = self.pref.get_preference('dotted_files', 'bool')
414
 
        for item in os.listdir(path):
415
 
            if not dotted_files and item[0] == '.':
416
 
                continue
417
 
            if os.path.isdir(path + '/' + item):
418
 
                dirs.append(item)
419
 
            else:
420
 
                files.append(item)
421
 
            
422
 
        # Sort'em
423
 
        dirs.sort()
424
 
        files.sort()
425
 
        
426
 
        # Add'em to the ListStore
427
 
        for item in dirs:    
428
 
            liststore.append([gtk.STOCK_DIRECTORY, item, ''])
429
 
        for item in files:
430
 
            try:
431
 
                status = check_status(path + '/' + item)
432
 
            except errors.PermissionDenied:
433
 
                continue
434
 
            
435
 
            if status == 'renamed':
436
 
                st = _('renamed')
437
 
            elif status == 'removed':
438
 
                st = _('removed')
439
 
            elif status == 'added':
440
 
                st = _('added')
441
 
            elif status == 'modified':
442
 
                st = _('modified')
443
 
            elif status == 'unchanged':
444
 
                st = _('unchanged')
445
 
            else:
446
 
                st = _('unknown')
447
 
            liststore.append([gtk.STOCK_FILE, item, st])
448
 
        
449
 
        # Add the ListStore to the TreeView
450
 
        self.treeview_right.set_model(liststore)
451
 
        
452
 
        # Check if current directory is a branch
453
 
        try:
454
 
            from bzrlib.branch import Branch
455
 
            Branch.open_containing(self.get_path())
456
 
            # Activate some items
457
 
            self.menuitem_branch_init.set_sensitive(False)
458
 
            self.menuitem_branch_get.set_sensitive(True)
459
 
            self.menuitem_branch_checkout.set_sensitive(True)
460
 
            self.menuitem_branch_pull.set_sensitive(True)
461
 
            self.menuitem_branch_push.set_sensitive(True)
462
 
            self.menuitem_branch_commit.set_sensitive(True)
463
 
            self.menuitem_branch_status.set_sensitive(True)
464
 
            self.menuitem_branch_missing.set_sensitive(True)
465
 
            self.menuitem_stats.set_sensitive(True)
466
 
            self.menuitem_add_files.set_sensitive(True)
467
 
            self.menuitem_remove_files.set_sensitive(True)
468
 
            self.menuitem_file_make_directory.set_sensitive(True)
469
 
            self.menuitem_file_rename.set_sensitive(True)
470
 
            self.menuitem_file_move.set_sensitive(True)
471
 
            #self.menutoolbutton_diff.set_sensitive(True)
472
 
            self.toolbutton_diff.set_sensitive(True)
473
 
            self.toolbutton_log.set_sensitive(True)
474
 
            self.toolbutton_commit.set_sensitive(True)
475
 
            self.toolbutton_pull.set_sensitive(True)
476
 
            self.toolbutton_push.set_sensitive(True)
477
 
        except errors.NotBranchError:
478
 
            # Deactivate some items
479
 
            self.menuitem_branch_init.set_sensitive(True)
480
 
            self.menuitem_branch_get.set_sensitive(False)
481
 
            self.menuitem_branch_checkout.set_sensitive(False)
482
 
            self.menuitem_branch_pull.set_sensitive(False)
483
 
            self.menuitem_branch_push.set_sensitive(False)
484
 
            self.menuitem_branch_commit.set_sensitive(False)
485
 
            self.menuitem_branch_status.set_sensitive(False)
486
 
            self.menuitem_branch_missing.set_sensitive(False)
487
 
            self.menuitem_stats.set_sensitive(False)
488
 
            self.menuitem_add_files.set_sensitive(False)
489
 
            self.menuitem_remove_files.set_sensitive(False)
490
 
            self.menuitem_file_make_directory.set_sensitive(False)
491
 
            self.menuitem_file_rename.set_sensitive(False)
492
 
            self.menuitem_file_move.set_sensitive(False)
493
 
            #self.menutoolbutton_diff.set_sensitive(False)
494
 
            self.toolbutton_diff.set_sensitive(False)
495
 
            self.toolbutton_log.set_sensitive(False)
496
 
            self.toolbutton_commit.set_sensitive(False)
497
 
            self.toolbutton_pull.set_sensitive(False)
498
 
            self.toolbutton_push.set_sensitive(False)
499
 
        
500
 
        self.set_busy(self.treeview_right, False)
501
 
 
502
 
    def set_busy(self, widget, busy=True):
503
 
        if busy:
504
 
            widget.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
505
 
        else:
506
 
            widget.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
507
 
 
508
 
        gtk.main_iteration(0)
509
 
 
510
 
class OlivePreferences:
511
 
    """ A class which handles Olive's preferences. """
512
 
    def __init__(self):
513
 
        """ Initialize the Preferences class. """
514
 
        # Some default options
515
 
        self.defaults = { 'strict_commit' : False,
516
 
                          'dotted_files'  : False,
517
 
                          'window_width'  : 700,
518
 
                          'window_height' : 400,
519
 
                          'window_x'      : 40,
520
 
                          'window_y'      : 40,
521
 
                          'paned_position': 200 }
522
 
        
523
 
        # Create a config parser object
524
 
        self.config = ConfigParser.RawConfigParser()
525
 
        
526
 
        # Load the configuration
527
 
        if sys.platform == 'win32':
528
 
            # Windows - no dotted files
529
 
            self.config.read([os.path.expanduser('~/olive.conf')])
530
 
        else:
531
 
            self.config.read([os.path.expanduser('~/.olive.conf')])
532
 
        
533
 
    def _get_default(self, option):
534
 
        """ Get the default option for a preference. """
535
 
        try:
536
 
            ret = self.defaults[option]
537
 
        except KeyError:
538
 
            return None
539
 
        else:
540
 
            return ret
541
 
 
542
 
    def refresh(self):
543
 
        """ Refresh the configuration. """
544
 
        # First write out the changes
545
 
        self.write()
546
 
        # Then load the configuration again
547
 
        if sys.platform == 'win32':
548
 
            # Windows - no dotted files
549
 
            self.config.read([os.path.expanduser('~/olive.conf')])
550
 
        else:
551
 
            self.config.read([os.path.expanduser('~/.olive.conf')])
552
 
 
553
 
    def write(self):
554
 
        """ Write the configuration to the appropriate files. """
555
 
        if sys.platform == 'win32':
556
 
            # Windows - no dotted files
557
 
            fp = open(os.path.expanduser('~/olive.conf'), 'w')
558
 
            self.config.write(fp)
559
 
            fp.close()
560
 
        else:
561
 
            fp = open(os.path.expanduser('~/.olive.conf'), 'w')
562
 
            self.config.write(fp)
563
 
            fp.close()
564
 
 
565
 
    def get_preference(self, option, kind='str'):
566
 
        """ Get the value of the given option.
567
 
        
568
 
        :param kind: str/bool/int/float. default: str
569
 
        """
570
 
        if self.config.has_option('preferences', option):
571
 
            if kind == 'bool':
572
 
                return self.config.getboolean('preferences', option)
573
 
            elif kind == 'int':
574
 
                return self.config.getint('preferences', option)
575
 
            elif kind == 'float':
576
 
                return self.config.getfloat('preferences', option)
577
 
            else:
578
 
                return self.config.get('preferences', option)
579
 
        else:
580
 
            try:
581
 
                return self._get_default(option)
582
 
            except KeyError:
583
 
                return None
584
 
    
585
 
    def set_preference(self, option, value):
586
 
        """ Set the value of the given option. """
587
 
        if self.config.has_section('preferences'):
588
 
            self.config.set('preferences', option, value)
589
 
        else:
590
 
            self.config.add_section('preferences')
591
 
            self.config.set('preferences', option, value)
592
 
    
593
 
    def get_bookmarks(self):
594
 
        """ Return the list of bookmarks. """
595
 
        bookmarks = self.config.sections()
596
 
        if self.config.has_section('preferences'):
597
 
            bookmarks.remove('preferences')
598
 
        return bookmarks
599
 
 
600
 
    def add_bookmark(self, path):
601
 
        """ Add bookmark. """
602
 
        try:
603
 
            self.config.add_section(path)
604
 
        except ConfigParser.DuplicateSectionError:
605
 
            return False
606
 
        else:
607
 
            return True
608
 
 
609
 
    def get_bookmark_title(self, path):
610
 
        """ Get bookmark title. """
611
 
        try:
612
 
            ret = self.config.get(path, 'title')
613
 
        except ConfigParser.NoOptionError:
614
 
            ret = path
615
 
        
616
 
        return ret
617
 
    
618
 
    def set_bookmark_title(self, path, title):
619
 
        """ Set bookmark title. """
620
 
        self.config.set(path, 'title', title)
621
 
    
622
 
    def remove_bookmark(self, path):
623
 
        """ Remove bookmark. """
624
 
        return self.config.remove_section(path)
625
 
 
626
 
def check_status(filename):
627
 
    """ Get the status of a file.
628
 
    
629
 
    :param filename: the full path to the file
630
 
    
631
 
    :return: renamed | added | removed | modified | unchanged | unknown
632
 
    """
633
 
    import bzrlib
634
 
    from bzrlib.delta import compare_trees
635
 
    from bzrlib.workingtree import WorkingTree
636
 
    
637
 
    try:
638
 
        tree1 = WorkingTree.open_containing(filename)[0]
639
 
    except errors.NotBranchError:
640
 
        return 'unknown'
641
 
    
642
 
    branch = tree1.branch
643
 
    tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
644
 
    
645
 
    # find the relative path to the given file (needed for proper delta)
646
 
    wtpath = tree1.basedir
647
 
    fullpath = filename
648
 
    i = 0
649
 
    wtsplit = wtpath.split('/')
650
 
    fpsplit = fullpath.split('/')
651
 
    fpcopy = fullpath.split('/')
652
 
    for item in fpsplit:
653
 
        if i is not len(wtsplit):
654
 
            if item == wtsplit[i]:
655
 
                del fpcopy[0]
656
 
            i = i + 1
657
 
    rel = '/'.join(fpcopy)
658
 
    
659
 
    delta = tree1.changes_from(tree2,
660
 
                                   want_unchanged=True,
661
 
                                   specific_files=[rel])
662
 
    
663
 
    if len(delta.renamed):
664
 
        return 'renamed'
665
 
    elif len(delta.added):
666
 
        return 'added'
667
 
    elif len(delta.removed):
668
 
        return 'removed'
669
 
    elif len(delta.modified):
670
 
        return 'modified'
671
 
    elif len(delta.unchanged):
672
 
        return 'unchanged'
673
 
    else:
674
 
        return 'unknown'