/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-06 00:23:46 UTC
  • mto: (0.8.83 merge)
  • mto: This revision was merged to the branch mainline in revision 83.
  • Revision ID: jelmer@samba.org-20060906002346-73aa11b52d4d7b96
Load plugins on startup.

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'