/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/frontend/gtk/__init__.py

  • Committer: Szilveszter Farkas (Phanatic)
  • Date: 2006-09-27 19:11:59 UTC
  • mfrom: (0.8.90 merge)
  • mto: (93.1.1 win32.bialix)
  • mto: This revision was merged to the branch mainline in revision 103.
  • Revision ID: Szilveszter.Farkas@gmail.com-20060927191159-cc4e54f613575779
Merge all changes. Release 0.11.0.

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